@wasp.sh/wasp-cli-darwin-arm64-unknown 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @wasp.sh/wasp-cli-darwin-arm64-unknown might be problematic. Click here for more details.
- package/data/Cli/bash-completion +5 -0
- package/data/Cli/starters/README.md +22 -0
- package/data/Cli/starters/basic/.prettierignore +2 -0
- package/data/Cli/starters/basic/.prettierrc +3 -0
- package/data/Cli/starters/basic/README.md +35 -0
- package/data/Cli/starters/basic/eslint.config.js +15 -0
- package/data/Cli/starters/basic/main.wasp +100 -0
- package/data/Cli/starters/basic/package.json +27 -0
- package/data/Cli/starters/basic/postcss.config.cjs +6 -0
- package/data/Cli/starters/basic/schema.prisma +42 -0
- package/data/Cli/starters/basic/src/App.css +13 -0
- package/data/Cli/starters/basic/src/App.tsx +12 -0
- package/data/Cli/starters/basic/src/assets/logo.svg +1 -0
- package/data/Cli/starters/basic/src/auth/AuthLayout.tsx +10 -0
- package/data/Cli/starters/basic/src/auth/email/EmailVerificationPage.tsx +19 -0
- package/data/Cli/starters/basic/src/auth/email/LoginPage.tsx +27 -0
- package/data/Cli/starters/basic/src/auth/email/PasswordResetPage.tsx +19 -0
- package/data/Cli/starters/basic/src/auth/email/RequestPasswordResetPage.tsx +10 -0
- package/data/Cli/starters/basic/src/auth/email/SignupPage.tsx +34 -0
- package/data/Cli/starters/basic/src/auth/email/userSignupFields.ts +13 -0
- package/data/Cli/starters/basic/src/shared/components/Button.tsx +90 -0
- package/data/Cli/starters/basic/src/shared/components/Dialog.tsx +85 -0
- package/data/Cli/starters/basic/src/shared/components/Header.tsx +39 -0
- package/data/Cli/starters/basic/src/shared/components/Input.tsx +36 -0
- package/data/Cli/starters/basic/src/shared/components/Portal.tsx +26 -0
- package/data/Cli/starters/basic/src/tags/actions.ts +23 -0
- package/data/Cli/starters/basic/src/tags/components/ColorRadioButton.tsx +44 -0
- package/data/Cli/starters/basic/src/tags/components/ColorRadioButtons.tsx +59 -0
- package/data/Cli/starters/basic/src/tags/components/CreateTagDialog.tsx +50 -0
- package/data/Cli/starters/basic/src/tags/components/CreateTagForm.tsx +100 -0
- package/data/Cli/starters/basic/src/tags/components/TagLabel.tsx +55 -0
- package/data/Cli/starters/basic/src/tags/components/colors.ts +8 -0
- package/data/Cli/starters/basic/src/tags/queries.ts +14 -0
- package/data/Cli/starters/basic/src/tasks/TasksPage.tsx +19 -0
- package/data/Cli/starters/basic/src/tasks/actions.ts +71 -0
- package/data/Cli/starters/basic/src/tasks/components/CreateTaskForm.tsx +103 -0
- package/data/Cli/starters/basic/src/tasks/components/TaskList.tsx +68 -0
- package/data/Cli/starters/basic/src/tasks/components/TaskListItem.tsx +56 -0
- package/data/Cli/starters/basic/src/tasks/queries.ts +21 -0
- package/data/Cli/starters/basic/tailwind.config.cjs +30 -0
- package/data/Cli/starters/basic/vite.config.ts +7 -0
- package/data/Cli/starters/minimal/main.wasp +14 -0
- package/data/Cli/starters/minimal/package.json +16 -0
- package/data/Cli/starters/minimal/schema.prisma +10 -0
- package/data/Cli/starters/minimal/src/Main.css +103 -0
- package/data/Cli/starters/minimal/src/MainPage.tsx +37 -0
- package/data/Cli/starters/minimal/src/assets/logo.svg +1 -0
- package/data/Cli/starters/minimal/vite.config.ts +7 -0
- package/data/Cli/starters/skeleton/.waspignore +4 -0
- package/data/Cli/starters/skeleton/.wasproot +1 -0
- package/data/Cli/starters/skeleton/public/.gitkeep +0 -0
- package/data/Cli/starters/skeleton/public/favicon.ico +0 -0
- package/data/Cli/starters/skeleton/src/vite-env.d.ts +7 -0
- package/data/Cli/starters/skeleton/tsconfig.json +28 -0
- package/data/Generator/templates/Dockerfile +72 -0
- package/data/Generator/templates/db/schema.prisma +24 -0
- package/data/Generator/templates/dockerignore +2 -0
- package/data/Generator/templates/react-app/README.md +21 -0
- package/data/Generator/templates/react-app/gitignore +23 -0
- package/data/Generator/templates/react-app/index.html +22 -0
- package/data/Generator/templates/react-app/netlify.toml +8 -0
- package/data/Generator/templates/react-app/npmrc +1 -0
- package/data/Generator/templates/react-app/package.json +30 -0
- package/data/Generator/templates/react-app/public/manifest.json +15 -0
- package/data/Generator/templates/react-app/src/auth/pages/OAuthCallback.tsx +96 -0
- package/data/Generator/templates/react-app/src/auth/pages/createAuthRequiredPage.jsx +40 -0
- package/data/Generator/templates/react-app/src/components/DefaultRootErrorBoundary.tsx +16 -0
- package/data/Generator/templates/react-app/src/components/FullPageWrapper.tsx +21 -0
- package/data/Generator/templates/react-app/src/components/Loader.module.css +37 -0
- package/data/Generator/templates/react-app/src/components/Loader.tsx +12 -0
- package/data/Generator/templates/react-app/src/components/Message.tsx +86 -0
- package/data/Generator/templates/react-app/src/index.tsx +47 -0
- package/data/Generator/templates/react-app/src/logo.png +0 -0
- package/data/Generator/templates/react-app/src/router.tsx +57 -0
- package/data/Generator/templates/react-app/src/stitches.config.js +33 -0
- package/data/Generator/templates/react-app/src/test/vitest/setup.ts +8 -0
- package/data/Generator/templates/react-app/src/utils.js +3 -0
- package/data/Generator/templates/react-app/src/vite-env.d.ts +1 -0
- package/data/Generator/templates/react-app/tsconfig.app.json +20 -0
- package/data/Generator/templates/react-app/tsconfig.json +11 -0
- package/data/Generator/templates/react-app/tsconfig.vite.json +16 -0
- package/data/Generator/templates/react-app/vite/detectServerImports.ts +53 -0
- package/data/Generator/templates/react-app/vite/validateEnv.ts +45 -0
- package/data/Generator/templates/react-app/vite.config.ts +74 -0
- package/data/Generator/templates/sdk/wasp/api/events.ts +11 -0
- package/data/Generator/templates/sdk/wasp/api/index.ts +136 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/login.ts +13 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/passwordReset.ts +22 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/signup.ts +20 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/verifyEmail.ts +14 -0
- package/data/Generator/templates/sdk/wasp/auth/email/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Auth.tsx +108 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/ForgotPassword.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Login.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/ResetPassword.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Signup.tsx +24 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/VerifyEmail.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Form.tsx +107 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.tsx +21 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx +356 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ForgotPasswordForm.tsx +52 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ResetPasswordForm.tsx +82 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/VerifyEmailForm.tsx +42 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/useEmail.ts +33 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialButton.tsx +33 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx +78 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/usernameAndPassword/useUsernameAndPassword.ts +29 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/types.ts +52 -0
- package/data/Generator/templates/sdk/wasp/auth/helpers/_Provider.tsx +17 -0
- package/data/Generator/templates/sdk/wasp/auth/helpers/user.ts +15 -0
- package/data/Generator/templates/sdk/wasp/auth/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/auth/jwt.ts +22 -0
- package/data/Generator/templates/sdk/wasp/auth/logout.ts +18 -0
- package/data/Generator/templates/sdk/wasp/auth/lucia.ts +53 -0
- package/data/Generator/templates/sdk/wasp/auth/password.ts +36 -0
- package/data/Generator/templates/sdk/wasp/auth/providers/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/auth/providers/types.ts +68 -0
- package/data/Generator/templates/sdk/wasp/auth/session.ts +78 -0
- package/data/Generator/templates/sdk/wasp/auth/types.ts +2 -0
- package/data/Generator/templates/sdk/wasp/auth/useAuth.ts +37 -0
- package/data/Generator/templates/sdk/wasp/auth/user.ts +63 -0
- package/data/Generator/templates/sdk/wasp/auth/username/actions/login.ts +13 -0
- package/data/Generator/templates/sdk/wasp/auth/username/actions/signup.ts +20 -0
- package/data/Generator/templates/sdk/wasp/auth/username/index.ts +2 -0
- package/data/Generator/templates/sdk/wasp/auth/utils.ts +369 -0
- package/data/Generator/templates/sdk/wasp/auth/validation.ts +83 -0
- package/data/Generator/templates/sdk/wasp/client/auth/discord.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/email.ts +5 -0
- package/data/Generator/templates/sdk/wasp/client/auth/github.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/google.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/index.ts +29 -0
- package/data/Generator/templates/sdk/wasp/client/auth/keycloak.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/slack.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/ui.ts +32 -0
- package/data/Generator/templates/sdk/wasp/client/auth/username.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/config.ts +14 -0
- package/data/Generator/templates/sdk/wasp/client/crud/_crud.ts +89 -0
- package/data/Generator/templates/sdk/wasp/client/crud/index.ts +4 -0
- package/data/Generator/templates/sdk/wasp/client/crud/operationsHelpers.ts +21 -0
- package/data/Generator/templates/sdk/wasp/client/env/schema.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/env.ts +5 -0
- package/data/Generator/templates/sdk/wasp/client/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/client/operations/actions/core.ts +49 -0
- package/data/Generator/templates/sdk/wasp/client/operations/actions/index.ts +13 -0
- package/data/Generator/templates/sdk/wasp/client/operations/hooks.ts +347 -0
- package/data/Generator/templates/sdk/wasp/client/operations/index.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/index.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/resources.js +83 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/updateHandlersMap.js +37 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queries/core.ts +91 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queries/index.ts +16 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queryClient.ts +34 -0
- package/data/Generator/templates/sdk/wasp/client/operations/rpc.ts +96 -0
- package/data/Generator/templates/sdk/wasp/client/router/Link.tsx +21 -0
- package/data/Generator/templates/sdk/wasp/client/router/index.ts +53 -0
- package/data/Generator/templates/sdk/wasp/client/router/linkHelpers.ts +48 -0
- package/data/Generator/templates/sdk/wasp/client/router/types.ts +98 -0
- package/data/Generator/templates/sdk/wasp/client/test/index.ts +1 -0
- package/data/Generator/templates/sdk/wasp/client/test/vitest/helpers.tsx +95 -0
- package/data/Generator/templates/sdk/wasp/client/webSocket/WebSocketProvider.tsx +77 -0
- package/data/Generator/templates/sdk/wasp/client/webSocket/index.ts +39 -0
- package/data/Generator/templates/sdk/wasp/core/auth.ts +40 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/custom-register.ts +21 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/index.ts +56 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/prisma.ts +54 -0
- package/data/Generator/templates/sdk/wasp/core/stitches.config.ts +39 -0
- package/data/Generator/templates/sdk/wasp/core/storage.ts +50 -0
- package/data/Generator/templates/sdk/wasp/dev/index.ts +19 -0
- package/data/Generator/templates/sdk/wasp/entities/index.ts +28 -0
- package/data/Generator/templates/sdk/wasp/env/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/env/validation.ts +38 -0
- package/data/Generator/templates/sdk/wasp/package.json +151 -0
- package/data/Generator/templates/sdk/wasp/prisma-runtime-library.d.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/HttpError.ts +30 -0
- package/data/Generator/templates/sdk/wasp/server/_types/index.ts +105 -0
- package/data/Generator/templates/sdk/wasp/server/_types/taggedEntities.ts +26 -0
- package/data/Generator/templates/sdk/wasp/server/api/index.ts +44 -0
- package/data/Generator/templates/sdk/wasp/server/auth/email/index.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/email/utils.ts +104 -0
- package/data/Generator/templates/sdk/wasp/server/auth/hooks.ts +188 -0
- package/data/Generator/templates/sdk/wasp/server/auth/index.ts +49 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/index.ts +38 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/oneTimeCode.ts +50 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/provider.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/discord.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/github.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/google.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/keycloak.ts +23 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/slack.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/redirect.ts +43 -0
- package/data/Generator/templates/sdk/wasp/server/auth/user.ts +148 -0
- package/data/Generator/templates/sdk/wasp/server/auth/username.ts +1 -0
- package/data/Generator/templates/sdk/wasp/server/config.ts +47 -0
- package/data/Generator/templates/sdk/wasp/server/crud/_operationTypes.ts +134 -0
- package/data/Generator/templates/sdk/wasp/server/crud/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/server/dbClient.ts +35 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/helpers.ts +40 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/dummy.ts +34 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/mailgun.ts +31 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/sendgrid.ts +44 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/smtp.ts +29 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/types.ts +59 -0
- package/data/Generator/templates/sdk/wasp/server/email/index.ts +39 -0
- package/data/Generator/templates/sdk/wasp/server/env.ts +168 -0
- package/data/Generator/templates/sdk/wasp/server/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/_job.ts +39 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/job.ts +28 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/index.ts +3 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBoss.ts +76 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBossJob.ts +230 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/types.ts +9 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/server/middleware/globalMiddleware.ts +8 -0
- package/data/Generator/templates/sdk/wasp/server/middleware/index.ts +1 -0
- package/data/Generator/templates/sdk/wasp/server/operations/actions/index.ts +41 -0
- package/data/Generator/templates/sdk/wasp/server/operations/actions/types.ts +35 -0
- package/data/Generator/templates/sdk/wasp/server/operations/index.ts +13 -0
- package/data/Generator/templates/sdk/wasp/server/operations/queries/index.ts +42 -0
- package/data/Generator/templates/sdk/wasp/server/operations/queries/types.ts +36 -0
- package/data/Generator/templates/sdk/wasp/server/operations/wrappers.ts +242 -0
- package/data/Generator/templates/sdk/wasp/server/types/index.ts +11 -0
- package/data/Generator/templates/sdk/wasp/server/utils.ts +38 -0
- package/data/Generator/templates/sdk/wasp/server/webSocket/index.ts +57 -0
- package/data/Generator/templates/sdk/wasp/tsconfig.json +114 -0
- package/data/Generator/templates/sdk/wasp/universal/ansiColors.ts +14 -0
- package/data/Generator/templates/sdk/wasp/universal/predicates.ts +3 -0
- package/data/Generator/templates/sdk/wasp/universal/types.ts +74 -0
- package/data/Generator/templates/sdk/wasp/universal/url.ts +5 -0
- package/data/Generator/templates/sdk/wasp/universal/validators.ts +21 -0
- package/data/Generator/templates/sdk/wasp/vite-env.d.ts +1 -0
- package/data/Generator/templates/server/README.md +1 -0
- package/data/Generator/templates/server/gitignore +6 -0
- package/data/Generator/templates/server/nodemon.json +13 -0
- package/data/Generator/templates/server/npmrc +1 -0
- package/data/Generator/templates/server/package.json +27 -0
- package/data/Generator/templates/server/rollup.config.js +44 -0
- package/data/Generator/templates/server/src/actions/_action.ts +18 -0
- package/data/Generator/templates/server/src/app.js +36 -0
- package/data/Generator/templates/server/src/auth/hooks.ts +135 -0
- package/data/Generator/templates/server/src/auth/providers/config/discord.ts +69 -0
- package/data/Generator/templates/server/src/auth/providers/config/email.ts +96 -0
- package/data/Generator/templates/server/src/auth/providers/config/github.ts +78 -0
- package/data/Generator/templates/server/src/auth/providers/config/google.ts +65 -0
- package/data/Generator/templates/server/src/auth/providers/config/keycloak.ts +67 -0
- package/data/Generator/templates/server/src/auth/providers/config/slack.ts +65 -0
- package/data/Generator/templates/server/src/auth/providers/config/username.ts +33 -0
- package/data/Generator/templates/server/src/auth/providers/email/login.ts +66 -0
- package/data/Generator/templates/server/src/auth/providers/email/requestPasswordReset.ts +74 -0
- package/data/Generator/templates/server/src/auth/providers/email/resetPassword.ts +48 -0
- package/data/Generator/templates/server/src/auth/providers/email/signup.ts +165 -0
- package/data/Generator/templates/server/src/auth/providers/email/verifyEmail.ts +42 -0
- package/data/Generator/templates/server/src/auth/providers/index.ts +32 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/config.ts +19 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/cookies.ts +35 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/handler.ts +130 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/oneTimeCode.ts +39 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/state.ts +144 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/types.ts +7 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/user.ts +139 -0
- package/data/Generator/templates/server/src/auth/providers/username/login.ts +64 -0
- package/data/Generator/templates/server/src/auth/providers/username/signup.ts +59 -0
- package/data/Generator/templates/server/src/crud/_operations.ts +184 -0
- package/data/Generator/templates/server/src/dbSeed.ts +37 -0
- package/data/Generator/templates/server/src/jobs/_job.ts +9 -0
- package/data/Generator/templates/server/src/jobs/core/allJobs.ts +8 -0
- package/data/Generator/templates/server/src/middleware/globalMiddleware.ts +45 -0
- package/data/Generator/templates/server/src/middleware/index.ts +1 -0
- package/data/Generator/templates/server/src/middleware/operations.ts +28 -0
- package/data/Generator/templates/server/src/queries/_query.ts +18 -0
- package/data/Generator/templates/server/src/routes/apis/index.ts +67 -0
- package/data/Generator/templates/server/src/routes/auth/index.js +16 -0
- package/data/Generator/templates/server/src/routes/auth/logout.ts +12 -0
- package/data/Generator/templates/server/src/routes/auth/me.ts +10 -0
- package/data/Generator/templates/server/src/routes/crud/_crud.ts +46 -0
- package/data/Generator/templates/server/src/routes/crud/index.ts +12 -0
- package/data/Generator/templates/server/src/routes/index.js +37 -0
- package/data/Generator/templates/server/src/routes/operations/_action.js +5 -0
- package/data/Generator/templates/server/src/routes/operations/_query.js +5 -0
- package/data/Generator/templates/server/src/routes/operations/index.js +18 -0
- package/data/Generator/templates/server/src/server.ts +76 -0
- package/data/Generator/templates/server/src/webSocket/initialization.ts +59 -0
- package/data/Generator/templates/server/tsconfig.json +41 -0
- package/data/Lsp/templates/ts/action.fn.ts +12 -0
- package/data/Lsp/templates/ts/operation.fn.js +7 -0
- package/data/Lsp/templates/ts/page.component.jsx +9 -0
- package/data/Lsp/templates/ts/query.fn.ts +12 -0
- package/main.js +9 -0
- package/package.json +1 -0
- package/readme.md +3 -0
- package/wasp-bin +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import { env } from '../env.js';
|
|
3
|
+
import { initEmailSender } from "./core/index.js";
|
|
4
|
+
import { EmailSender } from "./core/types.js";
|
|
5
|
+
|
|
6
|
+
{=# isSmtpProviderEnabled =}
|
|
7
|
+
const emailProvider = {
|
|
8
|
+
type: "smtp",
|
|
9
|
+
host: env.SMTP_HOST,
|
|
10
|
+
port: env.SMTP_PORT,
|
|
11
|
+
username: env.SMTP_USERNAME,
|
|
12
|
+
password: env.SMTP_PASSWORD,
|
|
13
|
+
} as const;
|
|
14
|
+
{=/ isSmtpProviderEnabled =}
|
|
15
|
+
{=# isSendGridProviderEnabled =}
|
|
16
|
+
const emailProvider = {
|
|
17
|
+
type: "sendgrid",
|
|
18
|
+
apiKey: env.SENDGRID_API_KEY,
|
|
19
|
+
} as const;
|
|
20
|
+
{=/ isSendGridProviderEnabled =}
|
|
21
|
+
{=# isMailgunProviderEnabled =}
|
|
22
|
+
const emailProvider = {
|
|
23
|
+
type: "mailgun",
|
|
24
|
+
apiKey: env.MAILGUN_API_KEY,
|
|
25
|
+
domain: env.MAILGUN_DOMAIN,
|
|
26
|
+
apiUrl: env.MAILGUN_API_URL,
|
|
27
|
+
} as const;
|
|
28
|
+
{=/ isMailgunProviderEnabled =}
|
|
29
|
+
{=# isDummyProviderEnabled =}
|
|
30
|
+
const emailProvider = {
|
|
31
|
+
type: "dummy",
|
|
32
|
+
} as const;
|
|
33
|
+
{=/ isDummyProviderEnabled =}
|
|
34
|
+
|
|
35
|
+
// PUBLIC API
|
|
36
|
+
export const emailSender: EmailSender = initEmailSender(emailProvider);
|
|
37
|
+
|
|
38
|
+
// PUBLIC API
|
|
39
|
+
export type { Email, EmailFromField, EmailSender, SentMessageInfo } from "./core/types.js";
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import * as z from 'zod'
|
|
3
|
+
|
|
4
|
+
import { ensureEnvSchema } from '../env/validation.js'
|
|
5
|
+
|
|
6
|
+
{=# envValidationSchema.isDefined =}
|
|
7
|
+
{=& envValidationSchema.importStatement =}
|
|
8
|
+
const userServerEnvSchema = {= envValidationSchema.importIdentifier =}
|
|
9
|
+
{=/ envValidationSchema.isDefined =}
|
|
10
|
+
{=^ envValidationSchema.isDefined =}
|
|
11
|
+
const userServerEnvSchema = z.object({})
|
|
12
|
+
{=/ envValidationSchema.isDefined =}
|
|
13
|
+
|
|
14
|
+
const waspServerCommonSchema = z.object({
|
|
15
|
+
PORT: z.coerce.number().default({= defaultServerPort =}),
|
|
16
|
+
{= databaseUrlEnvVarName =}: z.string({
|
|
17
|
+
required_error: '{= databaseUrlEnvVarName =} is required',
|
|
18
|
+
}),
|
|
19
|
+
PG_BOSS_NEW_OPTIONS: z.string().optional(),
|
|
20
|
+
{=# isEmailSenderEnabled =}
|
|
21
|
+
{=# enabledEmailSenders.isSmtpProviderEnabled =}
|
|
22
|
+
SMTP_HOST: z.string({
|
|
23
|
+
required_error: getRequiredEnvVarErrorMessage('SMTP email sender', 'SMTP_HOST'),
|
|
24
|
+
}),
|
|
25
|
+
SMTP_PORT: z.coerce.number({
|
|
26
|
+
required_error: getRequiredEnvVarErrorMessage('SMTP email sender', 'SMTP_PORT'),
|
|
27
|
+
invalid_type_error: 'SMTP_PORT must be a number',
|
|
28
|
+
}),
|
|
29
|
+
SMTP_USERNAME: z.string({
|
|
30
|
+
required_error: getRequiredEnvVarErrorMessage('SMTP email sender', 'SMTP_USERNAME'),
|
|
31
|
+
}),
|
|
32
|
+
SMTP_PASSWORD: z.string({
|
|
33
|
+
required_error: getRequiredEnvVarErrorMessage('SMTP email sender', 'SMTP_PASSWORD'),
|
|
34
|
+
}),
|
|
35
|
+
{=/ enabledEmailSenders.isSmtpProviderEnabled =}
|
|
36
|
+
{=# enabledEmailSenders.isSendGridProviderEnabled =}
|
|
37
|
+
SENDGRID_API_KEY: z.string({
|
|
38
|
+
required_error: getRequiredEnvVarErrorMessage('SendGrid email sender', 'SENDGRID_API_KEY'),
|
|
39
|
+
}),
|
|
40
|
+
{=/ enabledEmailSenders.isSendGridProviderEnabled =}
|
|
41
|
+
{=# enabledEmailSenders.isMailgunProviderEnabled =}
|
|
42
|
+
MAILGUN_API_KEY: z.string({
|
|
43
|
+
required_error: getRequiredEnvVarErrorMessage('Mailgun email sender', 'MAILGUN_API_KEY'),
|
|
44
|
+
}),
|
|
45
|
+
MAILGUN_DOMAIN: z.string({
|
|
46
|
+
required_error: getRequiredEnvVarErrorMessage('Mailgun email sender', 'MAILGUN_DOMAIN'),
|
|
47
|
+
}),
|
|
48
|
+
MAILGUN_API_URL: z.string().optional(),
|
|
49
|
+
{=/ enabledEmailSenders.isMailgunProviderEnabled =}
|
|
50
|
+
{=/ isEmailSenderEnabled =}
|
|
51
|
+
SKIP_EMAIL_VERIFICATION_IN_DEV: z
|
|
52
|
+
.enum(['true', 'false'], {
|
|
53
|
+
message: 'SKIP_EMAIL_VERIFICATION_IN_DEV must be either "true" or "false"',
|
|
54
|
+
})
|
|
55
|
+
.transform((value) => value === 'true')
|
|
56
|
+
.default('false'),
|
|
57
|
+
{=# isAuthEnabled =}
|
|
58
|
+
{=# enabledAuthProviders.isGoogleAuthEnabled =}
|
|
59
|
+
GOOGLE_CLIENT_ID: z.string({
|
|
60
|
+
required_error: getRequiredEnvVarErrorMessage('Google auth provider', 'GOOGLE_CLIENT_ID'),
|
|
61
|
+
}),
|
|
62
|
+
GOOGLE_CLIENT_SECRET: z.string({
|
|
63
|
+
required_error: getRequiredEnvVarErrorMessage('Google auth provider', 'GOOGLE_CLIENT_SECRET'),
|
|
64
|
+
}),
|
|
65
|
+
{=/ enabledAuthProviders.isGoogleAuthEnabled =}
|
|
66
|
+
{=# enabledAuthProviders.isGitHubAuthEnabled =}
|
|
67
|
+
GITHUB_CLIENT_ID: z.string({
|
|
68
|
+
required_error: getRequiredEnvVarErrorMessage('GitHub auth provider', 'GITHUB_CLIENT_ID'),
|
|
69
|
+
}),
|
|
70
|
+
GITHUB_CLIENT_SECRET: z.string({
|
|
71
|
+
required_error: getRequiredEnvVarErrorMessage('GitHub auth provider', 'GITHUB_CLIENT_SECRET'),
|
|
72
|
+
}),
|
|
73
|
+
{=/ enabledAuthProviders.isGitHubAuthEnabled =}
|
|
74
|
+
{=# enabledAuthProviders.isSlackAuthEnabled =}
|
|
75
|
+
SLACK_CLIENT_ID: z.string({
|
|
76
|
+
required_error: getRequiredEnvVarErrorMessage('Slack auth provider', 'SLACK_CLIENT_ID'),
|
|
77
|
+
}),
|
|
78
|
+
SLACK_CLIENT_SECRET: z.string({
|
|
79
|
+
required_error: getRequiredEnvVarErrorMessage('Slack auth provider', 'SLACK_CLIENT_SECRET'),
|
|
80
|
+
}),
|
|
81
|
+
{=/ enabledAuthProviders.isSlackAuthEnabled =}
|
|
82
|
+
{=# enabledAuthProviders.isDiscordAuthEnabled =}
|
|
83
|
+
DISCORD_CLIENT_ID: z.string({
|
|
84
|
+
required_error: getRequiredEnvVarErrorMessage('Discord auth provider', 'DISCORD_CLIENT_ID'),
|
|
85
|
+
}),
|
|
86
|
+
DISCORD_CLIENT_SECRET: z.string({
|
|
87
|
+
required_error: getRequiredEnvVarErrorMessage('Discord auth provider', 'DISCORD_CLIENT_SECRET'),
|
|
88
|
+
}),
|
|
89
|
+
{=/ enabledAuthProviders.isDiscordAuthEnabled =}
|
|
90
|
+
{=# enabledAuthProviders.isKeycloakAuthEnabled =}
|
|
91
|
+
KEYCLOAK_CLIENT_ID: z.string({
|
|
92
|
+
required_error: getRequiredEnvVarErrorMessage('Keycloak auth provider', 'KEYCLOAK_CLIENT_ID'),
|
|
93
|
+
}),
|
|
94
|
+
KEYCLOAK_CLIENT_SECRET: z.string({
|
|
95
|
+
required_error: getRequiredEnvVarErrorMessage('Keycloak auth provider', 'KEYCLOAK_CLIENT_SECRET'),
|
|
96
|
+
}),
|
|
97
|
+
KEYCLOAK_REALM_URL: z
|
|
98
|
+
.string({
|
|
99
|
+
required_error: getRequiredEnvVarErrorMessage('Keycloak auth provider', 'KEYCLOAK_REALM_URL'),
|
|
100
|
+
})
|
|
101
|
+
.url({
|
|
102
|
+
message: 'KEYCLOAK_REALM_URL must be a valid URL',
|
|
103
|
+
}),
|
|
104
|
+
{=/ enabledAuthProviders.isKeycloakAuthEnabled =}
|
|
105
|
+
{=/ isAuthEnabled =}
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const serverUrlSchema = z
|
|
109
|
+
.string({
|
|
110
|
+
required_error: 'WASP_SERVER_URL is required',
|
|
111
|
+
})
|
|
112
|
+
.url({
|
|
113
|
+
message: 'WASP_SERVER_URL must be a valid URL',
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const clientUrlSchema = z
|
|
117
|
+
.string({
|
|
118
|
+
required_error: 'WASP_WEB_CLIENT_URL is required',
|
|
119
|
+
})
|
|
120
|
+
.url({
|
|
121
|
+
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
{=# isAuthEnabled =}
|
|
125
|
+
const jwtTokenSchema = z
|
|
126
|
+
.string({
|
|
127
|
+
required_error: 'JWT_SECRET is required',
|
|
128
|
+
})
|
|
129
|
+
{=/ isAuthEnabled =}
|
|
130
|
+
|
|
131
|
+
// In development, we provide default values for some environment variables
|
|
132
|
+
// to make the development process easier.
|
|
133
|
+
const serverDevSchema = z.object({
|
|
134
|
+
NODE_ENV: z.literal('development'),
|
|
135
|
+
WASP_SERVER_URL: serverUrlSchema
|
|
136
|
+
.default('{= defaultServerUrl =}'),
|
|
137
|
+
WASP_WEB_CLIENT_URL: clientUrlSchema
|
|
138
|
+
.default('{= defaultClientUrl =}'),
|
|
139
|
+
{=# isAuthEnabled =}
|
|
140
|
+
JWT_SECRET: jwtTokenSchema
|
|
141
|
+
.default('DEVJWTSECRET'),
|
|
142
|
+
{=/ isAuthEnabled =}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
const serverProdSchema = z.object({
|
|
146
|
+
NODE_ENV: z.literal('production'),
|
|
147
|
+
WASP_SERVER_URL: serverUrlSchema,
|
|
148
|
+
WASP_WEB_CLIENT_URL: clientUrlSchema,
|
|
149
|
+
{=# isAuthEnabled =}
|
|
150
|
+
JWT_SECRET: jwtTokenSchema,
|
|
151
|
+
{=/ isAuthEnabled =}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
const serverCommonSchema = userServerEnvSchema.merge(waspServerCommonSchema)
|
|
155
|
+
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
|
|
156
|
+
serverDevSchema.merge(serverCommonSchema),
|
|
157
|
+
serverProdSchema.merge(serverCommonSchema)
|
|
158
|
+
])
|
|
159
|
+
|
|
160
|
+
// PUBLIC API
|
|
161
|
+
export const env = ensureEnvSchema(
|
|
162
|
+
{ NODE_ENV: serverDevSchema.shape.NODE_ENV.value, ...process.env },
|
|
163
|
+
serverEnvSchema,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
function getRequiredEnvVarErrorMessage(featureName: string, envVarName: string) {
|
|
167
|
+
return `${envVarName} is required when using ${featureName}`
|
|
168
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PrismaClient } from './dbClient.js'
|
|
2
|
+
|
|
3
|
+
// PUBLIC API
|
|
4
|
+
export { default as config } from './config.js'
|
|
5
|
+
// PUBLIC API
|
|
6
|
+
export { default as prisma, type PrismaClient } from './dbClient.js'
|
|
7
|
+
// PUBLIC API
|
|
8
|
+
export { type ServerSetupFn } from './types/index.js'
|
|
9
|
+
// PUBLIC API
|
|
10
|
+
export { HttpError } from './HttpError.js'
|
|
11
|
+
// PUBLIC API
|
|
12
|
+
export { MiddlewareConfigFn } from './middleware/index.js'
|
|
13
|
+
// PUBLIC API
|
|
14
|
+
export { env } from './env.js'
|
|
15
|
+
|
|
16
|
+
// PUBLIC API
|
|
17
|
+
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import { prisma } from 'wasp/server'
|
|
3
|
+
import type { JSONValue, JSONObject } from 'wasp/core/serialization'
|
|
4
|
+
import { type JobFn, createJobDefinition } from '{= jobExecutorImportPath =}'
|
|
5
|
+
|
|
6
|
+
const entities = {
|
|
7
|
+
{=# entities =}
|
|
8
|
+
{= name =}: prisma.{= prismaIdentifier =},
|
|
9
|
+
{=/ entities =}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// PUBLIC API
|
|
13
|
+
export type {= typeName =}<Input extends JSONObject, Output extends JSONValue | void> = JobFn<Input, Output, typeof entities>
|
|
14
|
+
|
|
15
|
+
{=# jobSchedule.isDefined =}
|
|
16
|
+
const jobSchedule = {
|
|
17
|
+
cron: "{= jobSchedule.cron =}",
|
|
18
|
+
{=# jobSchedule.args.isDefined =}
|
|
19
|
+
args: {=& jobSchedule.args.json =},
|
|
20
|
+
{=/ jobSchedule.args.isDefined =}
|
|
21
|
+
{=# jobSchedule.options.isDefined =}
|
|
22
|
+
options: {=& jobSchedule.options.json =},
|
|
23
|
+
{=/ jobSchedule.options.isDefined =}
|
|
24
|
+
{=^ jobSchedule.options.isDefined =}
|
|
25
|
+
options: {},
|
|
26
|
+
{=/ jobSchedule.options.isDefined =}
|
|
27
|
+
}
|
|
28
|
+
{=/ jobSchedule.isDefined =}
|
|
29
|
+
{=^ jobSchedule.isDefined =}
|
|
30
|
+
const jobSchedule = null
|
|
31
|
+
{=/ jobSchedule.isDefined =}
|
|
32
|
+
|
|
33
|
+
// PUBLIC API
|
|
34
|
+
export const {= jobName =} = createJobDefinition({
|
|
35
|
+
jobName: '{= jobName =}',
|
|
36
|
+
defaultJobOptions: {=& jobPerformOptions =},
|
|
37
|
+
jobSchedule,
|
|
38
|
+
entities,
|
|
39
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a definition of a job (think draft or invocable computation), not the running instance itself.
|
|
3
|
+
* This can be submitted one or more times to be executed by some job executor via the same instance.
|
|
4
|
+
* Once submitted, you get a SubmittedJob to track it later.
|
|
5
|
+
*/
|
|
6
|
+
export class Job {
|
|
7
|
+
public readonly jobName: string
|
|
8
|
+
public readonly executorName: string | symbol
|
|
9
|
+
|
|
10
|
+
constructor(jobName: string, executorName: string | symbol) {
|
|
11
|
+
this.jobName = jobName
|
|
12
|
+
this.executorName = executorName
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* This is the result of submitting a Job to some executor.
|
|
18
|
+
* It can be used by callers to track things, or call executor-specific subclass functionality.
|
|
19
|
+
*/
|
|
20
|
+
export class SubmittedJob {
|
|
21
|
+
public readonly job: Job
|
|
22
|
+
public readonly jobId: string
|
|
23
|
+
|
|
24
|
+
constructor(job: Job, jobId: string) {
|
|
25
|
+
this.job = job
|
|
26
|
+
this.jobId = jobId
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import PgBoss from 'pg-boss'
|
|
2
|
+
import { config, env } from '../../../index.js'
|
|
3
|
+
|
|
4
|
+
const boss = createPgBoss()
|
|
5
|
+
|
|
6
|
+
function createPgBoss() {
|
|
7
|
+
let pgBossNewOptions = {
|
|
8
|
+
connectionString: config.databaseUrl,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Add an escape hatch for advanced configuration of pg-boss to overwrite our defaults.
|
|
12
|
+
if (env.PG_BOSS_NEW_OPTIONS) {
|
|
13
|
+
try {
|
|
14
|
+
pgBossNewOptions = JSON.parse(env.PG_BOSS_NEW_OPTIONS)
|
|
15
|
+
} catch {
|
|
16
|
+
console.error(
|
|
17
|
+
'Environment variable PG_BOSS_NEW_OPTIONS was not parsable by JSON.parse()!'
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return new PgBoss(pgBossNewOptions)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let resolvePgBossStarted: (boss: PgBoss) => void
|
|
26
|
+
let rejectPgBossStarted: (boss: PgBoss) => void
|
|
27
|
+
// PRIVATE API
|
|
28
|
+
// Code that wants to access pg-boss must wait until it has been started.
|
|
29
|
+
export const pgBossStarted = new Promise<PgBoss>((resolve, reject) => {
|
|
30
|
+
resolvePgBossStarted = resolve
|
|
31
|
+
rejectPgBossStarted = reject
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
enum PgBossStatus {
|
|
35
|
+
Unstarted = 'Unstarted',
|
|
36
|
+
Starting = 'Starting',
|
|
37
|
+
Started = 'Started',
|
|
38
|
+
Error = 'Error',
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let pgBossStatus: PgBossStatus = PgBossStatus.Unstarted
|
|
42
|
+
|
|
43
|
+
// PRIVATE API
|
|
44
|
+
/**
|
|
45
|
+
* Prepares the target PostgreSQL database and begins job monitoring.
|
|
46
|
+
* If the required database objects do not exist in the specified database,
|
|
47
|
+
* `boss.start()` will automatically create them.
|
|
48
|
+
* Ref: https://github.com/timgit/pg-boss/blob/master/docs/readme.md#start
|
|
49
|
+
*
|
|
50
|
+
* After making this call, we can send pg-boss jobs and they will be persisted and acted upon.
|
|
51
|
+
* This should only be called once during a server's lifetime.
|
|
52
|
+
*/
|
|
53
|
+
export async function startPgBoss(): Promise<void> {
|
|
54
|
+
// Ensure pg-boss can only be started once during a server's lifetime.
|
|
55
|
+
if (pgBossStatus !== PgBossStatus.Unstarted) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
pgBossStatus = PgBossStatus.Starting
|
|
59
|
+
console.log('Starting pg-boss...')
|
|
60
|
+
|
|
61
|
+
boss.on('error', (error) => console.error(error))
|
|
62
|
+
try {
|
|
63
|
+
await boss.start()
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('pg-boss failed to start!')
|
|
66
|
+
console.error(error)
|
|
67
|
+
pgBossStatus = PgBossStatus.Error
|
|
68
|
+
rejectPgBossStarted(boss)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
resolvePgBossStarted(boss)
|
|
73
|
+
|
|
74
|
+
console.log('pg-boss started!')
|
|
75
|
+
pgBossStatus = PgBossStatus.Started
|
|
76
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import PgBoss from 'pg-boss'
|
|
2
|
+
import { pgBossStarted } from './pgBoss.js'
|
|
3
|
+
import { Job, SubmittedJob } from '../job.js'
|
|
4
|
+
import type { JSONValue, JSONObject } from 'wasp/core/serialization'
|
|
5
|
+
import { PrismaDelegate } from 'wasp/server/_types'
|
|
6
|
+
import type { JobFn } from 'wasp/server/jobs/core/pgBoss'
|
|
7
|
+
|
|
8
|
+
export const PG_BOSS_EXECUTOR_NAME = Symbol('PgBoss')
|
|
9
|
+
|
|
10
|
+
type JobSchedule = {
|
|
11
|
+
cron: Parameters<PgBoss['schedule']>[1]
|
|
12
|
+
options: Parameters<PgBoss['schedule']>[3]
|
|
13
|
+
args?: NonNullable<Parameters<PgBoss['schedule']>[2]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// PRIVATE API
|
|
17
|
+
/**
|
|
18
|
+
* Creates an instance of PgBossJob which contains all of the necessary
|
|
19
|
+
* information to submit a job to pg-boss.
|
|
20
|
+
*/
|
|
21
|
+
export function createJobDefinition<
|
|
22
|
+
Input extends JSONObject,
|
|
23
|
+
Output extends JSONValue | void,
|
|
24
|
+
Entities extends Partial<PrismaDelegate>
|
|
25
|
+
>({
|
|
26
|
+
jobName,
|
|
27
|
+
defaultJobOptions,
|
|
28
|
+
jobSchedule,
|
|
29
|
+
entities,
|
|
30
|
+
}: {
|
|
31
|
+
// jobName - The user-defined job name in their .wasp file.
|
|
32
|
+
jobName: PgBossJob<Input, Output, Entities>['jobName']
|
|
33
|
+
// defaultJobOptions - pg-boss specific options for `boss.send()` applied to every `submit()` invocation,
|
|
34
|
+
// which can overriden in that call.
|
|
35
|
+
defaultJobOptions: PgBossJob<Input, Output, Entities>['defaultJobOptions']
|
|
36
|
+
jobSchedule: PgBossJob<Input, Output, Entities>['jobSchedule']
|
|
37
|
+
// Entities used by job, passed into callback context.
|
|
38
|
+
entities: Entities
|
|
39
|
+
}) {
|
|
40
|
+
return new PgBossJob<Input, Output, Entities>(
|
|
41
|
+
jobName,
|
|
42
|
+
defaultJobOptions,
|
|
43
|
+
entities,
|
|
44
|
+
jobSchedule,
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// PRIVATE API
|
|
49
|
+
/**
|
|
50
|
+
* Uses the info about a job in PgBossJob to register a user defined job handler with pg-boss.
|
|
51
|
+
* We expect this to be called once per job name. If called multiple times with the same name and different
|
|
52
|
+
* functions, we will override the previous calls.
|
|
53
|
+
*/
|
|
54
|
+
export function registerJob<
|
|
55
|
+
Input extends JSONObject,
|
|
56
|
+
Output extends JSONValue | void,
|
|
57
|
+
Entities extends Partial<PrismaDelegate>
|
|
58
|
+
>({ job, jobFn }: {
|
|
59
|
+
job: PgBossJob<Input, Output, Entities>,
|
|
60
|
+
jobFn: JobFn<Input, Output, Entities>,
|
|
61
|
+
}) {
|
|
62
|
+
// NOTE(shayne): We are not awaiting `pgBossStarted` here since we need to return an instance to the job
|
|
63
|
+
// template, or else the NodeJS module bootstrapping process will block and fail as it would then depend
|
|
64
|
+
// on a runtime resolution of the promise in `startServer()`.
|
|
65
|
+
// Since `pgBossStarted` will resolve in the future, it may appear possible to send pg-boss
|
|
66
|
+
// a job before we actually have registered the handler via `boss.work()`. However, even if NodeJS does
|
|
67
|
+
// not execute this callback before any job `submit()` calls, this is not a problem since pg-boss allows you
|
|
68
|
+
// to submit jobs even if there are no workers registered.
|
|
69
|
+
// Once they are registered, they will just start on the first job in their queue.
|
|
70
|
+
pgBossStarted.then(async (boss) => {
|
|
71
|
+
// As a safety precaution against undefined behavior of registering different
|
|
72
|
+
// functions for the same job name, remove all registered functions first.
|
|
73
|
+
await boss.offWork(job.jobName)
|
|
74
|
+
|
|
75
|
+
// This tells pg-boss to run given worker function when job with that name is submitted.
|
|
76
|
+
// Ref: https://github.com/timgit/pg-boss/blob/master/docs/readme.md#work
|
|
77
|
+
await boss.work<Input, Output>(
|
|
78
|
+
job.jobName,
|
|
79
|
+
pgBossCallbackWrapper<Input, Output, Entities>(jobFn, job.entities)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
// If a job schedule is provided, we should schedule the recurring job.
|
|
83
|
+
// If the schedule name already exists, it's updated to the provided cron expression, arguments, and options.
|
|
84
|
+
// Ref: https://github.com/timgit/pg-boss/blob/master/docs/readme.md#scheduling
|
|
85
|
+
if (job.jobSchedule) {
|
|
86
|
+
const options: PgBoss.ScheduleOptions = {
|
|
87
|
+
...job.defaultJobOptions,
|
|
88
|
+
...job.jobSchedule.options,
|
|
89
|
+
}
|
|
90
|
+
await boss.schedule(
|
|
91
|
+
job.jobName,
|
|
92
|
+
job.jobSchedule.cron,
|
|
93
|
+
job.jobSchedule.args,
|
|
94
|
+
options
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* This is an interface repesenting a job that can be submitted to pg-boss.
|
|
102
|
+
* It is not yet submitted until the caller invokes `submit()` on an instance.
|
|
103
|
+
* The caller can make as many calls to `submit()` as they wish.
|
|
104
|
+
*/
|
|
105
|
+
export class PgBossJob<
|
|
106
|
+
Input extends JSONObject,
|
|
107
|
+
Output extends JSONValue | void,
|
|
108
|
+
Entities extends Partial<PrismaDelegate>
|
|
109
|
+
> extends Job {
|
|
110
|
+
public readonly defaultJobOptions: Parameters<PgBoss['send']>[2]
|
|
111
|
+
public readonly startAfter: number | string | Date | undefined
|
|
112
|
+
public readonly entities: Entities
|
|
113
|
+
public readonly jobSchedule: JobSchedule | null
|
|
114
|
+
|
|
115
|
+
constructor(
|
|
116
|
+
jobName: string,
|
|
117
|
+
defaultJobOptions: Parameters<PgBoss['send']>[2],
|
|
118
|
+
entities: Entities,
|
|
119
|
+
jobSchedule: JobSchedule | null,
|
|
120
|
+
startAfter?: number | string | Date
|
|
121
|
+
) {
|
|
122
|
+
super(jobName, PG_BOSS_EXECUTOR_NAME)
|
|
123
|
+
this.defaultJobOptions = defaultJobOptions
|
|
124
|
+
this.entities = entities
|
|
125
|
+
this.jobSchedule = jobSchedule
|
|
126
|
+
this.startAfter = startAfter
|
|
127
|
+
}
|
|
128
|
+
delay(startAfter: number | string | Date) {
|
|
129
|
+
return new PgBossJob<Input, Output, Entities>(
|
|
130
|
+
this.jobName,
|
|
131
|
+
this.defaultJobOptions,
|
|
132
|
+
this.entities,
|
|
133
|
+
this.jobSchedule,
|
|
134
|
+
startAfter
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
async submit(jobArgs: Input, jobOptions: Parameters<PgBoss['send']>[2] = {}) {
|
|
138
|
+
const boss = await pgBossStarted
|
|
139
|
+
const jobId = await (boss.send as any)(this.jobName, jobArgs, {
|
|
140
|
+
...this.defaultJobOptions,
|
|
141
|
+
...(this.startAfter && { startAfter: this.startAfter }),
|
|
142
|
+
...jobOptions,
|
|
143
|
+
})
|
|
144
|
+
return new PgBossSubmittedJob<Input, Output, Entities>(boss, this, jobId)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* A pg-boss specific SubmittedJob that adds additional pg-boss functionality.
|
|
150
|
+
*/
|
|
151
|
+
class PgBossSubmittedJob<
|
|
152
|
+
Input extends JSONObject,
|
|
153
|
+
Output extends JSONValue | void,
|
|
154
|
+
Entities extends Partial<PrismaDelegate>
|
|
155
|
+
> extends SubmittedJob {
|
|
156
|
+
public readonly pgBoss: {
|
|
157
|
+
readonly cancel: () => ReturnType<PgBoss['cancel']>
|
|
158
|
+
readonly resume: () => ReturnType<PgBoss['resume']>
|
|
159
|
+
readonly details: () => Promise<PgBossDetails<Input, Output> | null>
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
constructor(
|
|
163
|
+
boss: PgBoss,
|
|
164
|
+
job: PgBossJob<Input, Output, Entities>,
|
|
165
|
+
jobId: SubmittedJob['jobId']
|
|
166
|
+
) {
|
|
167
|
+
super(job, jobId)
|
|
168
|
+
this.pgBoss = {
|
|
169
|
+
cancel: () => boss.cancel(jobId),
|
|
170
|
+
resume: () => boss.resume(jobId),
|
|
171
|
+
// Coarcing here since pg-boss typings are not precise enough.
|
|
172
|
+
details: () =>
|
|
173
|
+
boss.getJobById(jobId) as Promise<PgBossDetails<Input, Output> | null>,
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Wraps the normal pg-boss callback function to inject entities, as well as extract
|
|
180
|
+
* the `data` property so the arguments passed into the job are the exact same as those received.
|
|
181
|
+
*/
|
|
182
|
+
function pgBossCallbackWrapper<
|
|
183
|
+
Input extends JSONObject,
|
|
184
|
+
Output extends JSONValue | void,
|
|
185
|
+
Entities extends Partial<PrismaDelegate>
|
|
186
|
+
>(
|
|
187
|
+
// jobFn - The user-defined async job callback function.
|
|
188
|
+
jobFn: JobFn<Input, Output, Entities>,
|
|
189
|
+
// Entities used by job, passed into callback context.
|
|
190
|
+
entities: Entities
|
|
191
|
+
) {
|
|
192
|
+
return (args: { data: Input }) => {
|
|
193
|
+
const context = { entities }
|
|
194
|
+
return jobFn(args.data, context)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Overrides the default pg-boss JobWithMetadata type to provide more
|
|
199
|
+
// type safety.
|
|
200
|
+
type PgBossDetails<
|
|
201
|
+
Input extends JSONObject,
|
|
202
|
+
Output extends JSONValue | void
|
|
203
|
+
> = Omit<PgBoss.JobWithMetadata<Input>, 'state' | 'output'> & {
|
|
204
|
+
data: Input
|
|
205
|
+
} & (
|
|
206
|
+
| {
|
|
207
|
+
state: 'completed'
|
|
208
|
+
output: JobOutputToMetadataOutput<Output>
|
|
209
|
+
}
|
|
210
|
+
| {
|
|
211
|
+
state: 'failed'
|
|
212
|
+
output: object
|
|
213
|
+
}
|
|
214
|
+
| {
|
|
215
|
+
state: 'created' | 'retry' | 'active' | 'expired' | 'cancelled'
|
|
216
|
+
output: null
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
// pg-boss wraps primitive values in an object with a `value` property.
|
|
221
|
+
// https://github.com/timgit/pg-boss/blob/master/src/manager.js#L526
|
|
222
|
+
type JobOutputToMetadataOutput<JobOutput> = JobOutput extends
|
|
223
|
+
| null
|
|
224
|
+
| undefined
|
|
225
|
+
| void
|
|
226
|
+
| Function
|
|
227
|
+
? null
|
|
228
|
+
: JobOutput extends object
|
|
229
|
+
? JobOutput
|
|
230
|
+
: { value: JobOutput }
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PrismaDelegate } from 'wasp/server/_types'
|
|
2
|
+
import type { JSONValue, JSONObject } from 'wasp/core/serialization'
|
|
3
|
+
|
|
4
|
+
// PRIVATE API
|
|
5
|
+
export type JobFn<
|
|
6
|
+
Input extends JSONObject,
|
|
7
|
+
Output extends JSONValue | void,
|
|
8
|
+
Entities extends Partial<PrismaDelegate>
|
|
9
|
+
> = (data: Input, context: { entities: Entities }) => Promise<Output>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './globalMiddleware.js'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
{=! TODO: This template is exactly the same at the moment as one for queries,
|
|
3
|
+
consider in the future if it is worth removing this duplication. =}
|
|
4
|
+
|
|
5
|
+
{=! TODO: This will generate multiple import statements even though they're
|
|
6
|
+
importing symbols from the same file. We should improve our importing machinery
|
|
7
|
+
to support multiple imports from the same file =}
|
|
8
|
+
import { prisma } from 'wasp/server'
|
|
9
|
+
import {
|
|
10
|
+
type UnauthenticatedOperationFor,
|
|
11
|
+
createUnauthenticatedOperation,
|
|
12
|
+
{=# isAuthEnabled =}
|
|
13
|
+
type AuthenticatedOperationFor,
|
|
14
|
+
createAuthenticatedOperation,
|
|
15
|
+
{=/ isAuthEnabled =}
|
|
16
|
+
} from '../wrappers.js'
|
|
17
|
+
{=# operations =}
|
|
18
|
+
{=& jsFn.importStatement =}
|
|
19
|
+
{=/ operations =}
|
|
20
|
+
{=# operations =}
|
|
21
|
+
|
|
22
|
+
// PRIVATE API
|
|
23
|
+
export type {= operationTypeName =} = typeof {= jsFn.importIdentifier =}
|
|
24
|
+
|
|
25
|
+
// PUBLIC API
|
|
26
|
+
{=# usesAuth =}
|
|
27
|
+
export const {= operationName =}: AuthenticatedOperationFor<{= operationTypeName =}> =
|
|
28
|
+
createAuthenticatedOperation(
|
|
29
|
+
{=/ usesAuth =}
|
|
30
|
+
{=^ usesAuth =}
|
|
31
|
+
export const {= operationName =}: UnauthenticatedOperationFor<{= operationTypeName =}> =
|
|
32
|
+
createUnauthenticatedOperation(
|
|
33
|
+
{=/ usesAuth =}
|
|
34
|
+
{= jsFn.importIdentifier =},
|
|
35
|
+
{
|
|
36
|
+
{=# entities =}
|
|
37
|
+
{= name =}: prisma.{= prismaIdentifier =},
|
|
38
|
+
{=/ entities =}
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
{=/ operations =}
|