Skip to content

Instantly share code, notes, and snippets.

@medardm
Last active April 17, 2025 09:50
Show Gist options
  • Save medardm/263b2c933186eb1a496fa743c756edc7 to your computer and use it in GitHub Desktop.
Save medardm/263b2c933186eb1a496fa743c756edc7 to your computer and use it in GitHub Desktop.
Wasp-lang: An example of splitting/organizing main wasp file (OpenSaaS) into different sections
import { QueryConfig, ActionConfig, App, ApiConfig } from "wasp-config"
export const initActions = (app: App) => {
const {
getPaginatedUsersConfig,
updateCurrentUserConfig,
updateUserByIdConfig,
generateGptResponseConfig,
createTaskConfig,
deleteTaskConfig,
updateTaskConfig,
getGptResponsesConfig,
getAllTasksByUserConfig,
getCustomerPortalUrlConfig,
generateCheckoutSessionConfig,
createFileConfig,
getAllFilesByUserConfig,
getDownloadFileSignedURLConfig,
getDailyStatsConfig,
paymentsWebhookConfig
} = actionsConfig();
app.query('getPaginatedUsers', getPaginatedUsersConfig);
app.action('updateCurrentUser', updateCurrentUserConfig);
app.action('updateUserById', updateUserByIdConfig);
app.action('generateGptResponse', generateGptResponseConfig);
app.action('createTask', createTaskConfig);
app.action('deleteTask', deleteTaskConfig);
app.action('updateTask', updateTaskConfig);
app.query('getGptResponses', getGptResponsesConfig);
app.query('getAllTasksByUser', getAllTasksByUserConfig);
app.query('getCustomerPortalUrl', getCustomerPortalUrlConfig);
app.action('generateCheckoutSession', generateCheckoutSessionConfig);
app.action('createFile', createFileConfig);
app.query('getAllFilesByUser', getAllFilesByUserConfig);
app.query('getDownloadFileSignedURL', getDownloadFileSignedURLConfig);
app.query('getDailyStats', getDailyStatsConfig);
app.api('paymentsWebhook', paymentsWebhookConfig);
}
const actionsConfig = () => {
const getPaginatedUsersConfig: QueryConfig = {
fn: { import: 'getPaginatedUsers', from: '@src/user/operations' },
entities: ['User']
};
const updateCurrentUserConfig: ActionConfig = {
fn: { import: 'updateCurrentUser', from: '@src/user/operations' },
entities: ['User']
};
const updateUserByIdConfig: ActionConfig = {
fn: { import: 'updateUserById', from: '@src/user/operations' },
entities: ['User']
};
const generateGptResponseConfig: ActionConfig = {
fn: { import: 'generateGptResponse', from: '@src/demo-ai-app/operations' },
entities: ['User', 'Task', 'GptResponse']
};
const createTaskConfig: ActionConfig = {
fn: { import: 'createTask', from: '@src/demo-ai-app/operations' },
entities: ['Task']
};
const deleteTaskConfig: ActionConfig = {
fn: { import: 'deleteTask', from: '@src/demo-ai-app/operations' },
entities: ['Task']
};
const updateTaskConfig: ActionConfig = {
fn: { import: 'updateTask', from: '@src/demo-ai-app/operations' },
entities: ['Task']
};
const getGptResponsesConfig: QueryConfig = {
fn: { import: 'getGptResponses', from: '@src/demo-ai-app/operations' },
entities: ['User', 'GptResponse']
};
const getAllTasksByUserConfig: QueryConfig = {
fn: { import: 'getAllTasksByUser', from: '@src/demo-ai-app/operations' },
entities: ['Task']
};
const getCustomerPortalUrlConfig: QueryConfig = {
fn: { import: 'getCustomerPortalUrl', from: '@src/payment/operations' },
entities: ['User']
};
const generateCheckoutSessionConfig: ActionConfig = {
fn: { import: 'generateCheckoutSession', from: '@src/payment/operations' },
entities: ['User']
};
const createFileConfig: ActionConfig = {
fn: { import: 'createFile', from: '@src/file-upload/operations' },
entities: ['User', 'File']
};
const getAllFilesByUserConfig: QueryConfig = {
fn: { import: 'getAllFilesByUser', from: '@src/file-upload/operations' },
entities: ['User', 'File']
};
const getDownloadFileSignedURLConfig: QueryConfig = {
fn: { import: 'getDownloadFileSignedURL', from: '@src/file-upload/operations' },
entities: ['User', 'File']
};
const getDailyStatsConfig: QueryConfig = {
fn: { import: 'getDailyStats', from: '@src/analytics/operations' },
entities: ['User', 'DailyStats']
};
const paymentsWebhookConfig: ApiConfig = {
fn: { import: 'paymentsWebhook', from: '@src/payment/webhook' },
entities: ['User'],
middlewareConfigFn: { import: 'paymentsMiddlewareConfigFn', from: '@src/payment/webhook' },
httpRoute: ['POST', '/payments-webhook']
};
return {
getPaginatedUsersConfig,
updateCurrentUserConfig,
updateUserByIdConfig,
generateGptResponseConfig,
createTaskConfig,
deleteTaskConfig,
updateTaskConfig,
getGptResponsesConfig,
getAllTasksByUserConfig,
getCustomerPortalUrlConfig,
generateCheckoutSessionConfig,
createFileConfig,
getAllFilesByUserConfig,
getDownloadFileSignedURLConfig,
getDailyStatsConfig,
paymentsWebhookConfig
}
}
import { App, AppConfig, AuthConfig, ClientConfig, DbConfig, EmailSenderConfig } from 'wasp-config'
export const initApp = (appName: string, appConfig: AppConfig): App => {
const app = new App(appName, appConfig);
const { authConfig, dbConfig, clientConfig, emailSenderConfig } = config();
app.auth(authConfig);
app.db(dbConfig);
app.client(clientConfig);
app.emailSender(emailSenderConfig);
return app
}
const config = () => {
const authConfig: AuthConfig = {
userEntity: 'User',
methods: {
email: {
fromField: {
name: "AI Agent Resources API",
email: "[email protected]",
},
emailVerification: {
clientRoute: 'EmailVerificationRoute',
getEmailContentFn: { import: 'getVerificationEmailContent', from: '@src/auth/email-and-pass/emails' },
},
passwordReset: {
clientRoute: 'PasswordResetRoute',
getEmailContentFn: { import: 'getPasswordResetEmailContent', from: '@src/auth/email-and-pass/emails' },
},
userSignupFields: { import: 'getEmailUserFields', from: '@src/auth/userSignupFields' },
},
},
onAfterSignup: { import: 'onAfterSignup', from: '@src/auth/hooks' },
onAuthFailedRedirectTo: '/login',
onAuthSucceededRedirectTo: '/demo-app',
}
const dbConfig: DbConfig = {
seeds: [
{ import: 'seedMockUsers', from: '@src/server/scripts/dbSeeds' },
]
}
const clientConfig: ClientConfig = {
rootComponent: { importDefault: 'App', from: '@src/client/App' },
}
const emailSenderConfig: EmailSenderConfig = {
provider: 'SMTP',
defaultFrom: {
name: "Open SaaS App",
email: "[email protected]"
},
}
return { authConfig, dbConfig, clientConfig, emailSenderConfig }
}
import { App, JobConfig } from "wasp-config"
export const initJobs = (app: App) => {
const {
dailyStatsJobConfig,
sendNewsletterJobConfig
} = jobsConfig();
app.job('dailyStatsJob', dailyStatsJobConfig);
app.job('sendNewsletter', sendNewsletterJobConfig);
}
const jobsConfig = () => {
const dailyStatsJobConfig: JobConfig = {
executor: 'PgBoss',
perform: {
fn: { import: 'calculateDailyStats', from: '@src/analytics/stats' }
},
entities: ['User', 'DailyStats', 'Logs', 'PageViewSource']
};
const sendNewsletterJobConfig: JobConfig = {
executor: 'PgBoss',
perform: {
fn: { import: 'checkAndQueueNewsletterEmails', from: '@src/newsletter/sendNewsletter' }
},
entities: ['User']
};
return {
dailyStatsJobConfig,
sendNewsletterJobConfig
}
}
import { initApp } from './wasp-config/core.wasp.js'
import { initRoutes } from './wasp-config/routes.wasp.js'
import { initActions } from './wasp-config/actions.wasp.js'
import { initJobs } from './wasp-config/jobs.wasp.js'
// Configure the app here
const app = initApp(
'OpenSaaS App',
{
title: 'OpenSaaS App',
wasp: { version: '^0.15.0' },
head: [
"<meta charset='utf-8' />",
"<meta name='description' content='Your apps main description and features.' />",
"<meta name='author' content='OpenSaaS App' />",
"<meta name='keywords' content='saas, solution, product, app, service' />",
"<meta property='og:type' content='website' />",
"<meta property='og:title' content='OpenSaaS App' />",
"<meta property='og:site_name' content='OpenSaaS App' />",
"<meta property='og:url' content='https://your-saas-app.com' />",
"<meta property='og:description' content='Your apps main description and features.' />",
"<meta property='og:image' content='https://your-saas-app.com/public-banner.webp' />",
"<meta name='twitter:image' content='https://your-saas-app.com/public-banner.webp' />",
"<meta name='twitter:image:width' content='800' />",
"<meta name='twitter:image:height' content='400' />",
"<meta name='twitter:card' content='summary_large_image' />",
"<script defer data-domain='<your-site-id>' src='https://plausible.io/js/script.js'></script>",
"<script defer data-domain='<your-site-id>' src='https://plausible.io/js/script.local.js'></script>",
],
}
);
initRoutes(app);
initActions(app);
initJobs(app);
export default app;
import { App, RouteConfig } from "wasp-config";
export const initRoutes = (app: App) => {
const {
landingPageConfig,
loginPageConfig,
signupPageConfig,
requestPasswordResetPageConfig,
passwordResetPageConfig,
emailVerificationPageConfig,
accountPageConfig,
demoAppPageConfig,
pricingPageConfig,
checkoutPageConfig,
fileUploadPageConfig,
adminDashboardPageConfig,
adminUsersPageConfig,
adminSettingsPageConfig,
adminChartsPageConfig,
adminFormElementsPageConfig,
adminFormLayoutsPageConfig,
adminCalendarPageConfig,
adminUIAlertsPageConfig,
adminUIButtonsPageConfig,
notFoundPageConfig,
adminMessagesPageConfig
} = routesConfig(app);
app.route('LandingPageRoute', landingPageConfig);
app.route('LoginRoute', loginPageConfig);
app.route('SignupRoute', signupPageConfig);
app.route('RequestPasswordResetRoute', requestPasswordResetPageConfig);
app.route('PasswordResetRoute', passwordResetPageConfig);
app.route('EmailVerificationRoute', emailVerificationPageConfig);
app.route('AccountRoute', accountPageConfig);
app.route('DemoAppRoute', demoAppPageConfig);
app.route('PricingPageRoute', pricingPageConfig);
app.route('CheckoutRoute', checkoutPageConfig);
app.route('FileUploadRoute', fileUploadPageConfig);
app.route('AdminRoute', adminDashboardPageConfig);
app.route('AdminUsersRoute', adminUsersPageConfig);
app.route('AdminSettingsRoute', adminSettingsPageConfig);
app.route('AdminChartsRoute', adminChartsPageConfig);
app.route('AdminFormElementsRoute', adminFormElementsPageConfig);
app.route('AdminFormLayoutsRoute', adminFormLayoutsPageConfig);
app.route('AdminCalendarRoute', adminCalendarPageConfig);
app.route('AdminUIAlertsRoute', adminUIAlertsPageConfig);
app.route('AdminUIButtonsRoute', adminUIButtonsPageConfig);
app.route('NotFoundRoute', notFoundPageConfig);
app.route('AdminMessagesRoute', adminMessagesPageConfig);
}
const routesConfig = (app: App) => {
const landingPageConfig: RouteConfig = {
path: '/',
to: app.page('LandingPage', {
component: { importDefault: 'LandingPage', from: '@src/landing-page/LandingPage' }
})
};
const loginPageConfig: RouteConfig = {
path: '/login',
to: app.page('LoginPage', {
component: { importDefault: 'Login', from: '@src/auth/LoginPage' }
})
};
const signupPageConfig: RouteConfig = {
path: '/signup',
to: app.page('SignupPage', {
component: { import: 'Signup', from: '@src/auth/SignupPage' }
})
};
const requestPasswordResetPageConfig: RouteConfig = {
path: '/request-password-reset',
to: app.page('RequestPasswordResetPage', {
component: { import: 'RequestPasswordResetPage', from: '@src/auth/email-and-pass/RequestPasswordResetPage' }
})
};
const passwordResetPageConfig: RouteConfig = {
path: '/password-reset',
to: app.page('PasswordResetPage', {
component: { import: 'PasswordResetPage', from: '@src/auth/email-and-pass/PasswordResetPage' }
})
};
const emailVerificationPageConfig: RouteConfig = {
path: '/email-verification',
to: app.page('EmailVerificationPage', {
component: { import: 'EmailVerificationPage', from: '@src/auth/email-and-pass/EmailVerificationPage' }
})
};
const accountPageConfig: RouteConfig = {
path: '/account',
to: app.page('AccountPage', {
authRequired: true,
component: { importDefault: 'Account', from: '@src/user/AccountPage' }
})
};
const demoAppPageConfig: RouteConfig = {
path: '/demo-app',
to: app.page('DemoAppPage', {
authRequired: true,
component: { importDefault: 'DemoAppPage', from: '@src/demo-ai-app/DemoAppPage' }
})
};
const pricingPageConfig: RouteConfig = {
path: '/pricing',
to: app.page('PricingPage', {
component: { importDefault: 'PricingPage', from: '@src/payment/PricingPage' }
})
};
const checkoutPageConfig: RouteConfig = {
path: '/checkout',
to: app.page('CheckoutPage', {
authRequired: true,
component: { importDefault: 'Checkout', from: '@src/payment/CheckoutPage' }
})
};
const fileUploadPageConfig: RouteConfig = {
path: '/file-upload',
to: app.page('FileUploadPage', {
authRequired: true,
component: { importDefault: 'FileUpload', from: '@src/file-upload/FileUploadPage' }
})
};
const adminDashboardPageConfig: RouteConfig = {
path: '/admin',
to: app.page('AnalyticsDashboardPage', {
authRequired: true,
component: { importDefault: 'AnalyticsDashboardPage', from: '@src/admin/dashboards/analytics/AnalyticsDashboardPage' }
})
};
const adminUsersPageConfig: RouteConfig = {
path: '/admin/users',
to: app.page('AdminUsersPage', {
authRequired: true,
component: { importDefault: 'AdminUsers', from: '@src/admin/dashboards/users/UsersDashboardPage' }
})
};
const adminSettingsPageConfig: RouteConfig = {
path: '/admin/settings',
to: app.page('AdminSettingsPage', {
authRequired: true,
component: { importDefault: 'AdminSettings', from: '@src/admin/elements/settings/SettingsPage' }
})
};
const adminChartsPageConfig: RouteConfig = {
path: '/admin/chart',
to: app.page('AdminChartsPage', {
authRequired: true,
component: { importDefault: 'AdminCharts', from: '@src/admin/elements/charts/ChartsPage' }
})
};
const adminFormElementsPageConfig: RouteConfig = {
path: '/admin/forms/form-elements',
to: app.page('AdminFormElementsPage', {
authRequired: true,
component: { importDefault: 'AdminForms', from: '@src/admin/elements/forms/FormElementsPage' }
})
};
const adminFormLayoutsPageConfig: RouteConfig = {
path: '/admin/forms/form-layouts',
to: app.page('AdminFormLayoutsPage', {
authRequired: true,
component: { importDefault: 'AdminForms', from: '@src/admin/elements/forms/FormLayoutsPage' }
})
};
const adminCalendarPageConfig: RouteConfig = {
path: '/admin/calendar',
to: app.page('AdminCalendarPage', {
authRequired: true,
component: { importDefault: 'AdminCalendar', from: '@src/admin/elements/calendar/CalendarPage' }
})
};
const adminUIAlertsPageConfig: RouteConfig = {
path: '/admin/ui/alerts',
to: app.page('AdminUIAlertsPage', {
authRequired: true,
component: { importDefault: 'AdminUI', from: '@src/admin/elements/ui-elements/AlertsPage' }
})
};
const adminUIButtonsPageConfig: RouteConfig = {
path: '/admin/ui/buttons',
to: app.page('AdminUIButtonsPage', {
authRequired: true,
component: { importDefault: 'AdminUI', from: '@src/admin/elements/ui-elements/ButtonsPage' }
})
};
const notFoundPageConfig: RouteConfig = {
path: '*',
to: app.page('NotFoundPage', {
component: { import: 'NotFoundPage', from: '@src/client/components/NotFoundPage' }
})
};
const adminMessagesPageConfig: RouteConfig = {
path: '/admin/messages',
to: app.page('AdminMessagesPage', {
authRequired: true,
component: { importDefault: 'AdminMessages', from: '@src/messages/MessagesPage' }
})
};
return {
landingPageConfig,
loginPageConfig,
signupPageConfig,
requestPasswordResetPageConfig,
passwordResetPageConfig,
emailVerificationPageConfig,
accountPageConfig,
demoAppPageConfig,
pricingPageConfig,
checkoutPageConfig,
fileUploadPageConfig,
adminDashboardPageConfig,
adminUsersPageConfig,
adminSettingsPageConfig,
adminChartsPageConfig,
adminFormElementsPageConfig,
adminFormLayoutsPageConfig,
adminCalendarPageConfig,
adminUIAlertsPageConfig,
adminUIButtonsPageConfig,
notFoundPageConfig,
adminMessagesPageConfig
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment