Update e2e tests

This commit is contained in:
Mihovil Ilakovac 2024-10-29 15:03:15 +01:00
parent 7333b259af
commit 80baf9c3b1
233 changed files with 1864 additions and 522 deletions

View File

@ -7,6 +7,7 @@ waspBuild/.wasp/build/package.json
waspBuild/.wasp/build/sdk/wasp/api/events.ts
waspBuild/.wasp/build/sdk/wasp/api/index.ts
waspBuild/.wasp/build/sdk/wasp/client/config.ts
waspBuild/.wasp/build/sdk/wasp/client/env.ts
waspBuild/.wasp/build/sdk/wasp/client/index.ts
waspBuild/.wasp/build/sdk/wasp/client/operations/actions/core.ts
waspBuild/.wasp/build/sdk/wasp/client/operations/actions/index.ts
@ -36,6 +37,9 @@ waspBuild/.wasp/build/sdk/wasp/dist/api/index.js.map
waspBuild/.wasp/build/sdk/wasp/dist/client/config.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/client/config.js
waspBuild/.wasp/build/sdk/wasp/dist/client/config.js.map
waspBuild/.wasp/build/sdk/wasp/dist/client/env.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/client/env.js
waspBuild/.wasp/build/sdk/wasp/dist/client/env.js.map
waspBuild/.wasp/build/sdk/wasp/dist/client/index.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/client/index.js
waspBuild/.wasp/build/sdk/wasp/dist/client/index.js.map
@ -99,6 +103,9 @@ waspBuild/.wasp/build/sdk/wasp/dist/dev/index.js.map
waspBuild/.wasp/build/sdk/wasp/dist/entities/index.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/entities/index.js
waspBuild/.wasp/build/sdk/wasp/dist/entities/index.js.map
waspBuild/.wasp/build/sdk/wasp/dist/env/index.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/env/index.js
waspBuild/.wasp/build/sdk/wasp/dist/env/index.js.map
waspBuild/.wasp/build/sdk/wasp/dist/ext-src/MainPage.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/ext-src/MainPage.jsx
waspBuild/.wasp/build/sdk/wasp/dist/ext-src/MainPage.jsx.map
@ -120,6 +127,9 @@ waspBuild/.wasp/build/sdk/wasp/dist/server/config.js.map
waspBuild/.wasp/build/sdk/wasp/dist/server/dbClient.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/server/dbClient.js
waspBuild/.wasp/build/sdk/wasp/dist/server/dbClient.js.map
waspBuild/.wasp/build/sdk/wasp/dist/server/env.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/server/env.js
waspBuild/.wasp/build/sdk/wasp/dist/server/env.js.map
waspBuild/.wasp/build/sdk/wasp/dist/server/index.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/server/index.js
waspBuild/.wasp/build/sdk/wasp/dist/server/index.js.map
@ -163,6 +173,7 @@ waspBuild/.wasp/build/sdk/wasp/dist/universal/validators.d.ts
waspBuild/.wasp/build/sdk/wasp/dist/universal/validators.js
waspBuild/.wasp/build/sdk/wasp/dist/universal/validators.js.map
waspBuild/.wasp/build/sdk/wasp/entities/index.ts
waspBuild/.wasp/build/sdk/wasp/env/index.ts
waspBuild/.wasp/build/sdk/wasp/ext-src/Main.css
waspBuild/.wasp/build/sdk/wasp/ext-src/MainPage.jsx
waspBuild/.wasp/build/sdk/wasp/ext-src/vite-env.d.ts
@ -175,6 +186,7 @@ waspBuild/.wasp/build/sdk/wasp/server/_types/serialization.ts
waspBuild/.wasp/build/sdk/wasp/server/_types/taggedEntities.ts
waspBuild/.wasp/build/sdk/wasp/server/config.ts
waspBuild/.wasp/build/sdk/wasp/server/dbClient.ts
waspBuild/.wasp/build/sdk/wasp/server/env.ts
waspBuild/.wasp/build/sdk/wasp/server/index.ts
waspBuild/.wasp/build/sdk/wasp/server/middleware/globalMiddleware.ts
waspBuild/.wasp/build/sdk/wasp/server/middleware/index.ts
@ -196,7 +208,6 @@ waspBuild/.wasp/build/server/README.md
waspBuild/.wasp/build/server/nodemon.json
waspBuild/.wasp/build/server/package.json
waspBuild/.wasp/build/server/rollup.config.js
waspBuild/.wasp/build/server/scripts/validate-env.mjs
waspBuild/.wasp/build/server/src/app.js
waspBuild/.wasp/build/server/src/middleware/globalMiddleware.ts
waspBuild/.wasp/build/server/src/middleware/index.ts
@ -236,6 +247,7 @@ waspBuild/.wasp/build/web-app/vite.config.ts
waspBuild/.wasp/out/sdk/wasp/api/events.ts
waspBuild/.wasp/out/sdk/wasp/api/index.ts
waspBuild/.wasp/out/sdk/wasp/client/config.ts
waspBuild/.wasp/out/sdk/wasp/client/env.ts
waspBuild/.wasp/out/sdk/wasp/client/index.ts
waspBuild/.wasp/out/sdk/wasp/client/operations/actions/core.ts
waspBuild/.wasp/out/sdk/wasp/client/operations/actions/index.ts
@ -265,6 +277,9 @@ waspBuild/.wasp/out/sdk/wasp/dist/api/index.js.map
waspBuild/.wasp/out/sdk/wasp/dist/client/config.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/client/config.js
waspBuild/.wasp/out/sdk/wasp/dist/client/config.js.map
waspBuild/.wasp/out/sdk/wasp/dist/client/env.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/client/env.js
waspBuild/.wasp/out/sdk/wasp/dist/client/env.js.map
waspBuild/.wasp/out/sdk/wasp/dist/client/index.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/client/index.js
waspBuild/.wasp/out/sdk/wasp/dist/client/index.js.map
@ -328,6 +343,9 @@ waspBuild/.wasp/out/sdk/wasp/dist/dev/index.js.map
waspBuild/.wasp/out/sdk/wasp/dist/entities/index.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/entities/index.js
waspBuild/.wasp/out/sdk/wasp/dist/entities/index.js.map
waspBuild/.wasp/out/sdk/wasp/dist/env/index.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/env/index.js
waspBuild/.wasp/out/sdk/wasp/dist/env/index.js.map
waspBuild/.wasp/out/sdk/wasp/dist/ext-src/MainPage.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/ext-src/MainPage.jsx
waspBuild/.wasp/out/sdk/wasp/dist/ext-src/MainPage.jsx.map
@ -349,6 +367,9 @@ waspBuild/.wasp/out/sdk/wasp/dist/server/config.js.map
waspBuild/.wasp/out/sdk/wasp/dist/server/dbClient.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/server/dbClient.js
waspBuild/.wasp/out/sdk/wasp/dist/server/dbClient.js.map
waspBuild/.wasp/out/sdk/wasp/dist/server/env.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/server/env.js
waspBuild/.wasp/out/sdk/wasp/dist/server/env.js.map
waspBuild/.wasp/out/sdk/wasp/dist/server/index.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/server/index.js
waspBuild/.wasp/out/sdk/wasp/dist/server/index.js.map
@ -392,6 +413,7 @@ waspBuild/.wasp/out/sdk/wasp/dist/universal/validators.d.ts
waspBuild/.wasp/out/sdk/wasp/dist/universal/validators.js
waspBuild/.wasp/out/sdk/wasp/dist/universal/validators.js.map
waspBuild/.wasp/out/sdk/wasp/entities/index.ts
waspBuild/.wasp/out/sdk/wasp/env/index.ts
waspBuild/.wasp/out/sdk/wasp/ext-src/Main.css
waspBuild/.wasp/out/sdk/wasp/ext-src/MainPage.jsx
waspBuild/.wasp/out/sdk/wasp/ext-src/vite-env.d.ts
@ -404,6 +426,7 @@ waspBuild/.wasp/out/sdk/wasp/server/_types/serialization.ts
waspBuild/.wasp/out/sdk/wasp/server/_types/taggedEntities.ts
waspBuild/.wasp/out/sdk/wasp/server/config.ts
waspBuild/.wasp/out/sdk/wasp/server/dbClient.ts
waspBuild/.wasp/out/sdk/wasp/server/env.ts
waspBuild/.wasp/out/sdk/wasp/server/index.ts
waspBuild/.wasp/out/sdk/wasp/server/middleware/globalMiddleware.ts
waspBuild/.wasp/out/sdk/wasp/server/middleware/index.ts

View File

@ -18,14 +18,21 @@
"file",
"../out/sdk/wasp/client/config.ts"
],
"d94e8bee5fd8f6793b511652b9ee558e57f4913595763137a5385cd929648168"
"4c5835ad64352cc87a4a17e41fd70333bc0d1eedd7339d7ad3d3507cdb64038d"
],
[
[
"file",
"../out/sdk/wasp/client/env.ts"
],
"f630ded0392d5b60be93e1852f80ea8c75bc10262aee6fb106b6eb2561339362"
],
[
[
"file",
"../out/sdk/wasp/client/index.ts"
],
"2b3651e7040a63cfd6a271c2aa89f21cf01170e0abeb6c5ab74adde324852fe4"
"d5a83474d2db10e1ac90899a0e302503bf26b3ab5ab00c07b5f5ce0d9e6de2d4"
],
[
[
@ -167,6 +174,13 @@
],
"c59b97b122b977b5171686c92ee5ff2d80d397c2e83cc0915affb6ee136406fb"
],
[
[
"file",
"../out/sdk/wasp/env/index.ts"
],
"cd4e86f3c0f1cacd868984f4103a47fe100037758adc8ba3adf1a5a9d6c1c880"
],
[
[
"file",
@ -200,7 +214,7 @@
"file",
"../out/sdk/wasp/package.json"
],
"6f1afd30c951e1f49740256440cd626c9cb521cf0822d93d2d2a5d63d8719d7b"
"d18af37d0188a6c4c9eef72705e31caf179664cb8621eaacf8bc4c21bc57c212"
],
[
[
@ -242,7 +256,7 @@
"file",
"../out/sdk/wasp/server/config.ts"
],
"5dd35660e0969defaa3c180179919f4922ab7bc041746872dff7f2280c1872ae"
"dd528b5db722210a5781f39c4d410024211f31964383bcc708a2611bd8d9d195"
],
[
[
@ -251,12 +265,19 @@
],
"50f11eb232174184be5fd44e8ee3875c30707b486c8c70c3f7bfb93609d38e66"
],
[
[
"file",
"../out/sdk/wasp/server/env.ts"
],
"b6195fe1bead580b7e4009586a55066196c496f085e68505bafd767f7b0048cf"
],
[
[
"file",
"../out/sdk/wasp/server/index.ts"
],
"51c3e0802764f72b88f6daaf148dba514ae817e233a40cc9b92ec91784f71f98"
"a8d2ffa7dfd0a13f7fb6135193bcdac1f860603bdd0ddc2843033fd4f6f6151f"
],
[
[
@ -347,7 +368,7 @@
"file",
"../out/sdk/wasp/universal/url.ts"
],
"8dc6e044a1a231b796465d94985ca47c5efd42a5d411b407a7d83a61ebae4b6d"
"58ff4ad8ffc79264d7215461571d909f3c5fb177ff32c67058d1da9cd4115d6e"
],
[
[
@ -375,7 +396,7 @@
"file",
"Dockerfile"
],
"8851d4e81582d58921a5646dcf063b31dbf8ce9a46f3d4710360d2047dc644b5"
"c7525922516652d1be259b7f1bf3a242e0ce1d3516c190aa0c28de57fe3d41de"
],
[
[
@ -417,7 +438,7 @@
"file",
"server/package.json"
],
"a4eb7e59ac5309fc5c39ccd7e19f4fdc7a9a568a3b393f62358ef6a6065d65c3"
"eaaa1e16e4962f38deb7220a7439a26b920ed7f852890242d084b4cebc63b7c3"
],
[
[
@ -426,13 +447,6 @@
],
"c1beb8264f11898364288d73b16f08d1923bac5f70038d9827978deb5b58a2da"
],
[
[
"file",
"server/scripts/validate-env.mjs"
],
"100177b4326ccab7362eff378315d532ad1cc17cd28d1ed5978cb167fd627746"
],
[
[
"file",

View File

@ -53,12 +53,12 @@ COPY --from=server-builder /app/node_modules ./node_modules
# Copying the SDK because 'validate-env.mjs' executes independent of the bundle
# and references the 'wasp' package.
COPY --from=server-builder /app/.wasp/out/sdk .wasp/out/sdk
# Copying 'server/node_modules' because 'validate-env.mjs' executes independent
# of the bundle and references the dotenv package.
# Copying 'server/node_modules' because we require dotenv package to
# load environment variables
# TODO: replace dotenv with native Node.js environment variable loading
COPY --from=server-builder /app/.wasp/build/server/node_modules .wasp/build/server/node_modules
COPY --from=server-builder /app/.wasp/build/server/bundle .wasp/build/server/bundle
COPY --from=server-builder /app/.wasp/build/server/package*.json .wasp/build/server/
COPY --from=server-builder /app/.wasp/build/server/scripts .wasp/build/server/scripts
COPY db/ .wasp/build/db/
EXPOSE ${PORT}
WORKDIR /app/.wasp/build/server

View File

@ -1 +1 @@
{"_waspSdkNpmDeps":{"dependencies":[{"name":"@prisma/client","version":"5.19.1"},{"name":"prisma","version":"5.19.1"},{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"express","version":"~4.21.0"},{"name":"mitt","version":"3.0.0"},{"name":"react","version":"^18.2.0"},{"name":"lodash.merge","version":"^4.6.2"},{"name":"react-router-dom","version":"^6.26.2"},{"name":"react-hook-form","version":"^7.45.4"},{"name":"superjson","version":"^2.2.1"},{"name":"vitest","version":"^1.2.1"},{"name":"@vitest/ui","version":"^1.2.1"},{"name":"jsdom","version":"^21.1.1"},{"name":"@testing-library/react","version":"^14.1.2"},{"name":"@testing-library/jest-dom","version":"^6.3.0"},{"name":"msw","version":"^1.1.0"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/express-serve-static-core","version":"^4.17.13"}]},"_userNpmDeps":{"userDependencies":[{"name":"react","version":"^18.2.0"},{"name":"wasp","version":"file:.wasp/out/sdk/wasp"}],"userDevDependencies":[{"name":"@types/react","version":"^18.0.37"},{"name":"prisma","version":"5.19.1"},{"name":"typescript","version":"^5.1.0"},{"name":"vite","version":"^4.3.9"}]},"_waspFrameworkNpmDeps":{"npmDepsForWebApp":{"dependencies":[{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"react-dom","version":"^18.2.0"},{"name":"react-router-dom","version":"^6.26.2"}],"devDependencies":[{"name":"@tsconfig/vite-react","version":"^2.0.0"},{"name":"@types/react-dom","version":"^18.0.11"},{"name":"@vitejs/plugin-react","version":"^4.2.1"},{"name":"dotenv","version":"^16.0.3"}]},"npmDepsForServer":{"dependencies":[{"name":"cookie-parser","version":"~1.4.6"},{"name":"cors","version":"^2.8.5"},{"name":"dotenv","version":"^16.0.2"},{"name":"express","version":"~4.21.0"},{"name":"helmet","version":"^6.0.0"},{"name":"morgan","version":"~1.10.0"},{"name":"superjson","version":"^2.2.1"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/cors","version":"^2.8.5"},{"name":"@types/express","version":"^4.17.13"},{"name":"@types/express-serve-static-core","version":"^4.17.13"},{"name":"@types/node","version":"^18.0.0"},{"name":"nodemon","version":"^2.0.19"},{"name":"rollup","version":"^4.9.6"},{"name":"rollup-plugin-esbuild","version":"^6.1.1"}]}}}
{"_waspSdkNpmDeps":{"dependencies":[{"name":"@prisma/client","version":"5.19.1"},{"name":"prisma","version":"5.19.1"},{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"express","version":"~4.21.0"},{"name":"mitt","version":"3.0.0"},{"name":"react","version":"^18.2.0"},{"name":"lodash.merge","version":"^4.6.2"},{"name":"react-router-dom","version":"^6.26.2"},{"name":"react-hook-form","version":"^7.45.4"},{"name":"superjson","version":"^2.2.1"},{"name":"vitest","version":"^1.2.1"},{"name":"@vitest/ui","version":"^1.2.1"},{"name":"jsdom","version":"^21.1.1"},{"name":"@testing-library/react","version":"^14.1.2"},{"name":"@testing-library/jest-dom","version":"^6.3.0"},{"name":"msw","version":"^1.1.0"},{"name":"zod","version":"^3.23.8"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/express-serve-static-core","version":"^4.17.13"}]},"_userNpmDeps":{"userDependencies":[{"name":"react","version":"^18.2.0"},{"name":"wasp","version":"file:.wasp/out/sdk/wasp"}],"userDevDependencies":[{"name":"@types/react","version":"^18.0.37"},{"name":"prisma","version":"5.19.1"},{"name":"typescript","version":"^5.1.0"},{"name":"vite","version":"^4.3.9"}]},"_waspFrameworkNpmDeps":{"npmDepsForWebApp":{"dependencies":[{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"react-dom","version":"^18.2.0"},{"name":"react-router-dom","version":"^6.26.2"}],"devDependencies":[{"name":"@tsconfig/vite-react","version":"^2.0.0"},{"name":"@types/react-dom","version":"^18.0.11"},{"name":"@vitejs/plugin-react","version":"^4.2.1"},{"name":"dotenv","version":"^16.0.3"}]},"npmDepsForServer":{"dependencies":[{"name":"cookie-parser","version":"~1.4.6"},{"name":"cors","version":"^2.8.5"},{"name":"dotenv","version":"^16.0.2"},{"name":"express","version":"~4.21.0"},{"name":"helmet","version":"^6.0.0"},{"name":"morgan","version":"~1.10.0"},{"name":"superjson","version":"^2.2.1"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/cors","version":"^2.8.5"},{"name":"@types/express","version":"^4.17.13"},{"name":"@types/express-serve-static-core","version":"^4.17.13"},{"name":"@types/node","version":"^18.0.0"},{"name":"nodemon","version":"^2.0.19"},{"name":"rollup","version":"^4.9.6"},{"name":"rollup-plugin-esbuild","version":"^6.1.1"}]}}}

View File

@ -1,6 +1,7 @@
import { stripTrailingSlash } from '../universal/url.js'
import { env } from './env.js'
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL)
// PUBLIC API
export type ClientConfig = {

View File

@ -0,0 +1,13 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
})
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)

View File

@ -12,3 +12,6 @@ export type Route = { method: HttpMethod; path: string }
// PUBLIC API
export { config, ClientConfig } from './config'
// PUBLIC API
export { env } from './env.js'

View File

@ -1,5 +1,6 @@
import { stripTrailingSlash } from '../universal/url.js';
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
import { env } from './env.js';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL);
// PUBLIC API
export const config = {
apiUrl,

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,uBAAuB,CAAC;AAOhG,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;AAOxD,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}

View File

@ -0,0 +1,3 @@
export declare const env: {
REACT_APP_API_URL: string;
};

View File

@ -0,0 +1,11 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
});
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../client/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,iBAAiB,EAAE,CAAC;SACjB,MAAM,CAAC;QACN,cAAc,EAAE,+BAA+B;KAChD,CAAC;SACD,OAAO,CAAC,uBAAuB,CAAC;CACpC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -9,3 +9,4 @@ export type Route = {
path: string;
};
export { config, ClientConfig } from './config';
export { env } from './env.js';

View File

@ -9,4 +9,6 @@ export var HttpMethod;
})(HttpMethod || (HttpMethod = {}));
// PUBLIC API
export { config } from './config';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA;AAE/C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -0,0 +1,2 @@
import * as z from 'zod';
export declare function ensureEnvSchema<Schema extends z.ZodTypeAny>(data: unknown, schema: Schema): z.infer<Schema>;

View File

@ -0,0 +1,26 @@
import * as z from 'zod';
const redColor = '\x1b[31m';
export function ensureEnvSchema(data, schema) {
try {
return schema.parse(data);
}
catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error();
for (const error of e.errors) {
console.error(`- ${error.message}`);
}
console.error();
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables');
}
else {
throw e;
}
}
}
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../env/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,MAAM,QAAQ,GAAG,UAAU,CAAA;AAE3B,MAAM,UAAU,eAAe,CAC7B,IAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,mEAAmE;QACnE,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACrC,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;AACH,CAAC"}

View File

@ -1,42 +1,35 @@
var _a;
import merge from 'lodash.merge';
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'development';
import { env } from './env.js';
import { stripTrailingSlash } from '../universal/url.js';
const config = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
};
const resolvedConfig = merge(config.all, config[nodeEnv]);
const resolvedConfig = merge(config.all, config[env.NODE_ENV]);
// PUBLIC API
export default resolvedConfig;
function getDevelopmentConfig() {
var _a, _b;
const frontendUrl = stripTrailingSlash((_a = process.env.WASP_WEB_CLIENT_URL) !== null && _a !== void 0 ? _a : 'http://localhost:3000/');
const serverUrl = stripTrailingSlash((_b = process.env.WASP_SERVER_URL) !== null && _b !== void 0 ? _b : 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
};
}
function getProductionConfig() {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
};
}

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,QAAQ,mCAAI,aAAa,CAAA;AAyBrD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,OAAO;QACZ,aAAa,EAAE,OAAO,KAAK,aAAa;QACxC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC1D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACrC,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;AACjE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,mCAAI,wBAAwB,CAAC,CAAC;IACpG,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,eAAe,mCAAI,uBAAuB,CAAC,CAAC;IAC7F,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAClE,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,aAAa;QACb,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAyBxD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,aAAa,EAAE,GAAG,CAAC,QAAQ,KAAK,aAAa;QAC7C,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;AACtE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}

View File

@ -0,0 +1,17 @@
export declare const env: {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "development";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
} | {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "production";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
};

View File

@ -0,0 +1,48 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
});
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
});
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
});
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
});
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
});
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
});
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
]);
export const env = ensureEnvSchema(process.env, serverEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../server/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;QACrB,cAAc,EAAE,0BAA0B;KAC3C,CAAC;IACF,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,8BAA8B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAC3D,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,6BAA6B;CAC9C,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,qCAAqC;CAC/C,CAAC,CAAA;AAEJ,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,iCAAiC;CAClD,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,yCAAyC;CACnD,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,cAAc,EAAE,wBAAwB;CACzC,CAAC,CAAA;AAEJ,2EAA2E;AAC3E,yCAAyC;AACzC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAClC,eAAe,EAAE,eAAe;SAC7B,OAAO,CAAC,uBAAuB,CAAC;IACnC,mBAAmB,EAAE,eAAe;SACjC,OAAO,CAAC,wBAAwB,CAAC;CACrC,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACjC,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,eAAe;CACrC,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE;IACvD,eAAe,CAAC,KAAK,CAAC,kBAAkB,CAAC;IACzC,gBAAgB,CAAC,KAAK,CAAC,kBAAkB,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -4,4 +4,5 @@ export { default as prisma } from './dbClient.js';
export { type ServerSetupFn } from './types/index.js';
export { HttpError } from './HttpError.js';
export { MiddlewareConfigFn } from './middleware/index.js';
export { env } from './env.js';
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>;

View File

@ -4,4 +4,6 @@ export { default as config } from './config.js';
export { default as prisma } from './dbClient.js';
// PUBLIC API
export { HttpError } from './HttpError.js';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -1 +1,2 @@
export declare function stripTrailingSlash(url?: string): string | undefined;
export declare function stripTrailingSlash(url: string): string;
export declare function stripTrailingSlash(url: undefined): undefined;

View File

@ -1 +1 @@
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}

View File

@ -0,0 +1,28 @@
import * as z from 'zod'
const redColor = '\x1b[31m'
export function ensureEnvSchema<Schema extends z.ZodTypeAny>(
data: unknown,
schema: Schema
): z.infer<Schema> {
try {
return schema.parse(data)
} catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error()
for (const error of e.errors) {
console.error(`- ${error.message}`)
}
console.error()
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables')
} else {
throw e
}
}
}

View File

@ -16,7 +16,8 @@
"react-hook-form": "^7.45.4",
"react-router-dom": "^6.26.2",
"superjson": "^2.2.1",
"vitest": "^1.2.1"
"vitest": "^1.2.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@tsconfig/node18": "latest",

View File

@ -1,8 +1,7 @@
import merge from 'lodash.merge'
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = process.env.NODE_ENV ?? 'development'
import { env } from './env.js'
import { stripTrailingSlash } from '../universal/url.js'
// TODO:
// - Use dotenv library to consume env vars from a file.
@ -33,41 +32,36 @@ const config: {
production: EnvConfig,
} = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
}
const resolvedConfig: Config = merge(config.all, config[nodeEnv])
const resolvedConfig: Config = merge(config.all, config[env.NODE_ENV])
// PUBLIC API
export default resolvedConfig
function getDevelopmentConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL ?? 'http://localhost:3000/');
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL ?? 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
}
}
function getProductionConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
}
}

View File

@ -0,0 +1,56 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
})
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
})
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
})
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
})
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
})
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
})
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
])
export const env = ensureEnvSchema(process.env, serverEnvSchema)

View File

@ -10,6 +10,8 @@ export { type ServerSetupFn } from './types/index.js'
export { HttpError } from './HttpError.js'
// PUBLIC API
export { MiddlewareConfigFn } from './middleware/index.js'
// PUBLIC API
export { env } from './env.js'
// PUBLIC API
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>

View File

@ -1,3 +1,5 @@
export function stripTrailingSlash(url: string): string
export function stripTrailingSlash(url: undefined): undefined
export function stripTrailingSlash(url?: string): string | undefined {
return url?.replace(/\/$/, "");
}

View File

@ -34,9 +34,8 @@
"bundle-and-start": "npm run bundle && npm run start",
"db-migrate-prod": "prisma migrate deploy --schema=../db/schema.prisma",
"db-seed": "npm run bundle && node --enable-source-maps -r dotenv/config bundle/dbSeed.js",
"start": "npm run validate-env && node --enable-source-maps -r dotenv/config bundle/server.js",
"start": "node --enable-source-maps -r dotenv/config bundle/server.js",
"start-production": "NODE_ENV=production npm run start",
"validate-env": "node -r dotenv/config ./scripts/validate-env.mjs",
"watch": "nodemon --exec 'npm run bundle-and-start || exit 1'"
},
"type": "module",

View File

@ -1,5 +0,0 @@
import { throwIfNotValidAbsoluteURL } from 'wasp/universal/validators';
console.info("🔍 Validating environment variables...");
throwIfNotValidAbsoluteURL(process.env.WASP_WEB_CLIENT_URL, 'Environment variable WASP_WEB_CLIENT_URL');
throwIfNotValidAbsoluteURL(process.env.WASP_SERVER_URL, 'Environment variable WASP_SERVER_URL');

View File

@ -1,6 +1,7 @@
import { stripTrailingSlash } from '../universal/url.js'
import { env } from './env.js'
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL)
// PUBLIC API
export type ClientConfig = {

View File

@ -0,0 +1,13 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
})
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)

View File

@ -12,3 +12,6 @@ export type Route = { method: HttpMethod; path: string }
// PUBLIC API
export { config, ClientConfig } from './config'
// PUBLIC API
export { env } from './env.js'

View File

@ -1,5 +1,6 @@
import { stripTrailingSlash } from '../universal/url.js';
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
import { env } from './env.js';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL);
// PUBLIC API
export const config = {
apiUrl,

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,uBAAuB,CAAC;AAOhG,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;AAOxD,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}

View File

@ -0,0 +1,3 @@
export declare const env: {
REACT_APP_API_URL: string;
};

View File

@ -0,0 +1,11 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
});
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../client/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,iBAAiB,EAAE,CAAC;SACjB,MAAM,CAAC;QACN,cAAc,EAAE,+BAA+B;KAChD,CAAC;SACD,OAAO,CAAC,uBAAuB,CAAC;CACpC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -9,3 +9,4 @@ export type Route = {
path: string;
};
export { config, ClientConfig } from './config';
export { env } from './env.js';

View File

@ -9,4 +9,6 @@ export var HttpMethod;
})(HttpMethod || (HttpMethod = {}));
// PUBLIC API
export { config } from './config';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA;AAE/C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -0,0 +1,2 @@
import * as z from 'zod';
export declare function ensureEnvSchema<Schema extends z.ZodTypeAny>(data: unknown, schema: Schema): z.infer<Schema>;

View File

@ -0,0 +1,26 @@
import * as z from 'zod';
const redColor = '\x1b[31m';
export function ensureEnvSchema(data, schema) {
try {
return schema.parse(data);
}
catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error();
for (const error of e.errors) {
console.error(`- ${error.message}`);
}
console.error();
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables');
}
else {
throw e;
}
}
}
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../env/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,MAAM,QAAQ,GAAG,UAAU,CAAA;AAE3B,MAAM,UAAU,eAAe,CAC7B,IAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,mEAAmE;QACnE,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACrC,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;AACH,CAAC"}

View File

@ -1,42 +1,35 @@
var _a;
import merge from 'lodash.merge';
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'development';
import { env } from './env.js';
import { stripTrailingSlash } from '../universal/url.js';
const config = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
};
const resolvedConfig = merge(config.all, config[nodeEnv]);
const resolvedConfig = merge(config.all, config[env.NODE_ENV]);
// PUBLIC API
export default resolvedConfig;
function getDevelopmentConfig() {
var _a, _b;
const frontendUrl = stripTrailingSlash((_a = process.env.WASP_WEB_CLIENT_URL) !== null && _a !== void 0 ? _a : 'http://localhost:3000/');
const serverUrl = stripTrailingSlash((_b = process.env.WASP_SERVER_URL) !== null && _b !== void 0 ? _b : 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
};
}
function getProductionConfig() {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
};
}

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,QAAQ,mCAAI,aAAa,CAAA;AAyBrD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,OAAO;QACZ,aAAa,EAAE,OAAO,KAAK,aAAa;QACxC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC1D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACrC,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;AACjE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,mCAAI,wBAAwB,CAAC,CAAC;IACpG,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,eAAe,mCAAI,uBAAuB,CAAC,CAAC;IAC7F,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAClE,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,aAAa;QACb,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAyBxD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,aAAa,EAAE,GAAG,CAAC,QAAQ,KAAK,aAAa;QAC7C,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;AACtE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}

View File

@ -0,0 +1,17 @@
export declare const env: {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "development";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
} | {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "production";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
};

View File

@ -0,0 +1,48 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
});
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
});
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
});
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
});
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
});
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
});
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
]);
export const env = ensureEnvSchema(process.env, serverEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../server/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;QACrB,cAAc,EAAE,0BAA0B;KAC3C,CAAC;IACF,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,8BAA8B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAC3D,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,6BAA6B;CAC9C,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,qCAAqC;CAC/C,CAAC,CAAA;AAEJ,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,iCAAiC;CAClD,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,yCAAyC;CACnD,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,cAAc,EAAE,wBAAwB;CACzC,CAAC,CAAA;AAEJ,2EAA2E;AAC3E,yCAAyC;AACzC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAClC,eAAe,EAAE,eAAe;SAC7B,OAAO,CAAC,uBAAuB,CAAC;IACnC,mBAAmB,EAAE,eAAe;SACjC,OAAO,CAAC,wBAAwB,CAAC;CACrC,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACjC,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,eAAe;CACrC,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE;IACvD,eAAe,CAAC,KAAK,CAAC,kBAAkB,CAAC;IACzC,gBAAgB,CAAC,KAAK,CAAC,kBAAkB,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -4,4 +4,5 @@ export { default as prisma } from './dbClient.js';
export { type ServerSetupFn } from './types/index.js';
export { HttpError } from './HttpError.js';
export { MiddlewareConfigFn } from './middleware/index.js';
export { env } from './env.js';
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>;

View File

@ -4,4 +4,6 @@ export { default as config } from './config.js';
export { default as prisma } from './dbClient.js';
// PUBLIC API
export { HttpError } from './HttpError.js';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -1 +1,2 @@
export declare function stripTrailingSlash(url?: string): string | undefined;
export declare function stripTrailingSlash(url: string): string;
export declare function stripTrailingSlash(url: undefined): undefined;

View File

@ -1 +1 @@
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}

View File

@ -0,0 +1,28 @@
import * as z from 'zod'
const redColor = '\x1b[31m'
export function ensureEnvSchema<Schema extends z.ZodTypeAny>(
data: unknown,
schema: Schema
): z.infer<Schema> {
try {
return schema.parse(data)
} catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error()
for (const error of e.errors) {
console.error(`- ${error.message}`)
}
console.error()
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables')
} else {
throw e
}
}
}

View File

@ -16,7 +16,8 @@
"react-hook-form": "^7.45.4",
"react-router-dom": "^6.26.2",
"superjson": "^2.2.1",
"vitest": "^1.2.1"
"vitest": "^1.2.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@tsconfig/node18": "latest",

View File

@ -1,8 +1,7 @@
import merge from 'lodash.merge'
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = process.env.NODE_ENV ?? 'development'
import { env } from './env.js'
import { stripTrailingSlash } from '../universal/url.js'
// TODO:
// - Use dotenv library to consume env vars from a file.
@ -33,41 +32,36 @@ const config: {
production: EnvConfig,
} = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
}
const resolvedConfig: Config = merge(config.all, config[nodeEnv])
const resolvedConfig: Config = merge(config.all, config[env.NODE_ENV])
// PUBLIC API
export default resolvedConfig
function getDevelopmentConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL ?? 'http://localhost:3000/');
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL ?? 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
}
}
function getProductionConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
}
}

View File

@ -0,0 +1,56 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
})
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
})
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
})
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
})
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
})
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
})
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
])
export const env = ensureEnvSchema(process.env, serverEnvSchema)

View File

@ -10,6 +10,8 @@ export { type ServerSetupFn } from './types/index.js'
export { HttpError } from './HttpError.js'
// PUBLIC API
export { MiddlewareConfigFn } from './middleware/index.js'
// PUBLIC API
export { env } from './env.js'
// PUBLIC API
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>

View File

@ -1,3 +1,5 @@
export function stripTrailingSlash(url: string): string
export function stripTrailingSlash(url: undefined): undefined
export function stripTrailingSlash(url?: string): string | undefined {
return url?.replace(/\/$/, "");
}

View File

@ -6,6 +6,7 @@ waspCompile/.wasp/out/installedNpmDepsLog.json
waspCompile/.wasp/out/sdk/wasp/api/events.ts
waspCompile/.wasp/out/sdk/wasp/api/index.ts
waspCompile/.wasp/out/sdk/wasp/client/config.ts
waspCompile/.wasp/out/sdk/wasp/client/env.ts
waspCompile/.wasp/out/sdk/wasp/client/index.ts
waspCompile/.wasp/out/sdk/wasp/client/operations/actions/core.ts
waspCompile/.wasp/out/sdk/wasp/client/operations/actions/index.ts
@ -35,6 +36,9 @@ waspCompile/.wasp/out/sdk/wasp/dist/api/index.js.map
waspCompile/.wasp/out/sdk/wasp/dist/client/config.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/client/config.js
waspCompile/.wasp/out/sdk/wasp/dist/client/config.js.map
waspCompile/.wasp/out/sdk/wasp/dist/client/env.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/client/env.js
waspCompile/.wasp/out/sdk/wasp/dist/client/env.js.map
waspCompile/.wasp/out/sdk/wasp/dist/client/index.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/client/index.js
waspCompile/.wasp/out/sdk/wasp/dist/client/index.js.map
@ -98,6 +102,9 @@ waspCompile/.wasp/out/sdk/wasp/dist/dev/index.js.map
waspCompile/.wasp/out/sdk/wasp/dist/entities/index.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/entities/index.js
waspCompile/.wasp/out/sdk/wasp/dist/entities/index.js.map
waspCompile/.wasp/out/sdk/wasp/dist/env/index.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/env/index.js
waspCompile/.wasp/out/sdk/wasp/dist/env/index.js.map
waspCompile/.wasp/out/sdk/wasp/dist/ext-src/MainPage.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/ext-src/MainPage.jsx
waspCompile/.wasp/out/sdk/wasp/dist/ext-src/MainPage.jsx.map
@ -119,6 +126,9 @@ waspCompile/.wasp/out/sdk/wasp/dist/server/config.js.map
waspCompile/.wasp/out/sdk/wasp/dist/server/dbClient.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/server/dbClient.js
waspCompile/.wasp/out/sdk/wasp/dist/server/dbClient.js.map
waspCompile/.wasp/out/sdk/wasp/dist/server/env.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/server/env.js
waspCompile/.wasp/out/sdk/wasp/dist/server/env.js.map
waspCompile/.wasp/out/sdk/wasp/dist/server/index.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/server/index.js
waspCompile/.wasp/out/sdk/wasp/dist/server/index.js.map
@ -162,6 +172,7 @@ waspCompile/.wasp/out/sdk/wasp/dist/universal/validators.d.ts
waspCompile/.wasp/out/sdk/wasp/dist/universal/validators.js
waspCompile/.wasp/out/sdk/wasp/dist/universal/validators.js.map
waspCompile/.wasp/out/sdk/wasp/entities/index.ts
waspCompile/.wasp/out/sdk/wasp/env/index.ts
waspCompile/.wasp/out/sdk/wasp/ext-src/Main.css
waspCompile/.wasp/out/sdk/wasp/ext-src/MainPage.jsx
waspCompile/.wasp/out/sdk/wasp/ext-src/vite-env.d.ts
@ -174,6 +185,7 @@ waspCompile/.wasp/out/sdk/wasp/server/_types/serialization.ts
waspCompile/.wasp/out/sdk/wasp/server/_types/taggedEntities.ts
waspCompile/.wasp/out/sdk/wasp/server/config.ts
waspCompile/.wasp/out/sdk/wasp/server/dbClient.ts
waspCompile/.wasp/out/sdk/wasp/server/env.ts
waspCompile/.wasp/out/sdk/wasp/server/index.ts
waspCompile/.wasp/out/sdk/wasp/server/middleware/globalMiddleware.ts
waspCompile/.wasp/out/sdk/wasp/server/middleware/index.ts
@ -196,7 +208,6 @@ waspCompile/.wasp/out/server/README.md
waspCompile/.wasp/out/server/nodemon.json
waspCompile/.wasp/out/server/package.json
waspCompile/.wasp/out/server/rollup.config.js
waspCompile/.wasp/out/server/scripts/validate-env.mjs
waspCompile/.wasp/out/server/src/app.js
waspCompile/.wasp/out/server/src/middleware/globalMiddleware.ts
waspCompile/.wasp/out/server/src/middleware/index.ts

View File

@ -18,14 +18,21 @@
"file",
"../out/sdk/wasp/client/config.ts"
],
"d94e8bee5fd8f6793b511652b9ee558e57f4913595763137a5385cd929648168"
"4c5835ad64352cc87a4a17e41fd70333bc0d1eedd7339d7ad3d3507cdb64038d"
],
[
[
"file",
"../out/sdk/wasp/client/env.ts"
],
"f630ded0392d5b60be93e1852f80ea8c75bc10262aee6fb106b6eb2561339362"
],
[
[
"file",
"../out/sdk/wasp/client/index.ts"
],
"2b3651e7040a63cfd6a271c2aa89f21cf01170e0abeb6c5ab74adde324852fe4"
"d5a83474d2db10e1ac90899a0e302503bf26b3ab5ab00c07b5f5ce0d9e6de2d4"
],
[
[
@ -167,6 +174,13 @@
],
"c59b97b122b977b5171686c92ee5ff2d80d397c2e83cc0915affb6ee136406fb"
],
[
[
"file",
"../out/sdk/wasp/env/index.ts"
],
"cd4e86f3c0f1cacd868984f4103a47fe100037758adc8ba3adf1a5a9d6c1c880"
],
[
[
"file",
@ -200,7 +214,7 @@
"file",
"../out/sdk/wasp/package.json"
],
"6f1afd30c951e1f49740256440cd626c9cb521cf0822d93d2d2a5d63d8719d7b"
"d18af37d0188a6c4c9eef72705e31caf179664cb8621eaacf8bc4c21bc57c212"
],
[
[
@ -242,7 +256,7 @@
"file",
"../out/sdk/wasp/server/config.ts"
],
"5dd35660e0969defaa3c180179919f4922ab7bc041746872dff7f2280c1872ae"
"dd528b5db722210a5781f39c4d410024211f31964383bcc708a2611bd8d9d195"
],
[
[
@ -251,12 +265,19 @@
],
"50f11eb232174184be5fd44e8ee3875c30707b486c8c70c3f7bfb93609d38e66"
],
[
[
"file",
"../out/sdk/wasp/server/env.ts"
],
"b6195fe1bead580b7e4009586a55066196c496f085e68505bafd767f7b0048cf"
],
[
[
"file",
"../out/sdk/wasp/server/index.ts"
],
"51c3e0802764f72b88f6daaf148dba514ae817e233a40cc9b92ec91784f71f98"
"a8d2ffa7dfd0a13f7fb6135193bcdac1f860603bdd0ddc2843033fd4f6f6151f"
],
[
[
@ -347,7 +368,7 @@
"file",
"../out/sdk/wasp/universal/url.ts"
],
"8dc6e044a1a231b796465d94985ca47c5efd42a5d411b407a7d83a61ebae4b6d"
"58ff4ad8ffc79264d7215461571d909f3c5fb177ff32c67058d1da9cd4115d6e"
],
[
[
@ -375,7 +396,7 @@
"file",
"Dockerfile"
],
"8851d4e81582d58921a5646dcf063b31dbf8ce9a46f3d4710360d2047dc644b5"
"c7525922516652d1be259b7f1bf3a242e0ce1d3516c190aa0c28de57fe3d41de"
],
[
[
@ -424,7 +445,7 @@
"file",
"server/package.json"
],
"a4eb7e59ac5309fc5c39ccd7e19f4fdc7a9a568a3b393f62358ef6a6065d65c3"
"eaaa1e16e4962f38deb7220a7439a26b920ed7f852890242d084b4cebc63b7c3"
],
[
[
@ -433,13 +454,6 @@
],
"c1beb8264f11898364288d73b16f08d1923bac5f70038d9827978deb5b58a2da"
],
[
[
"file",
"server/scripts/validate-env.mjs"
],
"100177b4326ccab7362eff378315d532ad1cc17cd28d1ed5978cb167fd627746"
],
[
[
"file",

View File

@ -53,12 +53,12 @@ COPY --from=server-builder /app/node_modules ./node_modules
# Copying the SDK because 'validate-env.mjs' executes independent of the bundle
# and references the 'wasp' package.
COPY --from=server-builder /app/.wasp/out/sdk .wasp/out/sdk
# Copying 'server/node_modules' because 'validate-env.mjs' executes independent
# of the bundle and references the dotenv package.
# Copying 'server/node_modules' because we require dotenv package to
# load environment variables
# TODO: replace dotenv with native Node.js environment variable loading
COPY --from=server-builder /app/.wasp/build/server/node_modules .wasp/build/server/node_modules
COPY --from=server-builder /app/.wasp/build/server/bundle .wasp/build/server/bundle
COPY --from=server-builder /app/.wasp/build/server/package*.json .wasp/build/server/
COPY --from=server-builder /app/.wasp/build/server/scripts .wasp/build/server/scripts
COPY db/ .wasp/build/db/
EXPOSE ${PORT}
WORKDIR /app/.wasp/build/server

View File

@ -1 +1 @@
{"_waspSdkNpmDeps":{"dependencies":[{"name":"@prisma/client","version":"5.19.1"},{"name":"prisma","version":"5.19.1"},{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"express","version":"~4.21.0"},{"name":"mitt","version":"3.0.0"},{"name":"react","version":"^18.2.0"},{"name":"lodash.merge","version":"^4.6.2"},{"name":"react-router-dom","version":"^6.26.2"},{"name":"react-hook-form","version":"^7.45.4"},{"name":"superjson","version":"^2.2.1"},{"name":"vitest","version":"^1.2.1"},{"name":"@vitest/ui","version":"^1.2.1"},{"name":"jsdom","version":"^21.1.1"},{"name":"@testing-library/react","version":"^14.1.2"},{"name":"@testing-library/jest-dom","version":"^6.3.0"},{"name":"msw","version":"^1.1.0"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/express-serve-static-core","version":"^4.17.13"}]},"_userNpmDeps":{"userDependencies":[{"name":"react","version":"^18.2.0"},{"name":"wasp","version":"file:.wasp/out/sdk/wasp"}],"userDevDependencies":[{"name":"@types/react","version":"^18.0.37"},{"name":"prisma","version":"5.19.1"},{"name":"typescript","version":"^5.1.0"},{"name":"vite","version":"^4.3.9"}]},"_waspFrameworkNpmDeps":{"npmDepsForWebApp":{"dependencies":[{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"react-dom","version":"^18.2.0"},{"name":"react-router-dom","version":"^6.26.2"}],"devDependencies":[{"name":"@tsconfig/vite-react","version":"^2.0.0"},{"name":"@types/react-dom","version":"^18.0.11"},{"name":"@vitejs/plugin-react","version":"^4.2.1"},{"name":"dotenv","version":"^16.0.3"}]},"npmDepsForServer":{"dependencies":[{"name":"cookie-parser","version":"~1.4.6"},{"name":"cors","version":"^2.8.5"},{"name":"dotenv","version":"^16.0.2"},{"name":"express","version":"~4.21.0"},{"name":"helmet","version":"^6.0.0"},{"name":"morgan","version":"~1.10.0"},{"name":"superjson","version":"^2.2.1"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/cors","version":"^2.8.5"},{"name":"@types/express","version":"^4.17.13"},{"name":"@types/express-serve-static-core","version":"^4.17.13"},{"name":"@types/node","version":"^18.0.0"},{"name":"nodemon","version":"^2.0.19"},{"name":"rollup","version":"^4.9.6"},{"name":"rollup-plugin-esbuild","version":"^6.1.1"}]}}}
{"_waspSdkNpmDeps":{"dependencies":[{"name":"@prisma/client","version":"5.19.1"},{"name":"prisma","version":"5.19.1"},{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"express","version":"~4.21.0"},{"name":"mitt","version":"3.0.0"},{"name":"react","version":"^18.2.0"},{"name":"lodash.merge","version":"^4.6.2"},{"name":"react-router-dom","version":"^6.26.2"},{"name":"react-hook-form","version":"^7.45.4"},{"name":"superjson","version":"^2.2.1"},{"name":"vitest","version":"^1.2.1"},{"name":"@vitest/ui","version":"^1.2.1"},{"name":"jsdom","version":"^21.1.1"},{"name":"@testing-library/react","version":"^14.1.2"},{"name":"@testing-library/jest-dom","version":"^6.3.0"},{"name":"msw","version":"^1.1.0"},{"name":"zod","version":"^3.23.8"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/express-serve-static-core","version":"^4.17.13"}]},"_userNpmDeps":{"userDependencies":[{"name":"react","version":"^18.2.0"},{"name":"wasp","version":"file:.wasp/out/sdk/wasp"}],"userDevDependencies":[{"name":"@types/react","version":"^18.0.37"},{"name":"prisma","version":"5.19.1"},{"name":"typescript","version":"^5.1.0"},{"name":"vite","version":"^4.3.9"}]},"_waspFrameworkNpmDeps":{"npmDepsForWebApp":{"dependencies":[{"name":"@tanstack/react-query","version":"^4.29.0"},{"name":"axios","version":"^1.4.0"},{"name":"react-dom","version":"^18.2.0"},{"name":"react-router-dom","version":"^6.26.2"}],"devDependencies":[{"name":"@tsconfig/vite-react","version":"^2.0.0"},{"name":"@types/react-dom","version":"^18.0.11"},{"name":"@vitejs/plugin-react","version":"^4.2.1"},{"name":"dotenv","version":"^16.0.3"}]},"npmDepsForServer":{"dependencies":[{"name":"cookie-parser","version":"~1.4.6"},{"name":"cors","version":"^2.8.5"},{"name":"dotenv","version":"^16.0.2"},{"name":"express","version":"~4.21.0"},{"name":"helmet","version":"^6.0.0"},{"name":"morgan","version":"~1.10.0"},{"name":"superjson","version":"^2.2.1"}],"devDependencies":[{"name":"@tsconfig/node18","version":"latest"},{"name":"@types/cors","version":"^2.8.5"},{"name":"@types/express","version":"^4.17.13"},{"name":"@types/express-serve-static-core","version":"^4.17.13"},{"name":"@types/node","version":"^18.0.0"},{"name":"nodemon","version":"^2.0.19"},{"name":"rollup","version":"^4.9.6"},{"name":"rollup-plugin-esbuild","version":"^6.1.1"}]}}}

View File

@ -1,6 +1,7 @@
import { stripTrailingSlash } from '../universal/url.js'
import { env } from './env.js'
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL)
// PUBLIC API
export type ClientConfig = {

View File

@ -0,0 +1,13 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
})
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)

View File

@ -12,3 +12,6 @@ export type Route = { method: HttpMethod; path: string }
// PUBLIC API
export { config, ClientConfig } from './config'
// PUBLIC API
export { env } from './env.js'

View File

@ -1,5 +1,6 @@
import { stripTrailingSlash } from '../universal/url.js';
const apiUrl = stripTrailingSlash(import.meta.env.REACT_APP_API_URL) || 'http://localhost:3001';
import { env } from './env.js';
const apiUrl = stripTrailingSlash(env.REACT_APP_API_URL);
// PUBLIC API
export const config = {
apiUrl,

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,uBAAuB,CAAC;AAOhG,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../client/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;AAOxD,aAAa;AACb,MAAM,CAAC,MAAM,MAAM,GAAiB;IAClC,MAAM;CACP,CAAA"}

View File

@ -0,0 +1,3 @@
export declare const env: {
REACT_APP_API_URL: string;
};

View File

@ -0,0 +1,11 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const clientEnvSchema = z.object({
REACT_APP_API_URL: z
.string({
required_error: 'REACT_APP_API_URL is required',
})
.default('http://localhost:3001')
});
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../client/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,iBAAiB,EAAE,CAAC;SACjB,MAAM,CAAC;QACN,cAAc,EAAE,+BAA+B;KAChD,CAAC;SACD,OAAO,CAAC,uBAAuB,CAAC;CACpC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -9,3 +9,4 @@ export type Route = {
path: string;
};
export { config, ClientConfig } from './config';
export { env } from './env.js';

View File

@ -9,4 +9,6 @@ export var HttpMethod;
})(HttpMethod || (HttpMethod = {}));
// PUBLIC API
export { config } from './config';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../client/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,mFAAmF;AACnF,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACrB,yBAAW,CAAA;IACX,2BAAa,CAAA;IACb,yBAAW,CAAA;IACX,+BAAiB,CAAA;AAClB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAKD,aAAa;AACb,OAAO,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAA;AAE/C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -0,0 +1,2 @@
import * as z from 'zod';
export declare function ensureEnvSchema<Schema extends z.ZodTypeAny>(data: unknown, schema: Schema): z.infer<Schema>;

View File

@ -0,0 +1,26 @@
import * as z from 'zod';
const redColor = '\x1b[31m';
export function ensureEnvSchema(data, schema) {
try {
return schema.parse(data);
}
catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error();
for (const error of e.errors) {
console.error(`- ${error.message}`);
}
console.error();
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables');
}
else {
throw e;
}
}
}
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../env/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,MAAM,QAAQ,GAAG,UAAU,CAAA;AAE3B,MAAM,UAAU,eAAe,CAC7B,IAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,mEAAmE;QACnE,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACrC,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;AACH,CAAC"}

View File

@ -1,42 +1,35 @@
var _a;
import merge from 'lodash.merge';
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'development';
import { env } from './env.js';
import { stripTrailingSlash } from '../universal/url.js';
const config = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
};
const resolvedConfig = merge(config.all, config[nodeEnv]);
const resolvedConfig = merge(config.all, config[env.NODE_ENV]);
// PUBLIC API
export default resolvedConfig;
function getDevelopmentConfig() {
var _a, _b;
const frontendUrl = stripTrailingSlash((_a = process.env.WASP_WEB_CLIENT_URL) !== null && _a !== void 0 ? _a : 'http://localhost:3000/');
const serverUrl = stripTrailingSlash((_b = process.env.WASP_SERVER_URL) !== null && _b !== void 0 ? _b : 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
};
}
function getProductionConfig() {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
};
}

View File

@ -1 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,QAAQ,mCAAI,aAAa,CAAA;AAyBrD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,OAAO;QACZ,aAAa,EAAE,OAAO,KAAK,aAAa;QACxC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC1D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACrC,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;AACjE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,mCAAI,wBAAwB,CAAC,CAAC;IACpG,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,eAAe,mCAAI,uBAAuB,CAAC,CAAC;IAC7F,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAClE,OAAO;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,SAAS;QACT,aAAa;QACb,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAyBxD,MAAM,MAAM,GAIR;IACF,GAAG,EAAE;QACH,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,aAAa,EAAE,GAAG,CAAC,QAAQ,KAAK,aAAa;QAC7C,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,kBAAkB,EAAE,EAAE;KACvB;IACD,WAAW,EAAE,oBAAoB,EAAE;IACnC,UAAU,EAAE,mBAAmB,EAAE;CAClC,CAAA;AAED,MAAM,cAAc,GAAW,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;AACtE,aAAa;AACb,eAAe,cAAc,CAAA;AAE7B,SAAS,oBAAoB;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,GAAG;KACxB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO;QACL,WAAW;QACX,SAAS;QACT,kBAAkB,EAAE,CAAC,WAAW,CAAC;KAClC,CAAA;AACH,CAAC"}

View File

@ -0,0 +1,17 @@
export declare const env: {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "development";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
} | {
PORT: number;
DATABASE_URL: string;
SKIP_EMAIL_VERIFICATION_IN_DEV: boolean;
NODE_ENV: "production";
WASP_SERVER_URL: string;
WASP_WEB_CLIENT_URL: string;
PG_BOSS_NEW_OPTIONS?: string | undefined;
};

View File

@ -0,0 +1,48 @@
import * as z from 'zod';
import { ensureEnvSchema } from '../env/index.js';
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
});
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
});
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
});
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
});
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
});
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
});
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
]);
export const env = ensureEnvSchema(process.env, serverEnvSchema);
//# sourceMappingURL=env.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../server/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;QACrB,cAAc,EAAE,0BAA0B;KAC3C,CAAC;IACF,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,8BAA8B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAC3D,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,6BAA6B;CAC9C,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,qCAAqC;CAC/C,CAAC,CAAA;AAEJ,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,cAAc,EAAE,iCAAiC;CAClD,CAAC;KACD,GAAG,CAAC;IACH,OAAO,EAAE,yCAAyC;CACnD,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,cAAc,EAAE,wBAAwB;CACzC,CAAC,CAAA;AAEJ,2EAA2E;AAC3E,yCAAyC;AACzC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAClC,eAAe,EAAE,eAAe;SAC7B,OAAO,CAAC,uBAAuB,CAAC;IACnC,mBAAmB,EAAE,eAAe;SACjC,OAAO,CAAC,wBAAwB,CAAC;CACrC,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACjC,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,eAAe;CACrC,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE;IACvD,eAAe,CAAC,KAAK,CAAC,kBAAkB,CAAC;IACzC,gBAAgB,CAAC,KAAK,CAAC,kBAAkB,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA"}

View File

@ -4,4 +4,5 @@ export { default as prisma } from './dbClient.js';
export { type ServerSetupFn } from './types/index.js';
export { HttpError } from './HttpError.js';
export { MiddlewareConfigFn } from './middleware/index.js';
export { env } from './env.js';
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>;

View File

@ -4,4 +4,6 @@ export { default as config } from './config.js';
export { default as prisma } from './dbClient.js';
// PUBLIC API
export { HttpError } from './HttpError.js';
// PUBLIC API
export { env } from './env.js';
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAA;AAC/C,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAGjD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA"}

View File

@ -1 +1,2 @@
export declare function stripTrailingSlash(url?: string): string | undefined;
export declare function stripTrailingSlash(url: string): string;
export declare function stripTrailingSlash(url: undefined): undefined;

View File

@ -1 +1 @@
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../universal/url.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,OAAO,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}

View File

@ -0,0 +1,28 @@
import * as z from 'zod'
const redColor = '\x1b[31m'
export function ensureEnvSchema<Schema extends z.ZodTypeAny>(
data: unknown,
schema: Schema
): z.infer<Schema> {
try {
return schema.parse(data)
} catch (e) {
// TODO: figure out how to output the error message in a better way
if (e instanceof z.ZodError) {
console.error(redColor, '╔═════════════════════════════╗');
console.error(redColor, '║ Env vars validation failed ║');
console.error(redColor, '╚═════════════════════════════╝');
console.error()
for (const error of e.errors) {
console.error(`- ${error.message}`)
}
console.error()
console.error(redColor, '═══════════════════════════════');
throw new Error('Error parsing environment variables')
} else {
throw e
}
}
}

View File

@ -16,7 +16,8 @@
"react-hook-form": "^7.45.4",
"react-router-dom": "^6.26.2",
"superjson": "^2.2.1",
"vitest": "^1.2.1"
"vitest": "^1.2.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@tsconfig/node18": "latest",

View File

@ -1,8 +1,7 @@
import merge from 'lodash.merge'
import { stripTrailingSlash } from "../universal/url.js";
const nodeEnv = process.env.NODE_ENV ?? 'development'
import { env } from './env.js'
import { stripTrailingSlash } from '../universal/url.js'
// TODO:
// - Use dotenv library to consume env vars from a file.
@ -33,41 +32,36 @@ const config: {
production: EnvConfig,
} = {
all: {
env: nodeEnv,
isDevelopment: nodeEnv === 'development',
port: process.env.PORT ? parseInt(process.env.PORT) : 3001,
databaseUrl: process.env.DATABASE_URL,
env: env.NODE_ENV,
isDevelopment: env.NODE_ENV === 'development',
port: env.PORT,
databaseUrl: env.DATABASE_URL,
allowedCORSOrigins: [],
},
development: getDevelopmentConfig(),
production: getProductionConfig(),
}
const resolvedConfig: Config = merge(config.all, config[nodeEnv])
const resolvedConfig: Config = merge(config.all, config[env.NODE_ENV])
// PUBLIC API
export default resolvedConfig
function getDevelopmentConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL ?? 'http://localhost:3000/');
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL ?? 'http://localhost:3001');
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
allowedCORSOrigins: '*',
}
}
function getProductionConfig(): EnvConfig {
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(process.env.WASP_SERVER_URL);
const frontendUrl = stripTrailingSlash(env.WASP_WEB_CLIENT_URL);
const serverUrl = stripTrailingSlash(env.WASP_SERVER_URL);
return {
// @ts-ignore
frontendUrl,
// @ts-ignore
serverUrl,
// @ts-ignore
allowedCORSOrigins: [frontendUrl],
}
}

View File

@ -0,0 +1,56 @@
import * as z from 'zod'
import { ensureEnvSchema } from '../env/index.js'
const serverCommonSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string({
required_error: 'DATABASE_URL is required',
}),
PG_BOSS_NEW_OPTIONS: z.string().optional(),
SKIP_EMAIL_VERIFICATION_IN_DEV: z.boolean().default(false),
})
const serverUrlSchema = z
.string({
required_error: 'WASP_SERVER_URL is required',
})
.url({
message: 'WASP_SERVER_URL must be a valid URL',
})
const clientUrlSchema = z
.string({
required_error: 'WASP_WEB_CLIENT_URL is required',
})
.url({
message: 'WASP_WEB_CLIENT_URL must be a valid URL',
})
const jwtTokenSchema = z
.string({
required_error: 'JWT_SECRET is required',
})
// In development, we provide default values for some environment variables
// to make the development process easier
const serverDevSchema = z.object({
NODE_ENV: z.literal('development'),
WASP_SERVER_URL: serverUrlSchema
.default('http://localhost:3001'),
WASP_WEB_CLIENT_URL: clientUrlSchema
.default('http://localhost:3000/'),
})
const serverProdSchema = z.object({
NODE_ENV: z.literal('production'),
WASP_SERVER_URL: serverUrlSchema,
WASP_WEB_CLIENT_URL: clientUrlSchema,
})
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
serverDevSchema.merge(serverCommonSchema),
serverProdSchema.merge(serverCommonSchema)
])
export const env = ensureEnvSchema(process.env, serverEnvSchema)

View File

@ -10,6 +10,8 @@ export { type ServerSetupFn } from './types/index.js'
export { HttpError } from './HttpError.js'
// PUBLIC API
export { MiddlewareConfigFn } from './middleware/index.js'
// PUBLIC API
export { env } from './env.js'
// PUBLIC API
export type DbSeedFn = (prisma: PrismaClient) => Promise<void>

View File

@ -1,3 +1,5 @@
export function stripTrailingSlash(url: string): string
export function stripTrailingSlash(url: undefined): undefined
export function stripTrailingSlash(url?: string): string | undefined {
return url?.replace(/\/$/, "");
}

Some files were not shown because too many files have changed in this diff Show More