@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.
Files changed (410) hide show
  1. package/data/Cli/starters/README.md +22 -0
  2. package/data/Cli/starters/basic/README.md +35 -0
  3. package/data/Cli/starters/basic/eslint.config.js +24 -0
  4. package/data/Cli/starters/basic/main.wasp +100 -0
  5. package/data/Cli/starters/basic/package.json +29 -0
  6. package/data/Cli/starters/basic/postcss.config.js +6 -0
  7. package/data/Cli/starters/basic/schema.prisma +42 -0
  8. package/data/Cli/starters/basic/src/App.css +13 -0
  9. package/data/Cli/starters/basic/src/App.tsx +12 -0
  10. package/data/Cli/starters/basic/src/assets/logo.svg +1 -0
  11. package/data/Cli/starters/basic/src/auth/AuthLayout.tsx +10 -0
  12. package/data/Cli/starters/basic/src/auth/email/EmailVerificationPage.tsx +19 -0
  13. package/data/Cli/starters/basic/src/auth/email/LoginPage.tsx +27 -0
  14. package/data/Cli/starters/basic/src/auth/email/PasswordResetPage.tsx +19 -0
  15. package/data/Cli/starters/basic/src/auth/email/RequestPasswordResetPage.tsx +10 -0
  16. package/data/Cli/starters/basic/src/auth/email/SignupPage.tsx +34 -0
  17. package/data/Cli/starters/basic/src/auth/email/userSignupFields.ts +13 -0
  18. package/data/Cli/starters/basic/src/shared/components/Button.tsx +90 -0
  19. package/data/Cli/starters/basic/src/shared/components/Dialog.tsx +85 -0
  20. package/data/Cli/starters/basic/src/shared/components/Header.tsx +39 -0
  21. package/data/Cli/starters/basic/src/shared/components/Input.tsx +36 -0
  22. package/data/Cli/starters/basic/src/shared/components/Portal.tsx +26 -0
  23. package/data/Cli/starters/basic/src/tags/actions.ts +23 -0
  24. package/data/Cli/starters/basic/src/tags/components/ColorRadioButton.tsx +44 -0
  25. package/data/Cli/starters/basic/src/tags/components/ColorRadioButtons.tsx +59 -0
  26. package/data/Cli/starters/basic/src/tags/components/CreateTagDialog.tsx +50 -0
  27. package/data/Cli/starters/basic/src/tags/components/CreateTagForm.tsx +100 -0
  28. package/data/Cli/starters/basic/src/tags/components/TagLabel.tsx +55 -0
  29. package/data/Cli/starters/basic/src/tags/components/colors.ts +8 -0
  30. package/data/Cli/starters/basic/src/tags/queries.ts +14 -0
  31. package/data/Cli/starters/basic/src/tasks/TasksPage.tsx +19 -0
  32. package/data/Cli/starters/basic/src/tasks/actions.ts +71 -0
  33. package/data/Cli/starters/basic/src/tasks/components/CreateTaskForm.tsx +103 -0
  34. package/data/Cli/starters/basic/src/tasks/components/TaskList.tsx +68 -0
  35. package/data/Cli/starters/basic/src/tasks/components/TaskListItem.tsx +56 -0
  36. package/data/Cli/starters/basic/src/tasks/queries.ts +21 -0
  37. package/data/Cli/starters/basic/tailwind.config.js +30 -0
  38. package/data/Cli/starters/basic/vite.config.ts +7 -0
  39. package/data/Cli/starters/minimal/main.wasp +14 -0
  40. package/data/Cli/starters/minimal/package.json +18 -0
  41. package/data/Cli/starters/minimal/schema.prisma +10 -0
  42. package/data/Cli/starters/minimal/src/Main.css +103 -0
  43. package/data/Cli/starters/minimal/src/MainPage.tsx +37 -0
  44. package/data/Cli/starters/minimal/src/assets/logo.svg +1 -0
  45. package/data/Cli/starters/minimal/vite.config.ts +7 -0
  46. package/data/Cli/starters/skeleton/public/favicon.ico +0 -0
  47. package/data/Cli/starters/skeleton/src/vite-env.d.ts +7 -0
  48. package/data/Cli/starters/skeleton/tsconfig.json +28 -0
  49. package/data/Generator/templates/Dockerfile +78 -0
  50. package/data/Generator/templates/db/schema.prisma +24 -0
  51. package/data/Generator/templates/dockerignore +2 -0
  52. package/data/Generator/templates/react-app/README.md +21 -0
  53. package/data/Generator/templates/react-app/gitignore +23 -0
  54. package/data/Generator/templates/react-app/index.html +22 -0
  55. package/data/Generator/templates/react-app/netlify.toml +8 -0
  56. package/data/Generator/templates/react-app/npmrc +1 -0
  57. package/data/Generator/templates/react-app/package.json +31 -0
  58. package/data/Generator/templates/react-app/public/manifest.json +15 -0
  59. package/data/Generator/templates/react-app/src/auth/pages/OAuthCallback.tsx +93 -0
  60. package/data/Generator/templates/react-app/src/auth/pages/createAuthRequiredPage.jsx +40 -0
  61. package/data/Generator/templates/react-app/src/components/DefaultRootErrorBoundary.tsx +16 -0
  62. package/data/Generator/templates/react-app/src/components/FullPageWrapper.tsx +21 -0
  63. package/data/Generator/templates/react-app/src/components/Loader.module.css +37 -0
  64. package/data/Generator/templates/react-app/src/components/Loader.tsx +12 -0
  65. package/data/Generator/templates/react-app/src/components/Message.tsx +86 -0
  66. package/data/Generator/templates/react-app/src/index.tsx +47 -0
  67. package/data/Generator/templates/react-app/src/logo.png +0 -0
  68. package/data/Generator/templates/react-app/src/router.tsx +59 -0
  69. package/data/Generator/templates/react-app/src/test/vitest/setup.ts +8 -0
  70. package/data/Generator/templates/react-app/src/utils.js +3 -0
  71. package/data/Generator/templates/react-app/src/vite-env.d.ts +1 -0
  72. package/data/Generator/templates/react-app/tsconfig.app.json +28 -0
  73. package/data/Generator/templates/react-app/tsconfig.json +11 -0
  74. package/data/Generator/templates/react-app/tsconfig.vite.json +16 -0
  75. package/data/Generator/templates/react-app/vite/detectServerImports.ts +53 -0
  76. package/data/Generator/templates/react-app/vite/validateEnv.ts +45 -0
  77. package/data/Generator/templates/react-app/vite.config.ts +74 -0
  78. package/data/Generator/templates/sdk/wasp/api/events.ts +11 -0
  79. package/data/Generator/templates/sdk/wasp/api/index.ts +136 -0
  80. package/data/Generator/templates/sdk/wasp/auth/email/actions/login.ts +13 -0
  81. package/data/Generator/templates/sdk/wasp/auth/email/actions/passwordReset.ts +22 -0
  82. package/data/Generator/templates/sdk/wasp/auth/email/actions/signup.ts +20 -0
  83. package/data/Generator/templates/sdk/wasp/auth/email/actions/verifyEmail.ts +14 -0
  84. package/data/Generator/templates/sdk/wasp/auth/email/index.ts +5 -0
  85. package/data/Generator/templates/sdk/wasp/auth/forms/Auth.module.css +16 -0
  86. package/data/Generator/templates/sdk/wasp/auth/forms/Auth.tsx +94 -0
  87. package/data/Generator/templates/sdk/wasp/auth/forms/ForgotPassword.tsx +18 -0
  88. package/data/Generator/templates/sdk/wasp/auth/forms/Login.tsx +18 -0
  89. package/data/Generator/templates/sdk/wasp/auth/forms/ResetPassword.tsx +18 -0
  90. package/data/Generator/templates/sdk/wasp/auth/forms/Signup.tsx +24 -0
  91. package/data/Generator/templates/sdk/wasp/auth/forms/VerifyEmail.tsx +18 -0
  92. package/data/Generator/templates/sdk/wasp/auth/forms/internal/Form.module.css +99 -0
  93. package/data/Generator/templates/sdk/wasp/auth/forms/internal/Form.tsx +74 -0
  94. package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.module.css +22 -0
  95. package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.tsx +34 -0
  96. package/data/Generator/templates/sdk/wasp/auth/forms/internal/auth-styles.css +30 -0
  97. package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.module.css +55 -0
  98. package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx +291 -0
  99. package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ForgotPasswordForm.tsx +52 -0
  100. package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ResetPasswordForm.tsx +82 -0
  101. package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/VerifyEmailForm.tsx +43 -0
  102. package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/useEmail.ts +33 -0
  103. package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialButton.module.css +33 -0
  104. package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialButton.tsx +14 -0
  105. package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.module.css +4 -0
  106. package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx +74 -0
  107. package/data/Generator/templates/sdk/wasp/auth/forms/internal/usernameAndPassword/useUsernameAndPassword.ts +29 -0
  108. package/data/Generator/templates/sdk/wasp/auth/forms/internal/util.ts +16 -0
  109. package/data/Generator/templates/sdk/wasp/auth/forms/types.ts +77 -0
  110. package/data/Generator/templates/sdk/wasp/auth/helpers/_Provider.tsx +17 -0
  111. package/data/Generator/templates/sdk/wasp/auth/helpers/user.ts +15 -0
  112. package/data/Generator/templates/sdk/wasp/auth/index.ts +9 -0
  113. package/data/Generator/templates/sdk/wasp/auth/jwt.ts +22 -0
  114. package/data/Generator/templates/sdk/wasp/auth/logout.ts +18 -0
  115. package/data/Generator/templates/sdk/wasp/auth/lucia.ts +53 -0
  116. package/data/Generator/templates/sdk/wasp/auth/password.ts +36 -0
  117. package/data/Generator/templates/sdk/wasp/auth/providers/index.ts +9 -0
  118. package/data/Generator/templates/sdk/wasp/auth/providers/types.ts +68 -0
  119. package/data/Generator/templates/sdk/wasp/auth/session.ts +78 -0
  120. package/data/Generator/templates/sdk/wasp/auth/types.ts +2 -0
  121. package/data/Generator/templates/sdk/wasp/auth/useAuth.ts +37 -0
  122. package/data/Generator/templates/sdk/wasp/auth/user.ts +63 -0
  123. package/data/Generator/templates/sdk/wasp/auth/username/actions/login.ts +13 -0
  124. package/data/Generator/templates/sdk/wasp/auth/username/actions/signup.ts +20 -0
  125. package/data/Generator/templates/sdk/wasp/auth/username/index.ts +2 -0
  126. package/data/Generator/templates/sdk/wasp/auth/utils.ts +369 -0
  127. package/data/Generator/templates/sdk/wasp/auth/validation.ts +83 -0
  128. package/data/Generator/templates/sdk/wasp/client/auth/discord.ts +2 -0
  129. package/data/Generator/templates/sdk/wasp/client/auth/email.ts +5 -0
  130. package/data/Generator/templates/sdk/wasp/client/auth/github.ts +2 -0
  131. package/data/Generator/templates/sdk/wasp/client/auth/google.ts +2 -0
  132. package/data/Generator/templates/sdk/wasp/client/auth/index.ts +29 -0
  133. package/data/Generator/templates/sdk/wasp/client/auth/keycloak.ts +2 -0
  134. package/data/Generator/templates/sdk/wasp/client/auth/slack.ts +2 -0
  135. package/data/Generator/templates/sdk/wasp/client/auth/ui.ts +32 -0
  136. package/data/Generator/templates/sdk/wasp/client/auth/username.ts +2 -0
  137. package/data/Generator/templates/sdk/wasp/client/config.ts +15 -0
  138. package/data/Generator/templates/sdk/wasp/client/crud/_crud.ts +89 -0
  139. package/data/Generator/templates/sdk/wasp/client/crud/index.ts +4 -0
  140. package/data/Generator/templates/sdk/wasp/client/crud/operationsHelpers.ts +21 -0
  141. package/data/Generator/templates/sdk/wasp/client/env/schema.ts +22 -0
  142. package/data/Generator/templates/sdk/wasp/client/env.ts +5 -0
  143. package/data/Generator/templates/sdk/wasp/client/hooks.ts +19 -0
  144. package/data/Generator/templates/sdk/wasp/client/index.ts +17 -0
  145. package/data/Generator/templates/sdk/wasp/client/operations/actions/core.ts +49 -0
  146. package/data/Generator/templates/sdk/wasp/client/operations/actions/index.ts +13 -0
  147. package/data/Generator/templates/sdk/wasp/client/operations/hooks.ts +347 -0
  148. package/data/Generator/templates/sdk/wasp/client/operations/index.ts +22 -0
  149. package/data/Generator/templates/sdk/wasp/client/operations/internal/index.ts +22 -0
  150. package/data/Generator/templates/sdk/wasp/client/operations/internal/resources.js +83 -0
  151. package/data/Generator/templates/sdk/wasp/client/operations/internal/updateHandlersMap.js +37 -0
  152. package/data/Generator/templates/sdk/wasp/client/operations/queries/core.ts +91 -0
  153. package/data/Generator/templates/sdk/wasp/client/operations/queries/index.ts +16 -0
  154. package/data/Generator/templates/sdk/wasp/client/operations/queryClient.ts +34 -0
  155. package/data/Generator/templates/sdk/wasp/client/operations/rpc.ts +96 -0
  156. package/data/Generator/templates/sdk/wasp/client/router/Link.tsx +21 -0
  157. package/data/Generator/templates/sdk/wasp/client/router/index.ts +53 -0
  158. package/data/Generator/templates/sdk/wasp/client/router/linkHelpers.ts +48 -0
  159. package/data/Generator/templates/sdk/wasp/client/router/types.ts +98 -0
  160. package/data/Generator/templates/sdk/wasp/client/test/index.ts +1 -0
  161. package/data/Generator/templates/sdk/wasp/client/test/vitest/helpers.tsx +95 -0
  162. package/data/Generator/templates/sdk/wasp/client/webSocket/WebSocketProvider.tsx +77 -0
  163. package/data/Generator/templates/sdk/wasp/client/webSocket/index.ts +39 -0
  164. package/data/Generator/templates/sdk/wasp/core/auth.ts +40 -0
  165. package/data/Generator/templates/sdk/wasp/core/serialization/custom-register.ts +21 -0
  166. package/data/Generator/templates/sdk/wasp/core/serialization/index.ts +56 -0
  167. package/data/Generator/templates/sdk/wasp/core/serialization/prisma.ts +54 -0
  168. package/data/Generator/templates/sdk/wasp/core/storage.ts +50 -0
  169. package/data/Generator/templates/sdk/wasp/dev/index.ts +19 -0
  170. package/data/Generator/templates/sdk/wasp/entities/index.ts +28 -0
  171. package/data/Generator/templates/sdk/wasp/env/index.ts +9 -0
  172. package/data/Generator/templates/sdk/wasp/env/validation.ts +38 -0
  173. package/data/Generator/templates/sdk/wasp/package.json +152 -0
  174. package/data/Generator/templates/sdk/wasp/prisma-runtime-library.d.ts +17 -0
  175. package/data/Generator/templates/sdk/wasp/scripts/copy-assets.js +14 -0
  176. package/data/Generator/templates/sdk/wasp/server/HttpError.ts +30 -0
  177. package/data/Generator/templates/sdk/wasp/server/_types/index.ts +105 -0
  178. package/data/Generator/templates/sdk/wasp/server/_types/taggedEntities.ts +26 -0
  179. package/data/Generator/templates/sdk/wasp/server/api/index.ts +44 -0
  180. package/data/Generator/templates/sdk/wasp/server/auth/email/index.ts +20 -0
  181. package/data/Generator/templates/sdk/wasp/server/auth/email/utils.ts +104 -0
  182. package/data/Generator/templates/sdk/wasp/server/auth/hooks.ts +188 -0
  183. package/data/Generator/templates/sdk/wasp/server/auth/index.ts +49 -0
  184. package/data/Generator/templates/sdk/wasp/server/auth/oauth/index.ts +38 -0
  185. package/data/Generator/templates/sdk/wasp/server/auth/oauth/oneTimeCode.ts +50 -0
  186. package/data/Generator/templates/sdk/wasp/server/auth/oauth/provider.ts +20 -0
  187. package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/discord.ts +22 -0
  188. package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/github.ts +20 -0
  189. package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/google.ts +22 -0
  190. package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/keycloak.ts +23 -0
  191. package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/slack.ts +22 -0
  192. package/data/Generator/templates/sdk/wasp/server/auth/oauth/redirect.ts +43 -0
  193. package/data/Generator/templates/sdk/wasp/server/auth/user.ts +148 -0
  194. package/data/Generator/templates/sdk/wasp/server/auth/username.ts +1 -0
  195. package/data/Generator/templates/sdk/wasp/server/config.ts +47 -0
  196. package/data/Generator/templates/sdk/wasp/server/crud/_operationTypes.ts +134 -0
  197. package/data/Generator/templates/sdk/wasp/server/crud/index.ts +5 -0
  198. package/data/Generator/templates/sdk/wasp/server/dbClient.ts +35 -0
  199. package/data/Generator/templates/sdk/wasp/server/email/core/helpers.ts +40 -0
  200. package/data/Generator/templates/sdk/wasp/server/email/core/index.ts +17 -0
  201. package/data/Generator/templates/sdk/wasp/server/email/core/providers/dummy.ts +34 -0
  202. package/data/Generator/templates/sdk/wasp/server/email/core/providers/mailgun.ts +31 -0
  203. package/data/Generator/templates/sdk/wasp/server/email/core/providers/sendgrid.ts +44 -0
  204. package/data/Generator/templates/sdk/wasp/server/email/core/providers/smtp.ts +29 -0
  205. package/data/Generator/templates/sdk/wasp/server/email/core/types.ts +59 -0
  206. package/data/Generator/templates/sdk/wasp/server/email/index.ts +39 -0
  207. package/data/Generator/templates/sdk/wasp/server/env.ts +173 -0
  208. package/data/Generator/templates/sdk/wasp/server/index.ts +17 -0
  209. package/data/Generator/templates/sdk/wasp/server/jobs/_job.ts +39 -0
  210. package/data/Generator/templates/sdk/wasp/server/jobs/core/job.ts +28 -0
  211. package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/index.ts +3 -0
  212. package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBoss.ts +76 -0
  213. package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBossJob.ts +230 -0
  214. package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/types.ts +9 -0
  215. package/data/Generator/templates/sdk/wasp/server/jobs/index.ts +5 -0
  216. package/data/Generator/templates/sdk/wasp/server/middleware/globalMiddleware.ts +8 -0
  217. package/data/Generator/templates/sdk/wasp/server/middleware/index.ts +1 -0
  218. package/data/Generator/templates/sdk/wasp/server/operations/actions/index.ts +41 -0
  219. package/data/Generator/templates/sdk/wasp/server/operations/actions/types.ts +35 -0
  220. package/data/Generator/templates/sdk/wasp/server/operations/index.ts +13 -0
  221. package/data/Generator/templates/sdk/wasp/server/operations/queries/index.ts +42 -0
  222. package/data/Generator/templates/sdk/wasp/server/operations/queries/types.ts +36 -0
  223. package/data/Generator/templates/sdk/wasp/server/operations/wrappers.ts +242 -0
  224. package/data/Generator/templates/sdk/wasp/server/types/index.ts +11 -0
  225. package/data/Generator/templates/sdk/wasp/server/utils.ts +38 -0
  226. package/data/Generator/templates/sdk/wasp/server/webSocket/index.ts +57 -0
  227. package/data/Generator/templates/sdk/wasp/tsconfig.json +102 -0
  228. package/data/Generator/templates/sdk/wasp/universal/ansiColors.ts +14 -0
  229. package/data/Generator/templates/sdk/wasp/universal/predicates.ts +3 -0
  230. package/data/Generator/templates/sdk/wasp/universal/types.ts +74 -0
  231. package/data/Generator/templates/sdk/wasp/universal/url.ts +9 -0
  232. package/data/Generator/templates/sdk/wasp/universal/validators.ts +21 -0
  233. package/data/Generator/templates/sdk/wasp/vite-env.d.ts +1 -0
  234. package/data/Generator/templates/server/README.md +1 -0
  235. package/data/Generator/templates/server/gitignore +6 -0
  236. package/data/Generator/templates/server/nodemon.json +13 -0
  237. package/data/Generator/templates/server/npmrc +1 -0
  238. package/data/Generator/templates/server/package.json +27 -0
  239. package/data/Generator/templates/server/rollup.config.js +44 -0
  240. package/data/Generator/templates/server/src/actions/_action.ts +18 -0
  241. package/data/Generator/templates/server/src/app.js +36 -0
  242. package/data/Generator/templates/server/src/auth/hooks.ts +135 -0
  243. package/data/Generator/templates/server/src/auth/providers/config/discord.ts +69 -0
  244. package/data/Generator/templates/server/src/auth/providers/config/email.ts +96 -0
  245. package/data/Generator/templates/server/src/auth/providers/config/github.ts +78 -0
  246. package/data/Generator/templates/server/src/auth/providers/config/google.ts +65 -0
  247. package/data/Generator/templates/server/src/auth/providers/config/keycloak.ts +67 -0
  248. package/data/Generator/templates/server/src/auth/providers/config/slack.ts +65 -0
  249. package/data/Generator/templates/server/src/auth/providers/config/username.ts +33 -0
  250. package/data/Generator/templates/server/src/auth/providers/email/login.ts +66 -0
  251. package/data/Generator/templates/server/src/auth/providers/email/requestPasswordReset.ts +74 -0
  252. package/data/Generator/templates/server/src/auth/providers/email/resetPassword.ts +48 -0
  253. package/data/Generator/templates/server/src/auth/providers/email/signup.ts +165 -0
  254. package/data/Generator/templates/server/src/auth/providers/email/verifyEmail.ts +42 -0
  255. package/data/Generator/templates/server/src/auth/providers/index.ts +32 -0
  256. package/data/Generator/templates/server/src/auth/providers/oauth/config.ts +19 -0
  257. package/data/Generator/templates/server/src/auth/providers/oauth/cookies.ts +35 -0
  258. package/data/Generator/templates/server/src/auth/providers/oauth/handler.ts +130 -0
  259. package/data/Generator/templates/server/src/auth/providers/oauth/oneTimeCode.ts +39 -0
  260. package/data/Generator/templates/server/src/auth/providers/oauth/state.ts +144 -0
  261. package/data/Generator/templates/server/src/auth/providers/oauth/types.ts +7 -0
  262. package/data/Generator/templates/server/src/auth/providers/oauth/user.ts +139 -0
  263. package/data/Generator/templates/server/src/auth/providers/username/login.ts +64 -0
  264. package/data/Generator/templates/server/src/auth/providers/username/signup.ts +59 -0
  265. package/data/Generator/templates/server/src/crud/_operations.ts +184 -0
  266. package/data/Generator/templates/server/src/dbSeed.ts +37 -0
  267. package/data/Generator/templates/server/src/jobs/_job.ts +9 -0
  268. package/data/Generator/templates/server/src/jobs/core/allJobs.ts +8 -0
  269. package/data/Generator/templates/server/src/middleware/globalMiddleware.ts +45 -0
  270. package/data/Generator/templates/server/src/middleware/index.ts +1 -0
  271. package/data/Generator/templates/server/src/middleware/operations.ts +28 -0
  272. package/data/Generator/templates/server/src/queries/_query.ts +18 -0
  273. package/data/Generator/templates/server/src/routes/apis/index.ts +67 -0
  274. package/data/Generator/templates/server/src/routes/auth/index.js +16 -0
  275. package/data/Generator/templates/server/src/routes/auth/logout.ts +12 -0
  276. package/data/Generator/templates/server/src/routes/auth/me.ts +10 -0
  277. package/data/Generator/templates/server/src/routes/crud/_crud.ts +46 -0
  278. package/data/Generator/templates/server/src/routes/crud/index.ts +12 -0
  279. package/data/Generator/templates/server/src/routes/index.js +55 -0
  280. package/data/Generator/templates/server/src/routes/operations/_action.js +5 -0
  281. package/data/Generator/templates/server/src/routes/operations/_query.js +5 -0
  282. package/data/Generator/templates/server/src/routes/operations/index.js +18 -0
  283. package/data/Generator/templates/server/src/server.ts +76 -0
  284. package/data/Generator/templates/server/src/views/wrong-port.ts +123 -0
  285. package/data/Generator/templates/server/src/webSocket/initialization.ts +59 -0
  286. package/data/Generator/templates/server/tsconfig.json +41 -0
  287. package/data/Lsp/templates/ts/action.fn.ts +12 -0
  288. package/data/Lsp/templates/ts/operation.fn.js +7 -0
  289. package/data/Lsp/templates/ts/page.component.jsx +9 -0
  290. package/data/Lsp/templates/ts/query.fn.ts +12 -0
  291. package/data/packages/deploy/dist/common/brandedTypes.js +2 -0
  292. package/data/packages/deploy/dist/common/clientApp.js +26 -0
  293. package/data/packages/deploy/dist/common/commander.js +8 -0
  294. package/data/packages/deploy/dist/common/random.js +5 -0
  295. package/data/packages/deploy/dist/common/terminal.js +24 -0
  296. package/data/packages/deploy/dist/common/typeUtils.js +2 -0
  297. package/data/packages/deploy/dist/common/validation.js +14 -0
  298. package/data/packages/deploy/dist/common/waspBuild.js +21 -0
  299. package/data/packages/deploy/dist/common/waspProject.js +43 -0
  300. package/data/packages/deploy/dist/common/zx.js +10 -0
  301. package/data/packages/deploy/dist/index.js +30 -0
  302. package/data/packages/deploy/dist/providers/fly/CommonCmdOptions.js +2 -0
  303. package/data/packages/deploy/dist/providers/fly/CommonOps.js +36 -0
  304. package/data/packages/deploy/dist/providers/fly/DeploymentInstructions.js +12 -0
  305. package/data/packages/deploy/dist/providers/fly/commands/cmd/CmdCmdOptions.js +2 -0
  306. package/data/packages/deploy/dist/providers/fly/commands/cmd/cmd.js +29 -0
  307. package/data/packages/deploy/dist/providers/fly/commands/createDb/CreateDbCmdOptions.js +2 -0
  308. package/data/packages/deploy/dist/providers/fly/commands/createDb/createDb.js +55 -0
  309. package/data/packages/deploy/dist/providers/fly/commands/deploy/DeployCmdOptions.js +2 -0
  310. package/data/packages/deploy/dist/providers/fly/commands/deploy/deploy.js +88 -0
  311. package/data/packages/deploy/dist/providers/fly/commands/launch/LaunchCmdOptions.js +2 -0
  312. package/data/packages/deploy/dist/providers/fly/commands/launch/launch.js +17 -0
  313. package/data/packages/deploy/dist/providers/fly/commands/setup/SetupCmdOptions.js +2 -0
  314. package/data/packages/deploy/dist/providers/fly/commands/setup/setup.js +141 -0
  315. package/data/packages/deploy/dist/providers/fly/flyAppUrl.js +4 -0
  316. package/data/packages/deploy/dist/providers/fly/flyCli.js +74 -0
  317. package/data/packages/deploy/dist/providers/fly/index.js +121 -0
  318. package/data/packages/deploy/dist/providers/fly/jsonOutputSchemas.js +37 -0
  319. package/data/packages/deploy/dist/providers/fly/tomlFile.js +65 -0
  320. package/data/packages/deploy/dist/providers/railway/DeploymentInstructions.js +11 -0
  321. package/data/packages/deploy/dist/providers/railway/brandedTypes.js +2 -0
  322. package/data/packages/deploy/dist/providers/railway/commands/deploy/DeployCmdOptions.js +2 -0
  323. package/data/packages/deploy/dist/providers/railway/commands/deploy/client.js +22 -0
  324. package/data/packages/deploy/dist/providers/railway/commands/deploy/common.js +40 -0
  325. package/data/packages/deploy/dist/providers/railway/commands/deploy/index.js +57 -0
  326. package/data/packages/deploy/dist/providers/railway/commands/deploy/server.js +17 -0
  327. package/data/packages/deploy/dist/providers/railway/commands/launch/LaunchCmdOptions.js +2 -0
  328. package/data/packages/deploy/dist/providers/railway/commands/launch/launch.js +9 -0
  329. package/data/packages/deploy/dist/providers/railway/commands/setup/SetupCmdOptions.js +2 -0
  330. package/data/packages/deploy/dist/providers/railway/commands/setup/setup.js +146 -0
  331. package/data/packages/deploy/dist/providers/railway/index.js +83 -0
  332. package/data/packages/deploy/dist/providers/railway/jsonOutputSchemas.js +19 -0
  333. package/data/packages/deploy/dist/providers/railway/ports.js +6 -0
  334. package/data/packages/deploy/dist/providers/railway/railwayCli.js +85 -0
  335. package/data/packages/deploy/dist/providers/railway/railwayProject/RailwayProject.js +14 -0
  336. package/data/packages/deploy/dist/providers/railway/railwayProject/cli.js +80 -0
  337. package/data/packages/deploy/dist/providers/railway/railwayProject/index.js +48 -0
  338. package/data/packages/deploy/dist/providers/railway/railwayService/nameGenerator.js +24 -0
  339. package/data/packages/deploy/dist/providers/railway/railwayService/url.js +32 -0
  340. package/data/packages/deploy/package-lock.json +3536 -0
  341. package/data/packages/deploy/package.json +29 -0
  342. package/data/packages/prisma/dist/format.js +35 -0
  343. package/data/packages/prisma/dist/index.js +33 -0
  344. package/data/packages/prisma/package-lock.json +5101 -0
  345. package/data/packages/prisma/package.json +30 -0
  346. package/data/packages/studio/dist/index.js +48 -0
  347. package/data/packages/studio/dist/public/assets/Flow-b5112d3d.js +26 -0
  348. package/data/packages/studio/dist/public/assets/index-17ce6ed4.css +1 -0
  349. package/data/packages/studio/dist/public/assets/index-62a9d21a.js +120 -0
  350. package/data/packages/studio/dist/public/index.html +14 -0
  351. package/data/packages/studio/package-lock.json +1866 -0
  352. package/data/packages/studio/package.json +33 -0
  353. package/data/packages/ts-inspect/dist/exports.js +82 -0
  354. package/data/packages/ts-inspect/dist/index.js +28 -0
  355. package/data/packages/ts-inspect/package-lock.json +4947 -0
  356. package/data/packages/ts-inspect/package.json +31 -0
  357. package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.d.ts +2 -0
  358. package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.d.ts.map +1 -0
  359. package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.js +59 -0
  360. package/data/packages/wasp-config/dist/__tests__/cli.unit.test.d.ts +2 -0
  361. package/data/packages/wasp-config/dist/__tests__/cli.unit.test.d.ts.map +1 -0
  362. package/data/packages/wasp-config/dist/__tests__/cli.unit.test.js +65 -0
  363. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.d.ts +2 -0
  364. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.d.ts.map +1 -0
  365. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.integration.test.js +126 -0
  366. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.d.ts +2 -0
  367. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.d.ts.map +1 -0
  368. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.js +743 -0
  369. package/data/packages/wasp-config/dist/__tests__/testFixtures.d.ts +224 -0
  370. package/data/packages/wasp-config/dist/__tests__/testFixtures.d.ts.map +1 -0
  371. package/data/packages/wasp-config/dist/__tests__/testFixtures.js +656 -0
  372. package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.d.ts +2 -0
  373. package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.d.ts.map +1 -0
  374. package/data/packages/wasp-config/dist/__tests__/testFixtures.test-d.js +57 -0
  375. package/data/packages/wasp-config/dist/src/_private.d.ts +2 -0
  376. package/data/packages/wasp-config/dist/src/_private.d.ts.map +1 -0
  377. package/data/packages/wasp-config/dist/src/_private.js +1 -0
  378. package/data/packages/wasp-config/dist/src/appAnalyzer.d.ts +16 -0
  379. package/data/packages/wasp-config/dist/src/appAnalyzer.d.ts.map +1 -0
  380. package/data/packages/wasp-config/dist/src/appAnalyzer.js +34 -0
  381. package/data/packages/wasp-config/dist/src/appSpec.d.ts +223 -0
  382. package/data/packages/wasp-config/dist/src/appSpec.d.ts.map +1 -0
  383. package/data/packages/wasp-config/dist/src/appSpec.js +6 -0
  384. package/data/packages/wasp-config/dist/src/branded.d.ts +7 -0
  385. package/data/packages/wasp-config/dist/src/branded.d.ts.map +1 -0
  386. package/data/packages/wasp-config/dist/src/branded.js +1 -0
  387. package/data/packages/wasp-config/dist/src/cli.d.ts +6 -0
  388. package/data/packages/wasp-config/dist/src/cli.d.ts.map +1 -0
  389. package/data/packages/wasp-config/dist/src/cli.js +24 -0
  390. package/data/packages/wasp-config/dist/src/index.d.ts +8 -0
  391. package/data/packages/wasp-config/dist/src/index.d.ts.map +1 -0
  392. package/data/packages/wasp-config/dist/src/index.js +1 -0
  393. package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.d.ts +38 -0
  394. package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.d.ts.map +1 -0
  395. package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.js +294 -0
  396. package/data/packages/wasp-config/dist/src/publicApi/App.d.ts +24 -0
  397. package/data/packages/wasp-config/dist/src/publicApi/App.d.ts.map +1 -0
  398. package/data/packages/wasp-config/dist/src/publicApi/App.js +75 -0
  399. package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts +171 -0
  400. package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts.map +1 -0
  401. package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.js +1 -0
  402. package/data/packages/wasp-config/dist/src/run.d.ts +3 -0
  403. package/data/packages/wasp-config/dist/src/run.d.ts.map +1 -0
  404. package/data/packages/wasp-config/dist/src/run.js +18 -0
  405. package/data/packages/wasp-config/package-lock.json +3992 -0
  406. package/data/packages/wasp-config/package.json +39 -0
  407. package/main.js +9 -0
  408. package/package.json +1 -0
  409. package/readme.md +3 -0
  410. 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,5 @@
1
+ import { clientEnvSchema } from './env/schema.js'
2
+ import { ensureEnvSchema } from '../env/validation.js'
3
+
4
+ // PUBLIC API
5
+ export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)
@@ -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
+ }