@wasp.sh/wasp-cli-darwin-arm64-unknown 0.21.1 → 0.22.0-rc1

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 (51) hide show
  1. package/data/Cli/starters/skeleton/gitignore +11 -0
  2. package/data/Cli/starters/ts-minimal/main.wasp.ts +15 -0
  3. package/data/Cli/starters/ts-minimal/package.json +18 -0
  4. package/data/Cli/starters/ts-minimal/schema.prisma +10 -0
  5. package/data/Cli/starters/ts-minimal/src/Main.css +103 -0
  6. package/data/Cli/starters/ts-minimal/src/MainPage.tsx +37 -0
  7. package/data/Cli/starters/ts-minimal/src/assets/logo.svg +1 -0
  8. package/data/Cli/starters/ts-minimal/tsconfig.json +7 -0
  9. package/data/Cli/starters/ts-minimal/tsconfig.src.json +28 -0
  10. package/data/Cli/starters/ts-minimal/tsconfig.wasp.json +15 -0
  11. package/data/Cli/starters/ts-minimal/vite.config.ts +9 -0
  12. package/data/Generator/libs/auth/wasp.sh-lib-auth-0.22.0.tgz +0 -0
  13. package/data/Generator/templates/Dockerfile +5 -3
  14. package/data/Generator/templates/sdk/wasp/client/app/components/WaspApp.tsx +7 -1
  15. package/data/Generator/templates/sdk/wasp/client/app/router/router.tsx +3 -2
  16. package/data/Generator/templates/sdk/wasp/client/env/schema.ts +28 -11
  17. package/data/Generator/templates/sdk/wasp/client/env.ts +6 -3
  18. package/data/Generator/templates/sdk/wasp/client/vite/plugins/validateEnv.ts +25 -26
  19. package/data/Generator/templates/sdk/wasp/client/vite/plugins/waspConfig.ts +57 -11
  20. package/data/Generator/templates/sdk/wasp/client/vite/virtual-files/files/routes.tsx +26 -7
  21. package/data/Generator/templates/sdk/wasp/env/index.ts +1 -1
  22. package/data/Generator/templates/sdk/wasp/env/validation.ts +28 -22
  23. package/data/Generator/templates/sdk/wasp/server/email/core/providers/dummy.ts +23 -25
  24. package/data/Generator/templates/sdk/wasp/server/env.ts +72 -67
  25. package/data/Generator/templates/sdk/wasp/universal/ansiColors.ts +55 -11
  26. package/data/packages/deploy/dist/providers/fly/flyCli.js +1 -4
  27. package/data/packages/deploy/dist/providers/fly/jsonOutputSchemas.js +6 -2
  28. package/data/packages/deploy/dist/providers/fly/tomlFile.js +8 -2
  29. package/data/packages/deploy/dist/providers/railway/commands/setup/setup.js +1 -12
  30. package/data/packages/deploy/dist/providers/railway/env.js +13 -0
  31. package/data/packages/deploy/dist/providers/railway/railwayService/url.js +1 -1
  32. package/data/packages/deploy/package-lock.json +2268 -15
  33. package/data/packages/deploy/package.json +6 -3
  34. package/data/packages/ts-inspect/dist/exports.js +1 -1
  35. package/data/packages/ts-inspect/package-lock.json +8 -7
  36. package/data/packages/ts-inspect/package.json +1 -1
  37. package/data/packages/wasp-config/dist/__tests__/appAnalyzer.unit.test.js +13 -0
  38. package/data/packages/wasp-config/dist/__tests__/mapTsAppSpecToAppSpecDecls.unit.test.js +1 -0
  39. package/data/packages/wasp-config/dist/__tests__/testFixtures.d.ts.map +1 -1
  40. package/data/packages/wasp-config/dist/__tests__/testFixtures.js +1 -0
  41. package/data/packages/wasp-config/dist/src/appAnalyzer.js +1 -1
  42. package/data/packages/wasp-config/dist/src/appSpec.d.ts +1 -0
  43. package/data/packages/wasp-config/dist/src/appSpec.d.ts.map +1 -1
  44. package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.d.ts.map +1 -1
  45. package/data/packages/wasp-config/dist/src/mapTsAppSpecToAppSpecDecls.js +2 -1
  46. package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts +1 -0
  47. package/data/packages/wasp-config/dist/src/publicApi/tsAppSpec.d.ts.map +1 -1
  48. package/data/packages/wasp-config/package.json +5 -4
  49. package/package.json +1 -1
  50. package/wasp-bin +0 -0
  51. package/data/Generator/libs/auth/wasp.sh-lib-auth-0.21.1.tgz +0 -0
@@ -0,0 +1,11 @@
1
+ .wasp/
2
+ node_modules/
3
+
4
+ # Ignore all dotenv files by default to prevent accidentally committing any secrets.
5
+ # To include specific dotenv files, use the `!` operator or adjust these rules.
6
+ .env
7
+ .env.*
8
+
9
+ # Don't ignore example dotenv files.
10
+ !.env.example
11
+ !.env.*.example
@@ -0,0 +1,15 @@
1
+ import { App } from "wasp-config";
2
+
3
+ const app = new App("__waspAppName__", {
4
+ title: "__waspProjectName__",
5
+ wasp: { version: "__waspVersion__" },
6
+ head: ["<link rel='icon' href='/favicon.ico' />"],
7
+ });
8
+
9
+ const mainPage = app.page("MainPage", {
10
+ component: { import: "MainPage", from: "@src/MainPage" },
11
+ });
12
+
13
+ app.route("RootRoute", { path: "/", to: mainPage });
14
+
15
+ export default app;
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "__waspAppName__",
3
+ "type": "module",
4
+ "workspaces": [".wasp/out/*", ".wasp/out/sdk/wasp"],
5
+ "dependencies": {
6
+ "react": "^19.2.1",
7
+ "react-dom": "^19.2.1",
8
+ "react-router": "^7.12.0"
9
+ },
10
+ "devDependencies": {
11
+ "@types/react": "^19.2.7",
12
+ "@types/react-dom": "^19.2.3",
13
+ "prisma": "5.19.1",
14
+ "typescript": "5.8.2",
15
+ "vite": "^7.0.6",
16
+ "wasp-config": "__waspConfigPackageSpecifier__"
17
+ }
18
+ }
@@ -0,0 +1,10 @@
1
+ datasource db {
2
+ provider = "sqlite"
3
+ // Wasp requires that the url is set to the DATABASE_URL environment variable.
4
+ url = env("DATABASE_URL")
5
+ }
6
+
7
+ // Wasp requires the `prisma-client-js` generator to be present.
8
+ generator client {
9
+ provider = "prisma-client-js"
10
+ }
@@ -0,0 +1,103 @@
1
+ * {
2
+ -webkit-font-smoothing: antialiased;
3
+ -moz-osx-font-smoothing: grayscale;
4
+ box-sizing: border-box;
5
+ margin: 0;
6
+ padding: 0;
7
+ }
8
+
9
+ body {
10
+ font-family:
11
+ -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
12
+ "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
13
+ }
14
+
15
+ #root {
16
+ min-height: 100vh;
17
+ display: flex;
18
+ flex-direction: column;
19
+ justify-content: center;
20
+ align-items: center;
21
+ }
22
+
23
+ .container {
24
+ margin: 3rem 3rem 10rem 3rem;
25
+ max-width: 726px;
26
+ display: flex;
27
+ flex-direction: column;
28
+ justify-content: center;
29
+ align-items: center;
30
+ text-align: center;
31
+ }
32
+
33
+ .logo {
34
+ max-height: 200px;
35
+ margin-bottom: 1rem;
36
+ }
37
+
38
+ .title {
39
+ font-size: 4rem;
40
+ font-weight: 700;
41
+ margin-bottom: 1rem;
42
+ }
43
+
44
+ .content {
45
+ font-size: 1.2rem;
46
+ font-weight: 400;
47
+ line-height: 2;
48
+ margin-bottom: 3rem;
49
+ }
50
+
51
+ .buttons {
52
+ display: flex;
53
+ flex-direction: row;
54
+ gap: 1rem;
55
+ }
56
+
57
+ .button {
58
+ font-size: 1.2rem;
59
+ font-weight: 700;
60
+ text-decoration: none;
61
+ padding: 1.2rem 1.5rem;
62
+ border-radius: 10px;
63
+ }
64
+
65
+ .button-filled {
66
+ color: black;
67
+ background-color: #ffcc00;
68
+ border: 2px solid #ffcc00;
69
+
70
+ transition: all 0.2s ease-in-out;
71
+ }
72
+
73
+ .button-filled:hover {
74
+ filter: brightness(0.95);
75
+ }
76
+
77
+ .button-outlined {
78
+ color: black;
79
+ background-color: transparent;
80
+ border: 2px solid #ffcc00;
81
+
82
+ transition: all 0.2s ease-in-out;
83
+ }
84
+
85
+ .button-outlined:hover {
86
+ filter: brightness(0.95);
87
+ }
88
+
89
+ code {
90
+ border-radius: 5px;
91
+ border: 1px solid #ffcc00;
92
+ padding: 0.2rem;
93
+ background: #ffcc0044;
94
+ font-family:
95
+ Menlo,
96
+ Monaco,
97
+ Lucida Console,
98
+ Liberation Mono,
99
+ DejaVu Sans Mono,
100
+ Bitstream Vera Sans Mono,
101
+ Courier New,
102
+ monospace;
103
+ }
@@ -0,0 +1,37 @@
1
+ import Logo from "./assets/logo.svg";
2
+ import "./Main.css";
3
+
4
+ export function MainPage() {
5
+ return (
6
+ <main className="container">
7
+ <img className="logo" src={Logo} alt="wasp" />
8
+
9
+ <h2 className="title">Welcome to Wasp!</h2>
10
+
11
+ <p className="content">
12
+ This is page <code>MainPage</code> located at route <code>/</code>.
13
+ <br />
14
+ Open <code>src/MainPage.tsx</code> to edit it.
15
+ </p>
16
+
17
+ <div className="buttons">
18
+ <a
19
+ className="button button-filled"
20
+ href="https://wasp.sh/docs/tutorial/create"
21
+ target="_blank"
22
+ rel="noreferrer noopener"
23
+ >
24
+ Take the Tutorial
25
+ </a>
26
+ <a
27
+ className="button button-outlined"
28
+ href="https://discord.com/invite/rzdnErX"
29
+ target="_blank"
30
+ rel="noreferrer noopener"
31
+ >
32
+ Chat on Discord
33
+ </a>
34
+ </div>
35
+ </main>
36
+ );
37
+ }
@@ -0,0 +1 @@
1
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 161 161"><defs><style>.cls-1{fill:#f5cc05;}.cls-2{fill-rule:evenodd;}</style></defs><g id="Page-1"><g id="Group-23"><circle id="Oval" class="cls-1" cx="80.5" cy="80.5" r="79"/><g id="Group-36"><g id="_" data-name="}"><path id="path-2" class="cls-2" d="M88.67,114.33h2.91q6,0,7.87-1.89c1.22-1.25,1.83-3.9,1.83-7.93V93.89c0-4.46.65-7.7,1.93-9.73s3.51-3.43,6.67-4.2q-4.69-1.08-6.65-4.12c-1.3-2-2-5.28-2-9.77V55.44q0-6-1.83-7.93t-7.87-1.88H88.67V39.5h2.65q10.65,0,14.24,3.15t3.59,12.62V65.56c0,4.28.77,7.24,2.29,8.87s4.3,2.44,8.32,2.44h2.74V83h-2.74q-6,0-8.32,2.49c-1.52,1.65-2.29,4.64-2.29,9v10.25q0,9.47-3.59,12.64T91.32,120.5H88.67Z"/><path id="path-2-2" data-name="path-2" class="cls-2" d="M88.67,114.33h2.91q6,0,7.87-1.89c1.22-1.25,1.83-3.9,1.83-7.93V93.89c0-4.46.65-7.7,1.93-9.73s3.51-3.43,6.67-4.2q-4.69-1.08-6.65-4.12c-1.3-2-2-5.28-2-9.77V55.44q0-6-1.83-7.93t-7.87-1.88H88.67V39.5h2.65q10.65,0,14.24,3.15t3.59,12.62V65.56c0,4.28.77,7.24,2.29,8.87s4.3,2.44,8.32,2.44h2.74V83h-2.74q-6,0-8.32,2.49c-1.52,1.65-2.29,4.64-2.29,9v10.25q0,9.47-3.59,12.64T91.32,120.5H88.67Z"/></g><g id="text831"><g id="_2" data-name="="><path id="path-3" class="cls-2" d="M38.5,85.15H75.83v7.58H38.5Zm0-17.88H75.83v7.49H38.5Z"/><path id="path-3-2" data-name="path-3" class="cls-2" d="M38.5,85.15H75.83v7.58H38.5Zm0-17.88H75.83v7.49H38.5Z"/></g></g></g></g></g></svg>
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.src.json" },
5
+ { "path": "./tsconfig.wasp.json" }
6
+ ]
7
+ }
@@ -0,0 +1,28 @@
1
+ // =============================== IMPORTANT =================================
2
+ // This file is mainly used for Wasp IDE support.
3
+ //
4
+ // Wasp will compile your code with slightly different (less strict) compilerOptions.
5
+ // You can increase the configuration's strictness (e.g., by adding
6
+ // "noUncheckedIndexedAccess": true), but you shouldn't reduce it (e.g., by
7
+ // adding "strict": false). Just keep in mind that this will only affect your
8
+ // IDE support, not the actual compilation.
9
+ //
10
+ // Full TypeScript configurability is coming very soon :)
11
+ {
12
+ "compilerOptions": {
13
+ "module": "esnext",
14
+ "composite": true,
15
+ "target": "esnext",
16
+ "moduleResolution": "bundler",
17
+ "jsx": "preserve",
18
+ "strict": true,
19
+ "esModuleInterop": true,
20
+ "isolatedModules": true,
21
+ "moduleDetection": "force",
22
+ "lib": ["dom", "dom.iterable", "esnext"],
23
+ "skipLibCheck": true,
24
+ "allowJs": true,
25
+ "outDir": ".wasp/out/user"
26
+ },
27
+ "include": ["src"]
28
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "skipLibCheck": true,
4
+ "target": "ES2022",
5
+ "isolatedModules": true,
6
+ "moduleDetection": "force",
7
+ "strict": true,
8
+ "noUnusedLocals": true,
9
+ "noUnusedParameters": true,
10
+ "module": "NodeNext",
11
+ "noEmit": true,
12
+ "lib": ["ES2023"]
13
+ },
14
+ "include": ["main.wasp.ts"]
15
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "vite";
2
+ import { wasp } from "wasp/client/vite";
3
+
4
+ export default defineConfig({
5
+ plugins: [wasp()],
6
+ server: {
7
+ open: true,
8
+ },
9
+ });
@@ -3,9 +3,7 @@
3
3
  # Because if not, we had situations where it would use the different version
4
4
  # locally and on Github CI. This way we ensure exact version is used,
5
5
  # and also have control over updating it (instead of update surprising us).
6
- {=! TODO: Upgrade this to the latest Alpine version once we update Prisma #2504 =}
7
- {=! (Alpine 3.21 at time of writing) =}
8
- FROM node:{= nodeVersion =}-alpine3.20 AS node
6
+ FROM node:{= nodeVersion =}-alpine3.23 AS node
9
7
 
10
8
 
11
9
  # We split Dockerfile into base, server-builder and server-production.
@@ -18,6 +16,10 @@ FROM node:{= nodeVersion =}-alpine3.20 AS node
18
16
 
19
17
  FROM node AS base
20
18
  RUN apk --no-cache -U upgrade # To ensure any potential security patches are applied.
19
+ # Alpine 3.21+ no longer includes openssl as a transitive dependency of the
20
+ # Node.js image. Prisma's native engine needs libssl at both build and runtime.
21
+ # TODO: Revisit once we upgrade to Prisma 6 (https://github.com/wasp-lang/wasp/issues/2504).
22
+ RUN apk add --no-cache openssl
21
23
 
22
24
 
23
25
  # Todo: The 'server-builder' image stays on disk under <none>:<none> and is
@@ -9,9 +9,15 @@ import { queryClientInitialized } from '../../operations/index'
9
9
  import { WebSocketProvider } from '../../webSocket/WebSocketProvider'
10
10
  {=/ areWebSocketsUsed =}
11
11
 
12
+ export type RouteMapping = Record<
13
+ string,
14
+ | { lazy: () => Promise<{ Component: React.ComponentType }> }
15
+ | { Component: React.ComponentType }
16
+ >;
17
+
12
18
  export type WaspAppProps = {
13
19
  rootElement?: React.ReactNode;
14
- routesMapping: Record<string, React.ComponentType>;
20
+ routesMapping: RouteMapping;
15
21
  }
16
22
 
17
23
  export function WaspApp({ rootElement, routesMapping }: Required<WaspAppProps>) {
@@ -8,13 +8,14 @@ import { OAuthCallbackPage } from "../pages/OAuthCallback"
8
8
 
9
9
  import { DefaultRootErrorBoundary } from '../components/DefaultRootErrorBoundary'
10
10
 
11
+ import type { RouteMapping } from '../components/WaspApp'
11
12
  import { routes } from '../../router/index'
12
13
 
13
14
  export function getRouter({
14
15
  routesMapping,
15
16
  rootElement,
16
17
  }: {
17
- routesMapping: Record<string, React.ComponentType>,
18
+ routesMapping: RouteMapping,
18
19
  rootElement: React.ReactNode,
19
20
  }) {
20
21
  const waspDefinedRoutes = [
@@ -28,7 +29,7 @@ export function getRouter({
28
29
  const userDefinedRoutes = Object.entries(routes).map(([routeKey, route]) => {
29
30
  return {
30
31
  path: route.to,
31
- Component: routesMapping[routeKey],
32
+ ...routesMapping[routeKey],
32
33
  }
33
34
  })
34
35
 
@@ -1,22 +1,39 @@
1
1
  {{={= =}=}}
2
- import * as z from 'zod'
2
+ import * as z from "zod"
3
3
 
4
4
  {=# envValidationSchema.isDefined =}
5
5
  {=& envValidationSchema.importStatement =}
6
- const userClientEnvSchema = {= envValidationSchema.importIdentifier =}
6
+ const userClientEnvSchema = {= envValidationSchema.importIdentifier =};
7
7
  {=/ envValidationSchema.isDefined =}
8
8
  {=^ envValidationSchema.isDefined =}
9
- const userClientEnvSchema = z.object({})
9
+ const userClientEnvSchema = z.object({});
10
10
  {=/ envValidationSchema.isDefined =}
11
11
 
12
- const waspClientEnvSchema = z.object({
13
- "{= serverUrlEnvVarName =}": z
14
- .string()
15
- .url({
16
- message: '{= serverUrlEnvVarName =} must be a valid URL',
12
+ const serverUrlSchema =
13
+ z.string({
14
+ error: '{= serverUrlEnvVarName =} is required',
17
15
  })
18
- .default('{= defaultServerUrl =}'),
19
- })
16
+ .pipe(
17
+ z.url({
18
+ error: '{= serverUrlEnvVarName =} must be a valid URL',
19
+ })
20
+ )
21
+
22
+ const waspDevClientEnvSchema = z.object({
23
+ "{= serverUrlEnvVarName =}": serverUrlSchema
24
+ .default("{= defaultServerUrl =}"),
25
+ });
26
+
27
+ const waspProdClientEnvSchema = z.object({
28
+ "{= serverUrlEnvVarName =}": serverUrlSchema,
29
+ });
20
30
 
21
31
  // PRIVATE API (sdk, Vite config)
22
- export const clientEnvSchema = userClientEnvSchema.merge(waspClientEnvSchema)
32
+ // TODO(franjo): Remove passing mode as param when this is no longer a plugin.
33
+ // See: https://github.com/wasp-lang/wasp/issues/3875.
34
+ export function getClientEnvSchema(mode: string) {
35
+ const waspClientEnvSchema = mode === "production"
36
+ ? waspProdClientEnvSchema
37
+ : waspDevClientEnvSchema;
38
+ return z.object({ ...userClientEnvSchema.shape, ...waspClientEnvSchema.shape })
39
+ }
@@ -1,5 +1,8 @@
1
- import { clientEnvSchema } from './env/schema.js'
2
- import { ensureEnvSchema } from '../env/validation.js'
1
+ import { ensureEnvSchema } from "../env/validation.js";
2
+ import { getClientEnvSchema } from "./env/schema.js";
3
3
 
4
4
  // PUBLIC API
5
- export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)
5
+ export const env = ensureEnvSchema(
6
+ import.meta.env,
7
+ getClientEnvSchema(import.meta.env.MODE),
8
+ );
@@ -1,19 +1,17 @@
1
- import { type Plugin } from 'vite'
1
+ import { type Plugin } from "vite";
2
2
 
3
- import { loadEnvVars } from './envFile.js'
4
3
  import {
4
+ formatZodEnvError,
5
5
  getValidatedEnvOrError,
6
- formatZodEnvErrors,
7
- } from '../../../env/validation.js'
8
- import { clientEnvSchema } from '../../env/schema.js'
9
- import { getColorizedConsoleFormatString } from '../../../universal/ansiColors.js'
10
-
11
- const redColorFormatString = getColorizedConsoleFormatString('red');
6
+ } from "../../../env/validation.js";
7
+ import { colorize } from "../../../universal/ansiColors.js";
8
+ import { getClientEnvSchema } from "../../env/schema.js";
9
+ import { loadEnvVars } from "./envFile.js";
12
10
 
13
11
  export function validateEnv(): Plugin {
14
- let validationResult: ReturnType<typeof getValidatedEnvOrError> | null = null
12
+ let validationResult: ReturnType<typeof getValidatedEnvOrError> | null = null;
15
13
  return {
16
- name: 'wasp:validate-env',
14
+ name: "wasp:validate-env",
17
15
  async configResolved(config) {
18
16
  const env = await loadEnvVars({
19
17
  rootDir: config.root,
@@ -23,33 +21,34 @@ export function validateEnv(): Plugin {
23
21
  // We load the env file variables only in development,
24
22
  // when building for production, users are expected to
25
23
  // provide the environment variables inline.
26
- loadDotEnvFile: config.command === 'serve',
27
- })
28
- validationResult = getValidatedEnvOrError(env, clientEnvSchema)
24
+ loadDotEnvFile: config.command === "serve",
25
+ });
26
+ const schema = getClientEnvSchema(config.mode);
27
+ validationResult = getValidatedEnvOrError(env, schema);
29
28
 
30
29
  // Exit if we are in build mode, because we can't show the error in the browser.
31
- if (config.command === 'build' && !validationResult.success) {
32
- const message = formatZodEnvErrors(validationResult.error.issues)
33
- console.error(`${redColorFormatString}${message}`)
34
- process.exit(1)
30
+ if (config.command === "build" && !validationResult.success) {
31
+ const validationErrorMessage = formatZodEnvError(validationResult.error);
32
+ console.error(colorize("red", validationErrorMessage));
33
+ process.exit(1);
35
34
  }
36
35
  },
37
36
  configureServer: (server) => {
38
37
  if (validationResult === null || validationResult.success) {
39
- return
38
+ return;
40
39
  }
41
40
 
42
41
  // Send the error to the browser.
43
- const message = formatZodEnvErrors(validationResult.error.issues)
44
- server.ws.on('connection', () => {
42
+ const validationErrorMessage = formatZodEnvError(validationResult.error);
43
+ server.ws.on("connection", () => {
45
44
  server.ws.send({
46
- type: 'error',
45
+ type: "error",
47
46
  err: {
48
- message,
49
- stack: '',
47
+ message: validationErrorMessage,
48
+ stack: "",
50
49
  },
51
- })
52
- })
50
+ });
51
+ });
53
52
  },
54
- }
53
+ };
55
54
  }
@@ -1,25 +1,46 @@
1
1
  {{={= =}=}}
2
- import { type PluginOption, mergeConfig } from "vite";
2
+ /// <reference types="vitest/config" />
3
+ import { type PluginOption } from "vite";
3
4
  import { defaultExclude } from "vitest/config"
4
5
 
6
+ // Vite merges `userConfig` and our `waspConfig` returned from the plugin.
7
+ // In that merge, primitive values from waspConfig take precedence, and
8
+ // arrays are concatenated.
9
+ //
10
+ // This allows us to treat config values differently:
11
+ // - Forced: hardcoded in the return object so they always win. If the
12
+ // user set one of these in their vite.config.ts, we throw an error.
13
+ // - Overridable: we read the user's value and use it or fall back to
14
+ // our default.
15
+ // - Additive (arrays): we only return Wasp's entries; Vite's merge
16
+ // appends them to whatever the user already has.
17
+
18
+ const forcedOptions = {
19
+ 'base': "{= baseDir =}",
20
+ 'envPrefix': "REACT_APP_",
21
+ 'build.outDir': "{= clientBuildDirPath =}",
22
+ } as const;
23
+
5
24
  export function waspConfig(): PluginOption {
6
25
  return {
7
26
  name: "wasp:config",
8
27
  enforce: 'pre',
9
28
  config(config) {
10
- return mergeConfig({
11
- base: "{= baseDir =}",
29
+ throwIfOverridingForcedOptions(config);
30
+
31
+ // Returned config is merged with the user's config by Vite (mergeConfig).
32
+ return {
33
+ base: forcedOptions['base'],
12
34
  optimizeDeps: {
13
35
  exclude: {=& depsExcludedFromOptimization =}
14
36
  },
15
37
  server: {
16
- port: {= defaultClientPort =},
17
- host: "0.0.0.0",
18
- open: true,
38
+ port: useUserValue(config.server?.port, {= defaultClientPort =}),
39
+ host: useUserValue(config.server?.host, "0.0.0.0"),
19
40
  },
20
- envPrefix: "REACT_APP_",
41
+ envPrefix: forcedOptions['envPrefix'],
21
42
  build: {
22
- outDir: "{= clientBuildDirPath =}",
43
+ outDir: forcedOptions['build.outDir'],
23
44
  },
24
45
  resolve: {
25
46
  // These packages rely on a single instance per page. Not deduping them
@@ -42,15 +63,40 @@ export function waspConfig(): PluginOption {
42
63
  ],
43
64
  },
44
65
  test: {
45
- globals: true,
46
- environment: "jsdom",
66
+ globals: useUserValue(config.test?.globals, true),
67
+ environment: useUserValue(config.test?.environment, "jsdom"),
47
68
  setupFiles: {=& vitest.setupFilesArray =},
48
69
  exclude: [
49
70
  ...defaultExclude,
50
71
  "{= vitest.excludeWaspArtefactsPattern =}",
51
72
  ]
52
73
  },
53
- }, config);
74
+ };
54
75
  }
55
76
  };
56
77
  }
78
+
79
+ function useUserValue<T>(userValue: T | undefined, defaultValue: T): T {
80
+ return userValue ?? defaultValue;
81
+ }
82
+
83
+ function throwIfOverridingForcedOptions(config: Record<string, any>): void {
84
+ const conflicts: string[] = [];
85
+ for (const [path, forcedValue] of Object.entries(forcedOptions)) {
86
+ const userValue = getByPath(config, path);
87
+ if (userValue !== undefined && userValue !== forcedValue) {
88
+ conflicts.push(
89
+ ` - "${path}" is set to ${JSON.stringify(userValue)}, but Wasp requires ${JSON.stringify(forcedValue)}`
90
+ );
91
+ }
92
+ }
93
+ if (conflicts.length > 0) {
94
+ throw new Error(
95
+ `Your vite.config.ts sets options that Wasp controls:\n${conflicts.join('\n')}\n\nRemove these from your Vite config, Wasp sets them automatically.`
96
+ );
97
+ }
98
+ }
99
+
100
+ function getByPath(obj: Record<string, any>, path: string): unknown {
101
+ return path.split('.').reduce<any>((node, segment) => node?.[segment], obj);
102
+ }
@@ -3,15 +3,34 @@
3
3
  {=# isAuthEnabled =}
4
4
  import { createAuthRequiredPage } from "wasp/client/app"
5
5
  {=/ isAuthEnabled =}
6
-
7
- // These files are used from user-land and the import paths below are relative to the
8
- // user's project dir, and not the SDK:
9
- {=# pagesToImport =}
10
- {=& importStatement =}
11
- {=/ pagesToImport =}
6
+ {=# routes =}
7
+ {=^ isLazy =}
8
+ {=& import.importStatement =}
9
+ {=/ isLazy =}
10
+ {=/ routes =}
12
11
 
13
12
  export const routesMapping = {
14
13
  {=# routes =}
15
- {= name =}: {= targetComponent =},
14
+ {=# isLazy =}
15
+ {= name =}: { lazy: async () => {
16
+ const Component = await {=& import.dynamicImportExpression =}
17
+ {=# isAuthRequired =}
18
+ return { Component: createAuthRequiredPage(Component) }
19
+ {=/ isAuthRequired =}
20
+ {=^ isAuthRequired =}
21
+ return { Component }
22
+ {=/ isAuthRequired =}
23
+ }},
24
+ {=/ isLazy =}
25
+ {=^ isLazy =}
26
+ {= name =}: {
27
+ {=# isAuthRequired =}
28
+ Component: createAuthRequiredPage({= import.importIdentifier =}),
29
+ {=/ isAuthRequired =}
30
+ {=^ isAuthRequired =}
31
+ Component: {= import.importIdentifier =},
32
+ {=/ isAuthRequired =}
33
+ },
34
+ {=/ isLazy =}
16
35
  {=/ routes =}
17
36
  } as const;
@@ -1,7 +1,7 @@
1
1
  import * as z from 'zod'
2
2
 
3
3
  // PUBLIC API
4
- export function defineEnvValidationSchema<Schema extends z.ZodObject<any>>(
4
+ export function defineEnvValidationSchema<Schema extends z.ZodObject>(
5
5
  schema: Schema,
6
6
  ): Schema {
7
7
  return schema