mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-11-23 01:54:37 +03:00
Enable users to define their env vars
This commit is contained in:
parent
1da4542578
commit
1d823aea51
@ -3,7 +3,15 @@ import * as z from 'zod'
|
||||
|
||||
import { ensureEnvSchema } from '../env/index.js'
|
||||
|
||||
const clientEnvSchema = z.object({
|
||||
{=# envValidationFn.isDefined =}
|
||||
{=& envValidationFn.importStatement =}
|
||||
const userClientEnvSchema = {= envValidationFn.importIdentifier =}()
|
||||
{=/ envValidationFn.isDefined =}
|
||||
{=^ envValidationFn.isDefined =}
|
||||
const userClientEnvSchema = z.object({})
|
||||
{=/ envValidationFn.isDefined =}
|
||||
|
||||
const waspClientEnvSchema = z.object({
|
||||
REACT_APP_API_URL: z
|
||||
.string({
|
||||
required_error: 'REACT_APP_API_URL is required',
|
||||
@ -11,4 +19,6 @@ const clientEnvSchema = z.object({
|
||||
.default('{= defaultServerUrl =}')
|
||||
})
|
||||
|
||||
const clientEnvSchema = waspClientEnvSchema.merge(userClientEnvSchema)
|
||||
|
||||
export const env = ensureEnvSchema(import.meta.env, clientEnvSchema)
|
||||
|
@ -3,7 +3,15 @@ import * as z from 'zod'
|
||||
|
||||
import { ensureEnvSchema } from '../env/index.js'
|
||||
|
||||
const serverCommonSchema = z.object({
|
||||
{=# envValidationFn.isDefined =}
|
||||
{=& envValidationFn.importStatement =}
|
||||
const userServerEnvSchema = {= envValidationFn.importIdentifier =}()
|
||||
{=/ envValidationFn.isDefined =}
|
||||
{=^ envValidationFn.isDefined =}
|
||||
const userServerEnvSchema = z.object({})
|
||||
{=/ envValidationFn.isDefined =}
|
||||
|
||||
const waspServerCommonSchema = z.object({
|
||||
PORT: z.coerce.number().default({= defaultServerPort =}),
|
||||
{= databaseUrlEnvVarName =}: z.string({
|
||||
required_error: '{= databaseUrlEnvVarName =} is required',
|
||||
@ -133,6 +141,7 @@ const serverProdSchema = z.object({
|
||||
{=/ isAuthEnabled =}
|
||||
})
|
||||
|
||||
const serverCommonSchema = waspServerCommonSchema.merge(userServerEnvSchema)
|
||||
const serverEnvSchema = z.discriminatedUnion('NODE_ENV', [
|
||||
serverDevSchema.merge(serverCommonSchema),
|
||||
serverProdSchema.merge(serverCommonSchema)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import PgBoss from 'pg-boss'
|
||||
import { env } from '../../../env.js'
|
||||
import { config } from '../../../index.js'
|
||||
import { config, env } from '../../../index.js'
|
||||
|
||||
const boss = createPgBoss()
|
||||
|
||||
|
@ -22,3 +22,5 @@ GITHUB_CLIENT_SECRET='dummy-gh-client-secret'
|
||||
# Dummy values here will allow app to run, but you will need real values to get Discord Auth to work.
|
||||
DISCORD_CLIENT_SECRET='dummy-discord-client-secret'
|
||||
DISCORD_CLIENT_ID='dummy-discord-client-id'
|
||||
|
||||
MY_ENV_VAR=123
|
||||
|
@ -52,12 +52,14 @@ app todoApp {
|
||||
onAfterLogin: import { onAfterLogin } from "@src/auth/hooks.js",
|
||||
},
|
||||
server: {
|
||||
setupFn: import setup from "@src/serverSetup",
|
||||
setupFn: import { setup } from "@src/serverSetup",
|
||||
middlewareConfigFn: import { serverMiddlewareFn } from "@src/serverSetup",
|
||||
envValidationFn: import { serverEnvValidationFn } from "@src/env",
|
||||
},
|
||||
client: {
|
||||
rootComponent: import { App } from "@src/App",
|
||||
setupFn: import setup from "@src/clientSetup"
|
||||
setupFn: import { setup } from "@src/clientSetup",
|
||||
envValidationFn: import { clientEnvValidationFn } from "@src/env",
|
||||
},
|
||||
db: {
|
||||
seeds: [
|
||||
|
6
waspc/examples/todoApp/prettier.config.cjs
Normal file
6
waspc/examples/todoApp/prettier.config.cjs
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 2,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 2,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
}
|
@ -17,10 +17,7 @@ export function App() {
|
||||
|
||||
const connectionIcon = isConnected ? '🟢' : '🔴'
|
||||
|
||||
// TODO: enable users to define their own client env vars
|
||||
const appName = import.meta.env.REACT_APP_NAME
|
||||
? import.meta.env.REACT_APP_NAME
|
||||
: 'TODO App'
|
||||
const appName = env.REACT_APP_NAME
|
||||
|
||||
return (
|
||||
<div className="app border-spacing-2 p-4">
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { testingAction } from 'wasp/client/operations'
|
||||
import { sayHi } from './util'
|
||||
|
||||
export default function setup() {
|
||||
export function setup() {
|
||||
console.log('This was called from the client setup function')
|
||||
testingAction()
|
||||
sayHi()
|
||||
|
13
waspc/examples/todoApp/src/env.ts
Normal file
13
waspc/examples/todoApp/src/env.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as z from 'zod'
|
||||
|
||||
export const serverEnvValidationFn = () =>
|
||||
z.object({
|
||||
MY_ENV_VAR: z.string({
|
||||
required_error: 'MY_ENV_VAR is required.',
|
||||
}),
|
||||
})
|
||||
|
||||
export const clientEnvValidationFn = () =>
|
||||
z.object({
|
||||
REACT_APP_NAME: z.string().default('TODO App'),
|
||||
})
|
@ -14,7 +14,7 @@ let someResource: string | undefined = undefined
|
||||
|
||||
export const getSomeResource = () => someResource
|
||||
|
||||
const setup: ServerSetupFn = async ({ app }) => {
|
||||
export const setup: ServerSetupFn = async ({ app }) => {
|
||||
addCustomRoute(app)
|
||||
|
||||
sayHi()
|
||||
@ -34,6 +34,8 @@ const setup: ServerSetupFn = async ({ app }) => {
|
||||
'submittedJob.pgBoss.details()',
|
||||
await submittedJob.pgBoss.details()
|
||||
)
|
||||
|
||||
console.log('Env var MY_ENV_VAR:', env.MY_ENV_VAR)
|
||||
}
|
||||
|
||||
function addCustomRoute(app: Application) {
|
||||
@ -52,5 +54,3 @@ export const serverMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
|
||||
)
|
||||
return middlewareConfig
|
||||
}
|
||||
|
||||
export default setup
|
||||
|
@ -16,6 +16,7 @@ data Client = Client
|
||||
{ setupFn :: Maybe ExtImport,
|
||||
rootComponent :: Maybe ExtImport,
|
||||
-- We expect the base dir to start with a slash e.g. /client
|
||||
baseDir :: Maybe String
|
||||
baseDir :: Maybe String,
|
||||
envValidationFn :: Maybe ExtImport
|
||||
}
|
||||
deriving (Show, Eq, Data, Generic, FromJSON)
|
||||
|
@ -14,6 +14,7 @@ import Wasp.AppSpec.ExtImport (ExtImport)
|
||||
|
||||
data Server = Server
|
||||
{ setupFn :: Maybe ExtImport,
|
||||
middlewareConfigFn :: Maybe ExtImport
|
||||
middlewareConfigFn :: Maybe ExtImport,
|
||||
envValidationFn :: Maybe ExtImport
|
||||
}
|
||||
deriving (Show, Eq, Data, Generic, FromJSON)
|
||||
|
@ -9,13 +9,17 @@ import Data.Maybe (isJust)
|
||||
import StrongPath (relfile)
|
||||
import Wasp.AppSpec (AppSpec)
|
||||
import qualified Wasp.AppSpec.App as AS.App
|
||||
import qualified Wasp.AppSpec.App.Client as AS.App.Client
|
||||
import qualified Wasp.AppSpec.App.Dependency as AS.Dependency
|
||||
import qualified Wasp.AppSpec.App.Server as AS.App.Server
|
||||
import Wasp.AppSpec.Valid (getApp)
|
||||
import qualified Wasp.Generator.AuthProviders as AuthProviders
|
||||
import qualified Wasp.Generator.EmailSenders as EmailSenders
|
||||
import Wasp.Generator.FileDraft (FileDraft)
|
||||
import qualified Wasp.Generator.JsImport as GJI
|
||||
import Wasp.Generator.Monad (Generator)
|
||||
import qualified Wasp.Generator.SdkGenerator.Common as C
|
||||
import Wasp.Generator.SdkGenerator.Server.OperationsGenerator (extImportToJsImport)
|
||||
import qualified Wasp.Generator.ServerGenerator.Common as Server
|
||||
import qualified Wasp.Generator.WebAppGenerator.Common as WebApp
|
||||
import qualified Wasp.Project.Db as Db
|
||||
@ -24,7 +28,7 @@ genEnvValidation :: AppSpec -> Generator [FileDraft]
|
||||
genEnvValidation spec =
|
||||
sequence
|
||||
[ genServerEnv spec,
|
||||
genClientEnv,
|
||||
genClientEnv spec,
|
||||
genFileCopy [relfile|env/index.ts|]
|
||||
]
|
||||
where
|
||||
@ -43,17 +47,25 @@ genServerEnv spec = return $ C.mkTmplFdWithData tmplPath tmplData
|
||||
"defaultServerPort" .= Server.defaultServerPort,
|
||||
"enabledAuthProviders" .= (AuthProviders.getEnabledAuthProvidersJson <$> maybeAuth),
|
||||
"isEmailSenderUsed" .= isJust maybeEmailSender,
|
||||
"enabledEmailSenders" .= (EmailSenders.getEnabledEmailProvidersJson <$> maybeEmailSender)
|
||||
"enabledEmailSenders" .= (EmailSenders.getEnabledEmailProvidersJson <$> maybeEmailSender),
|
||||
"envValidationFn" .= GJI.jsImportToImportJson (extImportToJsImport <$> maybeEnvValidationFn)
|
||||
]
|
||||
maybeAuth = AS.App.auth app
|
||||
maybeEmailSender = AS.App.emailSender app
|
||||
maybeEnvValidationFn = AS.App.server app >>= AS.App.Server.envValidationFn
|
||||
app = snd $ getApp spec
|
||||
|
||||
genClientEnv :: Generator FileDraft
|
||||
genClientEnv = return $ C.mkTmplFdWithData tmplPath tmplData
|
||||
genClientEnv :: AppSpec -> Generator FileDraft
|
||||
genClientEnv spec = return $ C.mkTmplFdWithData tmplPath tmplData
|
||||
where
|
||||
tmplPath = [relfile|client/env.ts|]
|
||||
tmplData = object ["defaultServerUrl" .= Server.defaultDevServerUrl]
|
||||
tmplData =
|
||||
object
|
||||
[ "defaultServerUrl" .= Server.defaultDevServerUrl,
|
||||
"envValidationFn" .= GJI.jsImportToImportJson (extImportToJsImport <$> maybeEnvValidationFn)
|
||||
]
|
||||
maybeEnvValidationFn = AS.App.client app >>= AS.App.Client.envValidationFn
|
||||
app = snd $ getApp spec
|
||||
|
||||
depsRequiredByEnvValidation :: [AS.Dependency.Dependency]
|
||||
depsRequiredByEnvValidation =
|
||||
|
Loading…
Reference in New Issue
Block a user