app todoApp { wasp: { version: "^0.11.0" }, title: "ToDo App", // head: [], dependencies: [ ("@tailwindcss/forms", "^0.5.3"), ("@tailwindcss/typography", "^0.5.7") ], webSocket: { fn: import { webSocketFn } from "@server/webSocket.js", // autoConnect: false }, auth: { userEntity: User, // externalAuthEntity: SocialLogin, methods: { // usernameAndPassword: {}, // google: { // configFn: import { config } from "@server/auth/google.js", // getUserFieldsFn: import { getUserFields } from "@server/auth/google.js" // }, // gitHub: { // // configFn: import { config } from "@server/auth/github.js", // // getUserFieldsFn: import { getUserFields } from "@server/auth/github.js" // }, email: { fromField: { name: "ToDO App", email: "mihovil@ilakovac.com" }, emailVerification: { getEmailContentFn: import { getVerificationEmailContent } from "@server/auth/email.js", clientRoute: EmailVerificationRoute, }, passwordReset: { getEmailContentFn: import { getPasswordResetEmailContent } from "@server/auth/email.js", clientRoute: PasswordResetRoute }, allowUnverifiedLogin: false, }, }, onAuthFailedRedirectTo: "/login", onAuthSucceededRedirectTo: "/profile" }, server: { setupFn: import setup from "@server/serverSetup.js", middlewareConfigFn: import { serverMiddlewareFn } from "@server/serverSetup.js", }, client: { rootComponent: import { App } from "@client/App.tsx", setupFn: import setup from "@client/clientSetup.js" }, db: { system: PostgreSQL, seeds: [ import { devSeedSimple } from "@server/dbSeeds.js", import { prodSeed } from "@server/dbSeeds.js" ] }, emailSender: { provider: SMTP, defaultFrom: { email: "mihovil@ilakovac.com" }, }, } entity User {=psl id Int @id @default(autoincrement()) // Email auth email String? @unique password String? isEmailVerified Boolean @default(false) emailVerificationSentAt DateTime? passwordResetSentAt DateTime? // Social login externalAuthAssociations SocialLogin[] // Business logic tasks Task[] psl=} entity SocialLogin {=psl id Int @id @default(autoincrement()) provider String providerId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int createdAt DateTime @default(now()) @@unique([provider, providerId, userId]) psl=} entity Task {=psl id Int @id @default(autoincrement()) description String isDone Boolean @default(false) user User @relation(fields: [userId], references: [id]) userId Int psl=} route SignupRoute { path: "/signup", to: SignupPage } page SignupPage { component: import Signup from "@client/pages/auth/Signup.tsx" } route LoginRoute { path: "/login", to: LoginPage } page LoginPage { component: import Login from "@client/pages/auth/Login.tsx" } route PasswordResetRoute { path: "/password-reset", to: PasswordResetPage } page PasswordResetPage { component: import { PasswordReset } from "@client/pages/auth/PasswordReset.tsx", } route EmailVerificationRoute { path: "/email-verification-", to: EmailVerificationPage } page EmailVerificationPage { component: import { EmailVerification } from "@client/pages/auth/EmailVerification.tsx", } route RequestPasswordResetRoute { path: "/request-password-reset", to: RequestPasswordResetPage } page RequestPasswordResetPage { component: import { RequestPasswordReset } from "@client/pages/auth/RequestPasswordReset.tsx", } route HomeRoute { path: "/", to: MainPage } page MainPage { authRequired: true, component: import Main from "@client/pages/Main.jsx" } route AboutRoute { path: "/about", to: AboutPage } page AboutPage { component: import About from "@client/pages/About.jsx" } route ProfileRoute { path: "/profile", to: ProfilePage } page ProfilePage { authRequired: true, component: import { ProfilePage } from "@client/pages/ProfilePage.tsx" } // Page for viewing a specific task // route TaskRoute { path: "/task/:id", to: TaskPage } page TaskPage { authRequired: true, component: import Task from "@client/pages/Task.tsx" } // --------- Queries --------- // query getTasks { fn: import { getTasks } from "@server/queries.js", entities: [Task] } api fooBar { fn: import { fooBar } from "@server/apis.js", middlewareConfigFn: import { fooBarMiddlewareFn } from "@server/apis.js", entities: [Task], // ALL here let's our CORS work. If we did GET, we would need an apiNamespace over it with CORS. httpRoute: (ALL, "/foo/bar") } apiNamespace bar { middlewareConfigFn: import { barNamespaceMiddlewareFn } from "@server/apis.js", path: "/bar" } api barBaz { fn: import { barBaz } from "@server/apis.js", auth: false, entities: [Task], httpRoute: (GET, "/bar/baz") } api webhookCallback { fn: import { webhookCallback } from "@server/apis.js", middlewareConfigFn: import { webhookCallbackMiddlewareFn } from "@server/apis.js", httpRoute: (POST, "/webhook/callback"), auth: false } query getNumTasks { fn: import { getNumTasks } from "@server/queries.js", entities: [Task], auth: false } query getTask { fn: import { getTask } from "@server/queries.js", entities: [Task] } query getDate { fn: import { getDate } from "@server/queries.js" } // --------- Actions --------- // action createTask { fn: import { createTask } from "@server/actions.js", entities: [Task] } action updateTaskIsDone { fn: import { updateTaskIsDone } from "@server/actions.js", entities: [Task] } action deleteCompletedTasks { fn: import { deleteCompletedTasks } from "@server/actions.js", entities: [Task] } action toggleAllTasks { fn: import { toggleAllTasks } from "@server/actions.js", entities: [Task] } job mySpecialJob { executor: PgBoss, perform: { fn: import { foo } from "@server/jobs/bar.js", executorOptions: { pgBoss: {=json { "retryLimit": 1 } json=} } }, entities: [Task] } job mySpecialScheduledJob { executor: PgBoss, perform: { fn: import { foo } from "@server/jobs/bar.js" }, schedule: { cron: "0 * * * *", args: {=json { "foo": "bar" } json=}, executorOptions: { pgBoss: {=json { "retryLimit": 2 } json=} } } }