@wasp.sh/wasp-cli-darwin-x64-unknown 0.20.0
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.
- package/data/Cli/starters/README.md +22 -0
- package/data/Cli/starters/basic/README.md +35 -0
- package/data/Cli/starters/basic/eslint.config.js +24 -0
- package/data/Cli/starters/basic/main.wasp +100 -0
- package/data/Cli/starters/basic/package.json +29 -0
- package/data/Cli/starters/basic/postcss.config.js +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.js +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 +18 -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/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 +78 -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 +31 -0
- package/data/Generator/templates/react-app/public/manifest.json +15 -0
- package/data/Generator/templates/react-app/src/auth/pages/OAuthCallback.tsx +93 -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 +59 -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 +28 -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.module.css +16 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Auth.tsx +94 -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.module.css +99 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Form.tsx +74 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.module.css +22 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.tsx +34 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/auth-styles.css +30 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.module.css +55 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx +291 -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 +43 -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.module.css +33 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialButton.tsx +14 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.module.css +4 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx +74 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/usernameAndPassword/useUsernameAndPassword.ts +29 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/util.ts +16 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/types.ts +77 -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 +15 -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/hooks.ts +19 -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/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 +152 -0
- package/data/Generator/templates/sdk/wasp/prisma-runtime-library.d.ts +17 -0
- package/data/Generator/templates/sdk/wasp/scripts/copy-assets.js +14 -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 +173 -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 +102 -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 +9 -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 +55 -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/views/wrong-port.ts +123 -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/data/packages/deploy/dist/common/brandedTypes.js +2 -0
- package/data/packages/deploy/dist/common/clientApp.js +26 -0
- package/data/packages/deploy/dist/common/commander.js +8 -0
- package/data/packages/deploy/dist/common/random.js +5 -0
- package/data/packages/deploy/dist/common/terminal.js +24 -0
- package/data/packages/deploy/dist/common/typeUtils.js +2 -0
- package/data/packages/deploy/dist/common/validation.js +14 -0
- package/data/packages/deploy/dist/common/waspBuild.js +21 -0
- package/data/packages/deploy/dist/common/waspProject.js +43 -0
- package/data/packages/deploy/dist/common/zx.js +10 -0
- package/data/packages/deploy/dist/index.js +30 -0
- package/data/packages/deploy/dist/providers/fly/CommonCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/CommonOps.js +36 -0
- package/data/packages/deploy/dist/providers/fly/DeploymentInstructions.js +12 -0
- package/data/packages/deploy/dist/providers/fly/commands/cmd/CmdCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/commands/cmd/cmd.js +29 -0
- package/data/packages/deploy/dist/providers/fly/commands/createDb/CreateDbCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/commands/createDb/createDb.js +55 -0
- package/data/packages/deploy/dist/providers/fly/commands/deploy/DeployCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/commands/deploy/deploy.js +88 -0
- package/data/packages/deploy/dist/providers/fly/commands/launch/LaunchCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/commands/launch/launch.js +17 -0
- package/data/packages/deploy/dist/providers/fly/commands/setup/SetupCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/fly/commands/setup/setup.js +141 -0
- package/data/packages/deploy/dist/providers/fly/flyAppUrl.js +4 -0
- package/data/packages/deploy/dist/providers/fly/flyCli.js +74 -0
- package/data/packages/deploy/dist/providers/fly/index.js +121 -0
- package/data/packages/deploy/dist/providers/fly/jsonOutputSchemas.js +37 -0
- package/data/packages/deploy/dist/providers/fly/tomlFile.js +65 -0
- package/data/packages/deploy/dist/providers/railway/DeploymentInstructions.js +11 -0
- package/data/packages/deploy/dist/providers/railway/brandedTypes.js +2 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/DeployCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/client.js +22 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/common.js +40 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/index.js +57 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/server.js +17 -0
- package/data/packages/deploy/dist/providers/railway/commands/launch/LaunchCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/railway/commands/launch/launch.js +9 -0
- package/data/packages/deploy/dist/providers/railway/commands/setup/SetupCmdOptions.js +2 -0
- package/data/packages/deploy/dist/providers/railway/commands/setup/setup.js +146 -0
- package/data/packages/deploy/dist/providers/railway/index.js +83 -0
- package/data/packages/deploy/dist/providers/railway/jsonOutputSchemas.js +19 -0
- package/data/packages/deploy/dist/providers/railway/ports.js +6 -0
- package/data/packages/deploy/dist/providers/railway/railwayCli.js +85 -0
- package/data/packages/deploy/dist/providers/railway/railwayProject/RailwayProject.js +14 -0
- package/data/packages/deploy/dist/providers/railway/railwayProject/cli.js +80 -0
- package/data/packages/deploy/dist/providers/railway/railwayProject/index.js +48 -0
- package/data/packages/deploy/dist/providers/railway/railwayService/nameGenerator.js +24 -0
- package/data/packages/deploy/dist/providers/railway/railwayService/url.js +32 -0
- package/data/packages/deploy/package-lock.json +3536 -0
- package/data/packages/deploy/package.json +29 -0
- package/data/packages/prisma/dist/format.js +35 -0
- package/data/packages/prisma/dist/index.js +33 -0
- package/data/packages/prisma/package-lock.json +5101 -0
- package/data/packages/prisma/package.json +30 -0
- package/data/packages/studio/dist/index.js +48 -0
- package/data/packages/studio/dist/public/assets/Flow-b5112d3d.js +26 -0
- package/data/packages/studio/dist/public/assets/index-17ce6ed4.css +1 -0
- package/data/packages/studio/dist/public/assets/index-62a9d21a.js +120 -0
- package/data/packages/studio/dist/public/index.html +14 -0
- package/data/packages/studio/package-lock.json +1866 -0
- package/data/packages/studio/package.json +33 -0
- package/data/packages/ts-inspect/dist/exports.js +82 -0
- package/data/packages/ts-inspect/dist/index.js +28 -0
- package/data/packages/ts-inspect/package-lock.json +4947 -0
- package/data/packages/ts-inspect/package.json +31 -0
- package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.d.ts +2 -0
- package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.js +59 -0
- package/data/packages/wasp-config/dist/__tests__/cli.unit.test.d.ts +2 -0
- package/data/packages/wasp-config/dist/__tests__/cli.unit.test.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/cli.unit.test.js +65 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.d.ts +2 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.js +126 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.d.ts +2 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.js +743 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.d.ts +224 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.js +656 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.d.ts +2 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.js +57 -0
- package/data/packages/wasp-config/dist/src/_private.d.ts +2 -0
- package/data/packages/wasp-config/dist/src/_private.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/_private.js +1 -0
- package/data/packages/wasp-config/dist/src/appAnalyzer.d.ts +16 -0
- package/data/packages/wasp-config/dist/src/appAnalyzer.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/appAnalyzer.js +34 -0
- package/data/packages/wasp-config/dist/src/appSpec.d.ts +223 -0
- package/data/packages/wasp-config/dist/src/appSpec.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/appSpec.js +6 -0
- package/data/packages/wasp-config/dist/src/branded.d.ts +7 -0
- package/data/packages/wasp-config/dist/src/branded.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/branded.js +1 -0
- package/data/packages/wasp-config/dist/src/cli.d.ts +6 -0
- package/data/packages/wasp-config/dist/src/cli.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/cli.js +24 -0
- package/data/packages/wasp-config/dist/src/index.d.ts +8 -0
- package/data/packages/wasp-config/dist/src/index.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/index.js +1 -0
- package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.d.ts +38 -0
- package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.js +294 -0
- package/data/packages/wasp-config/dist/src/publicApi/App.d.ts +24 -0
- package/data/packages/wasp-config/dist/src/publicApi/App.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/publicApi/App.js +75 -0
- package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts +171 -0
- package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.js +1 -0
- package/data/packages/wasp-config/dist/src/run.d.ts +3 -0
- package/data/packages/wasp-config/dist/src/run.d.ts.map +1 -0
- package/data/packages/wasp-config/dist/src/run.js +18 -0
- package/data/packages/wasp-config/package-lock.json +3992 -0
- package/data/packages/wasp-config/package.json +39 -0
- package/main.js +9 -0
- package/package.json +1 -0
- package/readme.md +3 -0
- package/wasp-bin +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useAction, useQuery } from "../operations"
|
|
2
|
+
import type { Query, Action } from "../operations/rpc"
|
|
3
|
+
import type { Tail } from "../../universal/types"
|
|
4
|
+
|
|
5
|
+
// PRIVATE API
|
|
6
|
+
export function makeUseQueryFor<Input, Output>(
|
|
7
|
+
query: Query<Input, Output>
|
|
8
|
+
) {
|
|
9
|
+
return (
|
|
10
|
+
...rest: Tail<Parameters<typeof useQuery<Input, Output>>>
|
|
11
|
+
) => useQuery<Input, Output>(query, ...rest);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// PRIVATE API
|
|
15
|
+
export function makeUseActionFor<Input = unknown, Output = unknown>(
|
|
16
|
+
action: Action<Input, Output>
|
|
17
|
+
) {
|
|
18
|
+
return (
|
|
19
|
+
...rest: Tail<Parameters<typeof useAction<Input, Output>>>
|
|
20
|
+
) => useAction<Input, Output>(action, ...rest);
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import * as z from 'zod'
|
|
3
|
+
|
|
4
|
+
{=# envValidationSchema.isDefined =}
|
|
5
|
+
{=& envValidationSchema.importStatement =}
|
|
6
|
+
const userClientEnvSchema = {= envValidationSchema.importIdentifier =}
|
|
7
|
+
{=/ envValidationSchema.isDefined =}
|
|
8
|
+
{=^ envValidationSchema.isDefined =}
|
|
9
|
+
const userClientEnvSchema = z.object({})
|
|
10
|
+
{=/ envValidationSchema.isDefined =}
|
|
11
|
+
|
|
12
|
+
const waspClientEnvSchema = z.object({
|
|
13
|
+
"{= serverUrlEnvVarName =}": z
|
|
14
|
+
.string()
|
|
15
|
+
.url({
|
|
16
|
+
message: '{= serverUrlEnvVarName =} must be a valid URL',
|
|
17
|
+
})
|
|
18
|
+
.default('{= defaultServerUrl =}'),
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
// PRIVATE API (sdk, Vite config)
|
|
22
|
+
export const clientEnvSchema = userClientEnvSchema.merge(waspClientEnvSchema)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// PRIVATE API (sdk, web-app)
|
|
4
|
+
/**
|
|
5
|
+
* Hook to avoid running effect twice when using React's `StrictMode` in development mode.
|
|
6
|
+
* React renders each component twice in development mode to detect potential effect clean up
|
|
7
|
+
* issues. Wasp relies on some effects triggering only once, for example, OAuth token exchange
|
|
8
|
+
* or e-mail verification.
|
|
9
|
+
*/
|
|
10
|
+
export function useEffectOnce(callback: () => void) {
|
|
11
|
+
const hasRun = useRef(false);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!hasRun.current) {
|
|
15
|
+
callback();
|
|
16
|
+
hasRun.current = true;
|
|
17
|
+
}
|
|
18
|
+
}, [callback]);
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// PUBLIC API
|
|
2
|
+
// NOTE: This is enough to cover Operations and our APIs (src/Wasp/AppSpec/Api.hs).
|
|
3
|
+
export enum HttpMethod {
|
|
4
|
+
Get = 'GET',
|
|
5
|
+
Post = 'POST',
|
|
6
|
+
Put = 'PUT',
|
|
7
|
+
Delete = 'DELETE',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// PUBLIC API
|
|
11
|
+
export type Route = { method: HttpMethod; path: string }
|
|
12
|
+
|
|
13
|
+
// PUBLIC API
|
|
14
|
+
export { config, ClientConfig } from './config.js'
|
|
15
|
+
|
|
16
|
+
// PUBLIC API
|
|
17
|
+
export { env } from './env.js'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { _Awaited, _ReturnType } from 'wasp/universal/types'
|
|
2
|
+
import type { OperationRpcFor, GenericBackendOperation } from '../rpc.js'
|
|
3
|
+
import { callOperation, makeOperationRoute } from '../internal/index.js'
|
|
4
|
+
import {
|
|
5
|
+
registerActionInProgress,
|
|
6
|
+
registerActionDone,
|
|
7
|
+
} from '../internal/resources.js'
|
|
8
|
+
|
|
9
|
+
// PRIVATE API
|
|
10
|
+
export function createAction<BackendAction extends GenericBackendOperation>(
|
|
11
|
+
relativeActionRoute: string,
|
|
12
|
+
entitiesUsed: unknown[]
|
|
13
|
+
): ActionFor<BackendAction> {
|
|
14
|
+
const actionRoute = makeOperationRoute(relativeActionRoute)
|
|
15
|
+
|
|
16
|
+
async function internalAction(args, specificOptimisticUpdateDefinitions) {
|
|
17
|
+
registerActionInProgress(specificOptimisticUpdateDefinitions)
|
|
18
|
+
try {
|
|
19
|
+
// The `return await` is not redundant here. If we removed the await, the
|
|
20
|
+
// `finally` block would execute before the action finishes, prematurely
|
|
21
|
+
// registering the action as done.
|
|
22
|
+
return await callOperation(actionRoute, args)
|
|
23
|
+
} finally {
|
|
24
|
+
await registerActionDone(entitiesUsed, specificOptimisticUpdateDefinitions)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// We expose (and document) a restricted version of the API for our users,
|
|
29
|
+
// while also attaching the full "internal" API to the exposed action. By
|
|
30
|
+
// doing this, we can easily use the internal API of an action a users passes
|
|
31
|
+
// into our system (e.g., through the `useAction` hook) without needing a
|
|
32
|
+
// lookup table.
|
|
33
|
+
//
|
|
34
|
+
// While it does technically allow our users to access the interal API, it
|
|
35
|
+
// shouldn't be a problem in practice. Still, if it turns out to be a problem,
|
|
36
|
+
// we can always hide it using a Symbol.
|
|
37
|
+
const action = (args) => internalAction(args, [])
|
|
38
|
+
action.internal = internalAction
|
|
39
|
+
|
|
40
|
+
// NOTE: I'm not sure why unknown is necessary here,
|
|
41
|
+
// it might have something to do with functions allowing evolving types,
|
|
42
|
+
// // while objects to not:
|
|
43
|
+
// https://www.typescriptlang.org/play/?#code/MYewdgzgLgBCBGArGBeGBvGBDAXDA5AGYgj4wC+AUAogHTyoHxYBO+llA9JzIQK5hgUAJbhsAG3EgA7hGxgYAUwBuIccuFgA5jCgBPAA6KY8PrBqKhMACYhFcsCCiVQkWPwVoAFAEpUAPgJiUkoPekZ8ZjYgA
|
|
44
|
+
return action as unknown as ActionFor<BackendAction>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// PRIVATE API
|
|
48
|
+
export type ActionFor<BackendAction extends GenericBackendOperation> =
|
|
49
|
+
OperationRpcFor<BackendAction>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import { type ActionFor, createAction } from './core'
|
|
3
|
+
{=# actions =}
|
|
4
|
+
{=& operationTypeImportStmt =}
|
|
5
|
+
{=/ actions =}
|
|
6
|
+
{=# actions =}
|
|
7
|
+
|
|
8
|
+
// PUBLIC API
|
|
9
|
+
export const {= operationName =}: ActionFor<{= operationTypeName =}> = createAction<{= operationTypeName =}>(
|
|
10
|
+
'{= actionRoute =}',
|
|
11
|
+
{=& entitiesArray =},
|
|
12
|
+
)
|
|
13
|
+
{=/ actions =}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import {
|
|
2
|
+
QueryClient,
|
|
3
|
+
QueryKey,
|
|
4
|
+
useMutation,
|
|
5
|
+
UseMutationOptions,
|
|
6
|
+
useQueryClient,
|
|
7
|
+
useQuery as rqUseQuery,
|
|
8
|
+
UseQueryResult,
|
|
9
|
+
} from "@tanstack/react-query";
|
|
10
|
+
import { Action, Query } from "./rpc";
|
|
11
|
+
import { makeQueryCacheKey } from "./queries/core";
|
|
12
|
+
export { configureQueryClient } from "./queryClient";
|
|
13
|
+
|
|
14
|
+
// PUBLIC API
|
|
15
|
+
export function useQuery<Input, Output>(
|
|
16
|
+
query: Query<Input, Output>,
|
|
17
|
+
queryFnArgs?: Input,
|
|
18
|
+
options?: any
|
|
19
|
+
): UseQueryResult<Output, Error> {
|
|
20
|
+
if (typeof query !== 'function') {
|
|
21
|
+
throw new TypeError('useQuery requires queryFn to be a function.')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!query.queryCacheKey) {
|
|
25
|
+
throw new TypeError('queryFn needs to have queryCacheKey property defined.')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return rqUseQuery({
|
|
29
|
+
// todo: The full queryCacheKey is constructed in two places, both here and
|
|
30
|
+
// inside the Query. See https://github.com/wasp-lang/wasp/issues/2017
|
|
31
|
+
// FIXME: query fns don't handle the `undefined` case correctly
|
|
32
|
+
// https://github.com/wasp-lang/wasp/issues/2017
|
|
33
|
+
queryKey: makeQueryCacheKey(query, (queryFnArgs as Input)),
|
|
34
|
+
// FIXME: query fns don't handle the `undefined` case correctly
|
|
35
|
+
// https://github.com/wasp-lang/wasp/issues/2017
|
|
36
|
+
queryFn: () => query(queryFnArgs as Input),
|
|
37
|
+
...options,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// PUBLIC API
|
|
42
|
+
/**
|
|
43
|
+
* A hook for adding extra behavior to a Wasp Action (e.g., optimistic updates).
|
|
44
|
+
*
|
|
45
|
+
* @param actionFn The Wasp Action you wish to enhance/decorate.
|
|
46
|
+
* @param actionOptions An options object for enhancing/decorating the given Action.
|
|
47
|
+
* @returns A decorated Action with added behavior but an unchanged API.
|
|
48
|
+
*/
|
|
49
|
+
export function useAction<Input = unknown, Output = unknown>(
|
|
50
|
+
actionFn: Action<Input, Output>,
|
|
51
|
+
actionOptions?: ActionOptions<Input>
|
|
52
|
+
): typeof actionFn {
|
|
53
|
+
const queryClient = useQueryClient();
|
|
54
|
+
|
|
55
|
+
let mutationFn = actionFn;
|
|
56
|
+
let options = {};
|
|
57
|
+
if (actionOptions?.optimisticUpdates) {
|
|
58
|
+
const optimisticUpdatesDefinitions = actionOptions.optimisticUpdates.map(
|
|
59
|
+
translateToInternalDefinition
|
|
60
|
+
);
|
|
61
|
+
mutationFn = makeOptimisticUpdateMutationFn(
|
|
62
|
+
actionFn,
|
|
63
|
+
optimisticUpdatesDefinitions
|
|
64
|
+
);
|
|
65
|
+
options = makeRqOptimisticUpdateOptions(
|
|
66
|
+
queryClient,
|
|
67
|
+
optimisticUpdatesDefinitions
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// NOTE: We decided to hide React Query's extra mutation features (e.g.,
|
|
72
|
+
// isLoading, onSuccess and onError callbacks, synchronous mutate) and only
|
|
73
|
+
// expose a simple async function whose API matches the original Action.
|
|
74
|
+
// We did this to avoid cluttering the API with stuff we're not sure we need
|
|
75
|
+
// yet (e.g., isLoading), to postpone the action vs mutation dilemma, and to
|
|
76
|
+
// clearly separate our opinionated API from React Query's lower-level
|
|
77
|
+
// advanced API (which users can also use)
|
|
78
|
+
const mutation = useMutation(mutationFn, options);
|
|
79
|
+
|
|
80
|
+
// This assertion is necessary because, when the Input is void, we want to
|
|
81
|
+
// present the function as not accepting a payload (which isn't consistent
|
|
82
|
+
// with how it's defined).
|
|
83
|
+
return ((args: Input) => mutation.mutateAsync(args)) as typeof actionFn;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// PUBLIC API
|
|
87
|
+
// todo: Improve this type. Details here:
|
|
88
|
+
// https://github.com/wasp-lang/wasp/issues/2017
|
|
89
|
+
/**
|
|
90
|
+
* A documented (public) way to define optimistic updates.
|
|
91
|
+
*/
|
|
92
|
+
export type OptimisticUpdateDefinition<ActionInput, CachedData> = {
|
|
93
|
+
getQuerySpecifier: GetQuerySpecifier<ActionInput, CachedData>;
|
|
94
|
+
updateQuery: UpdateQuery<ActionInput, CachedData>;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* An options object passed into the `useAction` hook and used to enhance the
|
|
99
|
+
* action with extra options.
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
type ActionOptions<ActionInput> = {
|
|
103
|
+
optimisticUpdates: OptimisticUpdateDefinition<ActionInput, any>[];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A function that takes an item and returns a Wasp Query specifier.
|
|
108
|
+
*/
|
|
109
|
+
type GetQuerySpecifier<ActionInput, CachedData> = (
|
|
110
|
+
item: ActionInput
|
|
111
|
+
) => QuerySpecifier<unknown, CachedData>;
|
|
112
|
+
|
|
113
|
+
// todo: Improve the type's signature for when the cache is empty. Details here:
|
|
114
|
+
// https://github.com/wasp-lang/wasp/issues/2017
|
|
115
|
+
/**
|
|
116
|
+
* A function that takes an item and the previous state of the cache, and returns
|
|
117
|
+
* the desired (new) state of the cache.
|
|
118
|
+
*/
|
|
119
|
+
type UpdateQuery<ActionInput, CachedData> = (
|
|
120
|
+
item: ActionInput,
|
|
121
|
+
oldData: CachedData | undefined
|
|
122
|
+
) => CachedData;
|
|
123
|
+
|
|
124
|
+
// todo: Improve this type signature. Details here:
|
|
125
|
+
// https://github.com/wasp-lang/wasp/issues/2017
|
|
126
|
+
/**
|
|
127
|
+
* A public query specifier used for addressing Wasp queries. See our docs for details:
|
|
128
|
+
* https://wasp.sh/docs/language/features#the-useaction-hook.
|
|
129
|
+
*/
|
|
130
|
+
type QuerySpecifier<Input, Output> = [Query<Input, Output>, ...any[]];
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* An internal (undocumented, private, desugared) way of defining optimistic updates.
|
|
134
|
+
*/
|
|
135
|
+
type InternalOptimisticUpdateDefinition<ActionInput, CachedData> = {
|
|
136
|
+
getQueryKey: (item: ActionInput) => QueryKey;
|
|
137
|
+
updateQuery: UpdateQuery<ActionInput, CachedData>;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* An UpdateQuery function "instantiated" with a specific item. It only takes
|
|
142
|
+
* the current state of the cache and returns the desired (new) state of the
|
|
143
|
+
* cache.
|
|
144
|
+
*/
|
|
145
|
+
type SpecificUpdateQuery<CachedData> = (oldData: CachedData | undefined) => CachedData;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* A specific, "instantiated" optimistic update definition which contains a
|
|
149
|
+
* fully-constructed query key and a specific update function.
|
|
150
|
+
*/
|
|
151
|
+
type SpecificOptimisticUpdateDefinition<Item> = {
|
|
152
|
+
queryKey: QueryKey;
|
|
153
|
+
updateQuery: SpecificUpdateQuery<Item>;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type InternalAction<Input, Output> = Action<Input, Output> & {
|
|
157
|
+
internal<CachedData extends unknown>(
|
|
158
|
+
item: Input,
|
|
159
|
+
optimisticUpdateDefinitions: SpecificOptimisticUpdateDefinition<CachedData>[]
|
|
160
|
+
): Promise<Output>;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Translates/Desugars a public optimistic update definition object into a
|
|
165
|
+
* definition object our system uses internally.
|
|
166
|
+
*
|
|
167
|
+
* @param publicOptimisticUpdateDefinition An optimistic update definition
|
|
168
|
+
* object that's a part of the public API:
|
|
169
|
+
* https://wasp.sh/docs/language/features#the-useaction-hook.
|
|
170
|
+
* @returns An internally-used optimistic update definition object.
|
|
171
|
+
*/
|
|
172
|
+
function translateToInternalDefinition<Item, CachedData>(
|
|
173
|
+
publicOptimisticUpdateDefinition: OptimisticUpdateDefinition<Item, CachedData>
|
|
174
|
+
): InternalOptimisticUpdateDefinition<Item, CachedData> {
|
|
175
|
+
const { getQuerySpecifier, updateQuery } = publicOptimisticUpdateDefinition;
|
|
176
|
+
|
|
177
|
+
const definitionErrors: string[] = [];
|
|
178
|
+
if (typeof getQuerySpecifier !== "function") {
|
|
179
|
+
definitionErrors.push("`getQuerySpecifier` is not a function.");
|
|
180
|
+
}
|
|
181
|
+
if (typeof updateQuery !== "function") {
|
|
182
|
+
definitionErrors.push("`updateQuery` is not a function.");
|
|
183
|
+
}
|
|
184
|
+
if (definitionErrors.length) {
|
|
185
|
+
throw new TypeError(
|
|
186
|
+
`Invalid optimistic update definition: ${definitionErrors.join(", ")}.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
getQueryKey: (item) => getRqQueryKeyFromSpecifier(getQuerySpecifier(item)),
|
|
192
|
+
updateQuery,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Creates a function that performs an action while telling it about the
|
|
198
|
+
* optimistic updates it caused.
|
|
199
|
+
*
|
|
200
|
+
* @param actionFn The Wasp Action.
|
|
201
|
+
* @param optimisticUpdateDefinitions The optimisitc updates the action causes.
|
|
202
|
+
* @returns An decorated action which performs optimistic updates.
|
|
203
|
+
*/
|
|
204
|
+
function makeOptimisticUpdateMutationFn<Input, Output, CachedData>(
|
|
205
|
+
actionFn: Action<Input, Output>,
|
|
206
|
+
optimisticUpdateDefinitions: InternalOptimisticUpdateDefinition<
|
|
207
|
+
Input,
|
|
208
|
+
CachedData
|
|
209
|
+
>[]
|
|
210
|
+
): typeof actionFn {
|
|
211
|
+
return (function performActionWithOptimisticUpdates(item: Input) {
|
|
212
|
+
const specificOptimisticUpdateDefinitions = optimisticUpdateDefinitions.map(
|
|
213
|
+
(generalDefinition) =>
|
|
214
|
+
getOptimisticUpdateDefinitionForSpecificItem(generalDefinition, item)
|
|
215
|
+
);
|
|
216
|
+
return (actionFn as InternalAction<Input, Output>).internal(
|
|
217
|
+
item,
|
|
218
|
+
specificOptimisticUpdateDefinitions
|
|
219
|
+
);
|
|
220
|
+
// This assertion is necessary because, when the Input is void, we want to
|
|
221
|
+
// present the function as not accepting a payload (which isn't consistent
|
|
222
|
+
// with how it's defined).
|
|
223
|
+
}) as typeof actionFn;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Given a ReactQuery query client and our internal definition of optimistic
|
|
228
|
+
* updates, this function constructs an object describing those same optimistic
|
|
229
|
+
* updates in a format we can pass into React Query's useMutation hook. In other
|
|
230
|
+
* words, it translates our optimistic updates definition into React Query's
|
|
231
|
+
* optimistic updates definition. Check their docs for details:
|
|
232
|
+
* https://tanstack.com/query/v4/docs/guides/optimistic-updates?from=reactQueryV3&original=https://react-query-v3.tanstack.com/guides/optimistic-updates
|
|
233
|
+
*
|
|
234
|
+
* @param queryClient The QueryClient instance used by React Query.
|
|
235
|
+
* @param optimisticUpdateDefinitions A list containing internal optimistic
|
|
236
|
+
* updates definition objects (i.e., a list where each object carries the
|
|
237
|
+
* instructions for performing particular optimistic update).
|
|
238
|
+
* @returns An object containing 'onMutate' and 'onError' functions
|
|
239
|
+
* corresponding to the given optimistic update definitions (check the docs
|
|
240
|
+
* linked above for details).
|
|
241
|
+
*/
|
|
242
|
+
function makeRqOptimisticUpdateOptions<ActionInput, CachedData>(
|
|
243
|
+
queryClient: QueryClient,
|
|
244
|
+
optimisticUpdateDefinitions: InternalOptimisticUpdateDefinition<
|
|
245
|
+
ActionInput,
|
|
246
|
+
CachedData
|
|
247
|
+
>[]
|
|
248
|
+
): Pick<UseMutationOptions, "onMutate" | "onError"> {
|
|
249
|
+
async function onMutate(item) {
|
|
250
|
+
const specificOptimisticUpdateDefinitions = optimisticUpdateDefinitions.map(
|
|
251
|
+
(generalDefinition) =>
|
|
252
|
+
getOptimisticUpdateDefinitionForSpecificItem(generalDefinition, item)
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// Cancel any outgoing refetches (so they don't overwrite our optimistic update).
|
|
256
|
+
// Theoretically, we can be a bit faster. Instead of awaiting the
|
|
257
|
+
// cancellation of all queries, we could cancel and update them in parallel.
|
|
258
|
+
// However, awaiting cancellation hasn't yet proven to be a performance bottleneck.
|
|
259
|
+
await Promise.all(
|
|
260
|
+
specificOptimisticUpdateDefinitions.map(({ queryKey }) =>
|
|
261
|
+
queryClient.cancelQueries(queryKey)
|
|
262
|
+
)
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
// We're using a Map to correctly serialize query keys that contain objects.
|
|
266
|
+
const previousData: Map<QueryKey, CachedData | undefined> = new Map();
|
|
267
|
+
specificOptimisticUpdateDefinitions.forEach(({ queryKey, updateQuery }) => {
|
|
268
|
+
// Snapshot the currently cached value.
|
|
269
|
+
const previousDataForQuery: CachedData | undefined =
|
|
270
|
+
queryClient.getQueryData(queryKey);
|
|
271
|
+
|
|
272
|
+
// Attempt to optimistically update the cache using the new value.
|
|
273
|
+
try {
|
|
274
|
+
queryClient.setQueryData(queryKey, updateQuery);
|
|
275
|
+
} catch (e) {
|
|
276
|
+
console.error(
|
|
277
|
+
"The `updateQuery` function threw an exception, skipping optimistic update:"
|
|
278
|
+
);
|
|
279
|
+
console.error(e);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Remember the snapshotted value to restore in case of an error.
|
|
283
|
+
previousData.set(queryKey, previousDataForQuery);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
return { previousData };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function onError(_err, _item, context) {
|
|
290
|
+
// All we do in case of an error is roll back all optimistic updates. We ensure
|
|
291
|
+
// not to do anything else because React Query rethrows the error. This allows
|
|
292
|
+
// the programmer to handle the error as they usually would (i.e., we want the
|
|
293
|
+
// error handling to work as it would if the programmer wasn't using optimistic
|
|
294
|
+
// updates).
|
|
295
|
+
context.previousData.forEach(async (data, queryKey) => {
|
|
296
|
+
await queryClient.cancelQueries(queryKey);
|
|
297
|
+
queryClient.setQueryData(queryKey, data);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
onMutate,
|
|
303
|
+
onError,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Constructs the definition for optimistically updating a specific item. It
|
|
309
|
+
* uses a closure over the updated item to construct an item-specific query key
|
|
310
|
+
* (e.g., useful when the query key depends on an ID).
|
|
311
|
+
*
|
|
312
|
+
* @param optimisticUpdateDefinition The general, "uninstantiated" optimistic
|
|
313
|
+
* update definition with a function for constructing the query key.
|
|
314
|
+
* @param item The item triggering the Action/optimistic update (i.e., the
|
|
315
|
+
* argument passed to the Action).
|
|
316
|
+
* @returns A specific optimistic update definition which corresponds to the
|
|
317
|
+
* provided definition and closes over the provided item.
|
|
318
|
+
*/
|
|
319
|
+
function getOptimisticUpdateDefinitionForSpecificItem<ActionInput, CachedData>(
|
|
320
|
+
optimisticUpdateDefinition: InternalOptimisticUpdateDefinition<
|
|
321
|
+
ActionInput,
|
|
322
|
+
CachedData
|
|
323
|
+
>,
|
|
324
|
+
item: ActionInput
|
|
325
|
+
): SpecificOptimisticUpdateDefinition<CachedData> {
|
|
326
|
+
const { getQueryKey, updateQuery } = optimisticUpdateDefinition;
|
|
327
|
+
return {
|
|
328
|
+
queryKey: getQueryKey(item),
|
|
329
|
+
updateQuery: (old) => updateQuery(item, old),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// todo: Address the duplication between this function and the one in
|
|
334
|
+
// queries/core.ts. Details here: https://github.com/wasp-lang/wasp/issues/2017
|
|
335
|
+
/**
|
|
336
|
+
* Translates a Wasp query specifier to a query cache key used by React Query.
|
|
337
|
+
*
|
|
338
|
+
* @param querySpecifier A query specifier that's a part of the public API:
|
|
339
|
+
* https://wasp.sh/docs/language/features#the-useaction-hook.
|
|
340
|
+
* @returns A cache key React Query internally uses for addressing queries.
|
|
341
|
+
*/
|
|
342
|
+
function getRqQueryKeyFromSpecifier(
|
|
343
|
+
querySpecifier: QuerySpecifier<unknown, unknown>
|
|
344
|
+
): QueryKey {
|
|
345
|
+
const [queryFn, ...otherKeys] = querySpecifier;
|
|
346
|
+
return [...(queryFn as any).queryCacheKey, ...otherKeys];
|
|
347
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// PUBLIC API
|
|
2
|
+
export * from './actions'
|
|
3
|
+
// MOSTLY PUBLIC API (see the file for details)
|
|
4
|
+
export * from './queries'
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
// PUBLIC API
|
|
8
|
+
useAction,
|
|
9
|
+
// PUBLIC API
|
|
10
|
+
useQuery,
|
|
11
|
+
// PUBLIC API
|
|
12
|
+
type OptimisticUpdateDefinition,
|
|
13
|
+
} from './hooks'
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
// PUBLIC API
|
|
17
|
+
configureQueryClient,
|
|
18
|
+
// PRIVATE API (framework code)
|
|
19
|
+
initializeQueryClient,
|
|
20
|
+
// PRIVATE API (framework code)
|
|
21
|
+
queryClientInitialized
|
|
22
|
+
} from './queryClient'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { api, handleApiError } from 'wasp/client/api'
|
|
2
|
+
import { HttpMethod } from 'wasp/client'
|
|
3
|
+
import { serialize, deserialize } from 'wasp/core/serialization'
|
|
4
|
+
|
|
5
|
+
// PRIVATE API
|
|
6
|
+
export type OperationRoute = { method: HttpMethod.Post, path: string }
|
|
7
|
+
|
|
8
|
+
// PRIVATE API
|
|
9
|
+
export async function callOperation(operationRoute: OperationRoute, args: any) {
|
|
10
|
+
try {
|
|
11
|
+
const serializedArgs = serialize(args)
|
|
12
|
+
const response = await api.post(operationRoute.path, serializedArgs)
|
|
13
|
+
return deserialize(response.data)
|
|
14
|
+
} catch (error) {
|
|
15
|
+
throw handleApiError(error)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// PRIVATE API
|
|
20
|
+
export function makeOperationRoute(relativeOperationRoute: string): OperationRoute {
|
|
21
|
+
return { method: HttpMethod.Post, path: `/${relativeOperationRoute}` }
|
|
22
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { queryClientInitialized } from '../queryClient.js'
|
|
2
|
+
import { makeUpdateHandlersMap } from './updateHandlersMap'
|
|
3
|
+
import { hashQueryKey } from '@tanstack/react-query'
|
|
4
|
+
|
|
5
|
+
// Map where key is resource name and value is Set
|
|
6
|
+
// containing query ids of all the queries that use
|
|
7
|
+
// that resource.
|
|
8
|
+
const resourceToQueryCacheKeys = new Map()
|
|
9
|
+
|
|
10
|
+
const updateHandlers = makeUpdateHandlersMap(hashQueryKey)
|
|
11
|
+
|
|
12
|
+
// PRIVATE API
|
|
13
|
+
/**
|
|
14
|
+
* Remembers that specified query is using specified resources.
|
|
15
|
+
* If called multiple times for same query, resources are added, not reset.
|
|
16
|
+
* @param {string[]} queryCacheKey - Unique key under used to identify query in the cache.
|
|
17
|
+
* @param {string[]} resources - Names of resources that query is using.
|
|
18
|
+
*/
|
|
19
|
+
export function addResourcesUsedByQuery(queryCacheKey, resources) {
|
|
20
|
+
for (const resource of resources) {
|
|
21
|
+
let cacheKeys = resourceToQueryCacheKeys.get(resource)
|
|
22
|
+
if (!cacheKeys) {
|
|
23
|
+
cacheKeys = new Set()
|
|
24
|
+
resourceToQueryCacheKeys.set(resource, cacheKeys)
|
|
25
|
+
}
|
|
26
|
+
cacheKeys.add(queryCacheKey)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function registerActionInProgress(optimisticUpdateTuples) {
|
|
31
|
+
optimisticUpdateTuples.forEach(
|
|
32
|
+
({ queryKey, updateQuery }) => updateHandlers.add(queryKey, updateQuery)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function registerActionDone(resources, optimisticUpdateTuples) {
|
|
37
|
+
optimisticUpdateTuples.forEach(({ queryKey }) => updateHandlers.remove(queryKey))
|
|
38
|
+
await invalidateQueriesUsing(resources)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getActiveOptimisticUpdates(queryKey) {
|
|
42
|
+
return updateHandlers.getUpdateHandlers(queryKey)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function invalidateAndRemoveQueries() {
|
|
46
|
+
const queryClient = await queryClientInitialized
|
|
47
|
+
// If we don't reset the queries before removing them, Wasp will stay on
|
|
48
|
+
// the same page. The user would have to manually refresh the page to "finish"
|
|
49
|
+
// logging out.
|
|
50
|
+
// When a query is removed, the `Observer` is removed as well, and the components
|
|
51
|
+
// that are using the query are not re-rendered. This is why we need to reset
|
|
52
|
+
// the queries, so that the `Observer` is re-created and the components are re-rendered.
|
|
53
|
+
// For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125
|
|
54
|
+
queryClient.resetQueries()
|
|
55
|
+
// If we don't remove the queries after invalidating them, the old query data
|
|
56
|
+
// remains in the cache, casuing a potential privacy issue.
|
|
57
|
+
queryClient.removeQueries()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Invalidates all queries that are using specified resources.
|
|
62
|
+
* @param {string[]} resources - Names of resources.
|
|
63
|
+
*/
|
|
64
|
+
async function invalidateQueriesUsing(resources) {
|
|
65
|
+
const queryClient = await queryClientInitialized
|
|
66
|
+
|
|
67
|
+
const queryCacheKeysToInvalidate = getQueriesUsingResources(resources)
|
|
68
|
+
queryCacheKeysToInvalidate.forEach(
|
|
69
|
+
queryCacheKey => queryClient.invalidateQueries(queryCacheKey)
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} resource - Resource name.
|
|
75
|
+
* @returns {string[]} Array of "query cache keys" of queries that use specified resource.
|
|
76
|
+
*/
|
|
77
|
+
function getQueriesUsingResource(resource) {
|
|
78
|
+
return Array.from(resourceToQueryCacheKeys.get(resource) || [])
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getQueriesUsingResources(resources) {
|
|
82
|
+
return Array.from(new Set(resources.flatMap(getQueriesUsingResource)))
|
|
83
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function makeUpdateHandlersMap(calculateHash) {
|
|
2
|
+
const updateHandlers = new Map()
|
|
3
|
+
|
|
4
|
+
function getHandlerTuples(queryKeyHash) {
|
|
5
|
+
return updateHandlers.get(queryKeyHash) || [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function add(queryKey, updateQuery) {
|
|
9
|
+
const queryKeyHash = calculateHash(queryKey)
|
|
10
|
+
const handlers = getHandlerTuples(queryKeyHash);
|
|
11
|
+
updateHandlers.set(queryKeyHash, [...handlers, { queryKey, updateQuery }])
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getUpdateHandlers(queryKey) {
|
|
15
|
+
const queryKeyHash = calculateHash(queryKey)
|
|
16
|
+
return getHandlerTuples(queryKeyHash).map(({ updateQuery }) => updateQuery)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function remove(queryKeyToRemove) {
|
|
20
|
+
const queryKeyHash = calculateHash(queryKeyToRemove)
|
|
21
|
+
const filteredHandlers = getHandlerTuples(queryKeyHash).filter(
|
|
22
|
+
({ queryKey }) => queryKey !== queryKeyToRemove
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if (filteredHandlers.length > 0) {
|
|
26
|
+
updateHandlers.set(queryKeyHash, filteredHandlers)
|
|
27
|
+
} else {
|
|
28
|
+
updateHandlers.delete(queryKeyHash)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
add,
|
|
34
|
+
remove,
|
|
35
|
+
getUpdateHandlers,
|
|
36
|
+
}
|
|
37
|
+
}
|