@vite-env/core 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/dts-BgHTl6hC.cjs +114 -0
- package/dist/dts-BgHTl6hC.cjs.map +1 -0
- package/dist/dts.cjs +2 -1
- package/dist/dts.d.cts +10 -5
- package/dist/dts.d.mts +10 -5
- package/dist/dts.mjs +31 -23
- package/dist/dts.mjs.map +1 -1
- package/dist/format.cjs +6 -0
- package/dist/format.cjs.map +1 -1
- package/dist/format.d.cts +3 -1
- package/dist/format.d.mts +3 -1
- package/dist/format.mjs +6 -1
- package/dist/format.mjs.map +1 -1
- package/dist/index.cjs +2 -8
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/leak.cjs.map +1 -1
- package/dist/leak.d.cts +2 -2
- package/dist/leak.d.mts +2 -2
- package/dist/leak.mjs.map +1 -1
- package/dist/plugin.cjs +30 -13
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.mjs +31 -14
- package/dist/plugin.mjs.map +1 -1
- package/dist/schema.cjs +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.mts +1 -1
- package/dist/standard.cjs +46 -0
- package/dist/standard.cjs.map +1 -0
- package/dist/standard.d.cts +11 -0
- package/dist/standard.d.mts +11 -0
- package/dist/standard.mjs +43 -0
- package/dist/standard.mjs.map +1 -0
- package/dist/types-1okexcwM.d.cts +43 -0
- package/dist/types-DuWT_251.d.mts +43 -0
- package/package.json +19 -2
- package/dist/dts-DF71HNdJ.cjs +0 -100
- package/dist/dts-DF71HNdJ.cjs.map +0 -1
- package/dist/types-CluiDKAQ.d.mts +0 -22
- package/dist/types-DqTMuWwc.d.cts +0 -22
package/dist/plugin.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs","names":["process","path","loadEnvConfig","validateEnv","formatZodError","generateDts","detectServerLeak"],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { EnvDefinition } from './types'\n\nexport function buildClientModule(\n def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set(Object.keys(def.client ?? {}))\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { EnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateDts } from './dts'\nimport { formatZodError } from './format'\nimport { detectServerLeak } from './leak'\nimport { validateEnv } from './schema'\nimport { loadEnvSources } from './sources'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: EnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${formatted}`,\n )\n }\n\n lastValidated = result.data\n\n await generateDts(envDefinition, resolvedConfig.root)\n\n const count = Object.keys(result.data).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const leaks = detectServerLeak(\n envDefinition,\n lastValidated,\n bundle as Record<string, { type: string, code?: string }>,\n (keys) => {\n resolvedConfig.logger.warn(\n ` \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Leak detection skipped ${keys.length} server variable(s) with values shorter than 8 chars: ${keys.join(', ')}`,\n )\n },\n )\n\n if (leaks.length > 0) {\n const details = leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${details}\\n\\n These variables are marked as server-only and must never reach the browser.`,\n )\n }\n },\n\n configureServer(server) {\n const envDir = resolvedConfig.envDir || resolvedConfig.root\n server.watcher.add(path.join(envDir, '.env*'))\n\n let debounceTimer: ReturnType<typeof setTimeout>\n\n server.watcher.on('change', async (file) => {\n if (!path.basename(file).startsWith('.env'))\n return\n\n clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n try {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${formatted}`,\n )\n return\n }\n\n lastValidated = result.data\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n const serverMod = server.moduleGraph.getModuleById('\\0virtual:env/server')\n if (clientMod)\n server.moduleGraph.invalidateModule(clientMod)\n if (serverMod)\n server.moduleGraph.invalidateModule(serverMod)\n if (clientMod || serverMod) {\n server.hot.send({ type: 'full-reload' })\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidated`,\n )\n }\n }\n catch (e) {\n resolvedConfig.logger.error(\n `\\n \\x1B[31m✗\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Failed to reload env files: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAeA,eAAsB,eACpB,QACiC;AAOjC,QAAO;EACL,IAAA,GAAA,KAAA,SANA,OAAO,MACP,OAAO,UAAU,OAAO,MACxB,GACD;EAIC,GAAG,cAAcA,aAAAA,QAAQ,IAAI;EAC9B;;AAGH,SAAS,cAAc,KAAgD;AACrE,QAAO,OAAO,YACZ,OAAO,QAAQ,IAAI,CAAC,QACjB,UAAqC,OAAO,MAAM,OAAO,SAC3D,CACF;;;;ACjCH,SAAgB,kBACd,KACA,MACoC;CACpC,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;CAEzD,MAAM,aAAa,OAAO,YACxB,OAAO,QAAQ,KAAK,CAAC,QAAQ,CAAC,OAAO,WAAW,IAAI,EAAE,CAAC,CACxD;AAED,QAAO;EACL,YAAY;EACZ,MAAM;mCACyB,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;;EAEpE;;AAGH,SAAgB,kBACd,MACA,MACoC;AACpC,QAAO;EACL,YAAY;EACZ,MAAM;mCACyB,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;EAE9D;;;;ACTH,SAAwB,QAAQ,UAA0B,EAAE,EAAU;CACpE,IAAI;CACJ,IAAI;CACJ,IAAI,gBAAyC,EAAE;AAE/C,QAAO;EACL,MAAM;EACN,SAAS;EAET,MAAM,eAAe,QAAQ;AAC3B,oBAAiB;GAEjB,MAAM,aAAaC,UAAAA,QAAK,QACtB,OAAO,MACP,QAAQ,cAAc,SACvB;AAED,OAAI;AACF,oBAAgB,MAAMC,eAAAA,cAAc,WAAW;YAE1C,GAAG;AACR,UAAM,IAAI,MACR,qDAAqD,WAAW,kEAEhE,EAAE,OAAO,GAAG,CACb;;;EAIL,MAAM,aAAa;GACjB,MAAM,SAAS,MAAM,eAAe,eAAe;GACnD,MAAM,SAASC,eAAAA,YAAY,eAAe,OAAO;AAEjD,OAAI,CAAC,OAAO,SAAS;IACnB,MAAM,YAAYC,eAAAA,eAAe,OAAO,OAAO;AAC/C,UAAM,IAAI,MACR,gDAAgD,YACjD;;AAGH,mBAAgB,OAAO;AAEvB,SAAMC,YAAAA,YAAY,eAAe,eAAe,KAAK;GAErD,MAAM,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC;AACvC,kBAAe,OAAO,KACpB,gDAAgD,MAAM,sBACvD;;EAGH,UAAU,IAAI;AACZ,OAAI,OAAO,qBACT,QAAO;AACT,OAAI,OAAO,qBACT,QAAO;;EAGX,KAAK,IAAI;AACP,OAAI,OAAO,uBACT,QAAO,kBAAkB,eAAe,cAAc;AACxD,OAAI,OAAO,uBACT,QAAO,kBAAkB,eAAe,cAAc;;EAG1D,eAAe,UAAU,QAAQ;AAC/B,OAAI,eAAe,MAAM,IACvB;GAEF,MAAM,QAAQC,aAAAA,iBACZ,eACA,eACA,SACC,SAAS;AACR,mBAAe,OAAO,KACpB,uEAAuE,KAAK,OAAO,wDAAwD,KAAK,KAAK,KAAK,GAC3J;KAEJ;AAED,OAAI,MAAM,SAAS,GAAG;IACpB,MAAM,UAAU,MAAM,KAAI,MAAK,OAAO,EAAE,IAAI,YAAY,EAAE,QAAQ,CAAC,KAAK,KAAK;AAC7E,UAAM,IAAI,MACR,yEAAyE,QAAQ,mFAClF;;;EAIL,gBAAgB,QAAQ;GACtB,MAAM,SAAS,eAAe,UAAU,eAAe;AACvD,UAAO,QAAQ,IAAIL,UAAAA,QAAK,KAAK,QAAQ,QAAQ,CAAC;GAE9C,IAAI;AAEJ,UAAO,QAAQ,GAAG,UAAU,OAAO,SAAS;AAC1C,QAAI,CAACA,UAAAA,QAAK,SAAS,KAAK,CAAC,WAAW,OAAO,CACzC;AAEF,iBAAa,cAAc;AAC3B,oBAAgB,WAAW,YAAY;AACrC,SAAI;MACF,MAAM,SAAS,MAAM,eAAe,eAAe;MACnD,MAAM,SAASE,eAAAA,YAAY,eAAe,OAAO;AAEjD,UAAI,CAAC,OAAO,SAAS;OACnB,MAAM,YAAYC,eAAAA,eAAe,OAAO,OAAO;AAC/C,sBAAe,OAAO,KACpB,4EAA4E,YAC7E;AACD;;AAGF,sBAAgB,OAAO;MAEvB,MAAM,YAAY,OAAO,YAAY,cAAc,uBAAuB;MAC1E,MAAM,YAAY,OAAO,YAAY,cAAc,uBAAuB;AAC1E,UAAI,UACF,QAAO,YAAY,iBAAiB,UAAU;AAChD,UAAI,UACF,QAAO,YAAY,iBAAiB,UAAU;AAChD,UAAI,aAAa,WAAW;AAC1B,cAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAC;AACxC,sBAAe,OAAO,KACpB,+DACD;;cAGE,GAAG;AACR,qBAAe,OAAO,MACpB,8EAA8E,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE,GACzH;;OAEF,IAAI;KACP;;EAEL"}
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":["process","isStandardEnvDefinition","validateStandardEnv","formatStandardSchemaError","path","loadEnvConfig","generateStandardDts","detectServerLeak"],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { AnyEnvDefinition } from './types'\n\nexport function buildClientModule(\n def: AnyEnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set(Object.keys(def.client ?? {}))\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: AnyEnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { AnyEnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateStandardDts } from './dts'\nimport { formatStandardSchemaError } from './format'\nimport { detectServerLeak } from './leak'\nimport { loadEnvSources } from './sources'\nimport { isStandardEnvDefinition, validateStandardEnv } from './standard'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\n/**\n * Validates environment variables against the definition.\n * Routes to Zod or Standard Schema path based on definition type.\n * Zod modules are loaded dynamically to avoid requiring zod for Standard Schema users.\n */\nasync function validateAndFormat(\n def: AnyEnvDefinition,\n rawEnv: Record<string, string>,\n): Promise<{ data: Record<string, unknown> } | { error: string }> {\n if (isStandardEnvDefinition(def)) {\n const result = await validateStandardEnv(def, rawEnv)\n if (!result.success) {\n return { error: formatStandardSchemaError(result.errors) }\n }\n return { data: result.data }\n }\n\n const { validateEnv } = await import('./schema')\n const { formatZodError } = await import('./format')\n const result = validateEnv(def, rawEnv)\n if (!result.success) {\n return { error: formatZodError(result.errors) }\n }\n return { data: result.data }\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: AnyEnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = await validateAndFormat(envDefinition, rawEnv)\n\n if ('error' in result) {\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${result.error}`,\n )\n }\n\n lastValidated = result.data\n\n if (isStandardEnvDefinition(envDefinition)) {\n await generateStandardDts(envDefinition, resolvedConfig.root)\n }\n else {\n const { generateDts } = await import('./dts')\n await generateDts(envDefinition, resolvedConfig.root)\n }\n\n const count = Object.keys(lastValidated).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const leaks = detectServerLeak(\n envDefinition,\n lastValidated,\n bundle as Record<string, { type: string, code?: string }>,\n (keys) => {\n resolvedConfig.logger.warn(\n ` \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Leak detection skipped ${keys.length} server variable(s) with values shorter than 8 chars: ${keys.join(', ')}`,\n )\n },\n )\n\n if (leaks.length > 0) {\n const details = leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${details}\\n\\n These variables are marked as server-only and must never reach the browser.`,\n )\n }\n },\n\n configureServer(server) {\n const envDir = resolvedConfig.envDir || resolvedConfig.root\n server.watcher.add(path.join(envDir, '.env*'))\n\n let debounceTimer: ReturnType<typeof setTimeout>\n\n server.watcher.on('change', async (file) => {\n if (!path.basename(file).startsWith('.env'))\n return\n\n clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n try {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = await validateAndFormat(envDefinition, rawEnv)\n\n if ('error' in result) {\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${result.error}`,\n )\n return\n }\n\n lastValidated = result.data\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n const serverMod = server.moduleGraph.getModuleById('\\0virtual:env/server')\n if (clientMod)\n server.moduleGraph.invalidateModule(clientMod)\n if (serverMod)\n server.moduleGraph.invalidateModule(serverMod)\n if (clientMod || serverMod) {\n server.hot.send({ type: 'full-reload' })\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidated`,\n )\n }\n }\n catch (e) {\n resolvedConfig.logger.error(\n `\\n \\x1B[31m✗\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Failed to reload env files: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":"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"}
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isStandardEnvDefinition, validateStandardEnv } from "./standard.mjs";
|
|
2
2
|
import { loadEnvConfig } from "./config.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { generateStandardDts } from "./dts.mjs";
|
|
4
|
+
import { formatStandardSchemaError } from "./format.mjs";
|
|
5
5
|
import { detectServerLeak } from "./leak.mjs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import process from "node:process";
|
|
@@ -48,6 +48,23 @@ export default env;`
|
|
|
48
48
|
}
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/plugin.ts
|
|
51
|
+
/**
|
|
52
|
+
* Validates environment variables against the definition.
|
|
53
|
+
* Routes to Zod or Standard Schema path based on definition type.
|
|
54
|
+
* Zod modules are loaded dynamically to avoid requiring zod for Standard Schema users.
|
|
55
|
+
*/
|
|
56
|
+
async function validateAndFormat(def, rawEnv) {
|
|
57
|
+
if (isStandardEnvDefinition(def)) {
|
|
58
|
+
const result = await validateStandardEnv(def, rawEnv);
|
|
59
|
+
if (!result.success) return { error: formatStandardSchemaError(result.errors) };
|
|
60
|
+
return { data: result.data };
|
|
61
|
+
}
|
|
62
|
+
const { validateEnv } = await import("./schema.mjs");
|
|
63
|
+
const { formatZodError } = await import("./format.mjs");
|
|
64
|
+
const result = validateEnv(def, rawEnv);
|
|
65
|
+
if (!result.success) return { error: formatZodError(result.errors) };
|
|
66
|
+
return { data: result.data };
|
|
67
|
+
}
|
|
51
68
|
function ViteEnv(options = {}) {
|
|
52
69
|
let resolvedConfig;
|
|
53
70
|
let envDefinition;
|
|
@@ -66,14 +83,15 @@ function ViteEnv(options = {}) {
|
|
|
66
83
|
},
|
|
67
84
|
async buildStart() {
|
|
68
85
|
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
69
|
-
const result =
|
|
70
|
-
if (
|
|
71
|
-
const formatted = formatZodError(result.errors);
|
|
72
|
-
throw new Error(`[vite-env] Environment validation failed:\n\n${formatted}`);
|
|
73
|
-
}
|
|
86
|
+
const result = await validateAndFormat(envDefinition, rawEnv);
|
|
87
|
+
if ("error" in result) throw new Error(`[vite-env] Environment validation failed:\n\n${result.error}`);
|
|
74
88
|
lastValidated = result.data;
|
|
75
|
-
await
|
|
76
|
-
|
|
89
|
+
if (isStandardEnvDefinition(envDefinition)) await generateStandardDts(envDefinition, resolvedConfig.root);
|
|
90
|
+
else {
|
|
91
|
+
const { generateDts } = await import("./dts.mjs");
|
|
92
|
+
await generateDts(envDefinition, resolvedConfig.root);
|
|
93
|
+
}
|
|
94
|
+
const count = Object.keys(lastValidated).length;
|
|
77
95
|
resolvedConfig.logger.info(` \x1B[32m✓\x1B[0m \x1B[36m[vite-env]\x1B[0m ${count} variables validated`);
|
|
78
96
|
},
|
|
79
97
|
resolveId(id) {
|
|
@@ -104,10 +122,9 @@ function ViteEnv(options = {}) {
|
|
|
104
122
|
debounceTimer = setTimeout(async () => {
|
|
105
123
|
try {
|
|
106
124
|
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
107
|
-
const result =
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
resolvedConfig.logger.warn(`\n \x1B[33m⚠\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidation failed:\n${formatted}`);
|
|
125
|
+
const result = await validateAndFormat(envDefinition, rawEnv);
|
|
126
|
+
if ("error" in result) {
|
|
127
|
+
resolvedConfig.logger.warn(`\n \x1B[33m⚠\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidation failed:\n${result.error}`);
|
|
111
128
|
return;
|
|
112
129
|
}
|
|
113
130
|
lastValidated = result.data;
|
package/dist/plugin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { EnvDefinition } from './types'\n\nexport function buildClientModule(\n def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set(Object.keys(def.client ?? {}))\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { EnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateDts } from './dts'\nimport { formatZodError } from './format'\nimport { detectServerLeak } from './leak'\nimport { validateEnv } from './schema'\nimport { loadEnvSources } from './sources'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: EnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${formatted}`,\n )\n }\n\n lastValidated = result.data\n\n await generateDts(envDefinition, resolvedConfig.root)\n\n const count = Object.keys(result.data).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const leaks = detectServerLeak(\n envDefinition,\n lastValidated,\n bundle as Record<string, { type: string, code?: string }>,\n (keys) => {\n resolvedConfig.logger.warn(\n ` \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Leak detection skipped ${keys.length} server variable(s) with values shorter than 8 chars: ${keys.join(', ')}`,\n )\n },\n )\n\n if (leaks.length > 0) {\n const details = leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${details}\\n\\n These variables are marked as server-only and must never reach the browser.`,\n )\n }\n },\n\n configureServer(server) {\n const envDir = resolvedConfig.envDir || resolvedConfig.root\n server.watcher.add(path.join(envDir, '.env*'))\n\n let debounceTimer: ReturnType<typeof setTimeout>\n\n server.watcher.on('change', async (file) => {\n if (!path.basename(file).startsWith('.env'))\n return\n\n clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n try {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${formatted}`,\n )\n return\n }\n\n lastValidated = result.data\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n const serverMod = server.moduleGraph.getModuleById('\\0virtual:env/server')\n if (clientMod)\n server.moduleGraph.invalidateModule(clientMod)\n if (serverMod)\n server.moduleGraph.invalidateModule(serverMod)\n if (clientMod || serverMod) {\n server.hot.send({ type: 'full-reload' })\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidated`,\n )\n }\n }\n catch (e) {\n resolvedConfig.logger.error(\n `\\n \\x1B[31m✗\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Failed to reload env files: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAeA,eAAsB,eACpB,QACiC;AAOjC,QAAO;EACL,GAPc,QACd,OAAO,MACP,OAAO,UAAU,OAAO,MACxB,GACD;EAIC,GAAG,cAAc,QAAQ,IAAI;EAC9B;;AAGH,SAAS,cAAc,KAAgD;AACrE,QAAO,OAAO,YACZ,OAAO,QAAQ,IAAI,CAAC,QACjB,UAAqC,OAAO,MAAM,OAAO,SAC3D,CACF;;;;ACjCH,SAAgB,kBACd,KACA,MACoC;CACpC,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;CAEzD,MAAM,aAAa,OAAO,YACxB,OAAO,QAAQ,KAAK,CAAC,QAAQ,CAAC,OAAO,WAAW,IAAI,EAAE,CAAC,CACxD;AAED,QAAO;EACL,YAAY;EACZ,MAAM;mCACyB,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;;EAEpE;;AAGH,SAAgB,kBACd,MACA,MACoC;AACpC,QAAO;EACL,YAAY;EACZ,MAAM;mCACyB,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;EAE9D;;;;ACTH,SAAwB,QAAQ,UAA0B,EAAE,EAAU;CACpE,IAAI;CACJ,IAAI;CACJ,IAAI,gBAAyC,EAAE;AAE/C,QAAO;EACL,MAAM;EACN,SAAS;EAET,MAAM,eAAe,QAAQ;AAC3B,oBAAiB;GAEjB,MAAM,aAAa,KAAK,QACtB,OAAO,MACP,QAAQ,cAAc,SACvB;AAED,OAAI;AACF,oBAAgB,MAAM,cAAc,WAAW;YAE1C,GAAG;AACR,UAAM,IAAI,MACR,qDAAqD,WAAW,kEAEhE,EAAE,OAAO,GAAG,CACb;;;EAIL,MAAM,aAAa;GACjB,MAAM,SAAS,MAAM,eAAe,eAAe;GACnD,MAAM,SAAS,YAAY,eAAe,OAAO;AAEjD,OAAI,CAAC,OAAO,SAAS;IACnB,MAAM,YAAY,eAAe,OAAO,OAAO;AAC/C,UAAM,IAAI,MACR,gDAAgD,YACjD;;AAGH,mBAAgB,OAAO;AAEvB,SAAM,YAAY,eAAe,eAAe,KAAK;GAErD,MAAM,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC;AACvC,kBAAe,OAAO,KACpB,gDAAgD,MAAM,sBACvD;;EAGH,UAAU,IAAI;AACZ,OAAI,OAAO,qBACT,QAAO;AACT,OAAI,OAAO,qBACT,QAAO;;EAGX,KAAK,IAAI;AACP,OAAI,OAAO,uBACT,QAAO,kBAAkB,eAAe,cAAc;AACxD,OAAI,OAAO,uBACT,QAAO,kBAAkB,eAAe,cAAc;;EAG1D,eAAe,UAAU,QAAQ;AAC/B,OAAI,eAAe,MAAM,IACvB;GAEF,MAAM,QAAQ,iBACZ,eACA,eACA,SACC,SAAS;AACR,mBAAe,OAAO,KACpB,uEAAuE,KAAK,OAAO,wDAAwD,KAAK,KAAK,KAAK,GAC3J;KAEJ;AAED,OAAI,MAAM,SAAS,GAAG;IACpB,MAAM,UAAU,MAAM,KAAI,MAAK,OAAO,EAAE,IAAI,YAAY,EAAE,QAAQ,CAAC,KAAK,KAAK;AAC7E,UAAM,IAAI,MACR,yEAAyE,QAAQ,mFAClF;;;EAIL,gBAAgB,QAAQ;GACtB,MAAM,SAAS,eAAe,UAAU,eAAe;AACvD,UAAO,QAAQ,IAAI,KAAK,KAAK,QAAQ,QAAQ,CAAC;GAE9C,IAAI;AAEJ,UAAO,QAAQ,GAAG,UAAU,OAAO,SAAS;AAC1C,QAAI,CAAC,KAAK,SAAS,KAAK,CAAC,WAAW,OAAO,CACzC;AAEF,iBAAa,cAAc;AAC3B,oBAAgB,WAAW,YAAY;AACrC,SAAI;MACF,MAAM,SAAS,MAAM,eAAe,eAAe;MACnD,MAAM,SAAS,YAAY,eAAe,OAAO;AAEjD,UAAI,CAAC,OAAO,SAAS;OACnB,MAAM,YAAY,eAAe,OAAO,OAAO;AAC/C,sBAAe,OAAO,KACpB,4EAA4E,YAC7E;AACD;;AAGF,sBAAgB,OAAO;MAEvB,MAAM,YAAY,OAAO,YAAY,cAAc,uBAAuB;MAC1E,MAAM,YAAY,OAAO,YAAY,cAAc,uBAAuB;AAC1E,UAAI,UACF,QAAO,YAAY,iBAAiB,UAAU;AAChD,UAAI,UACF,QAAO,YAAY,iBAAiB,UAAU;AAChD,UAAI,aAAa,WAAW;AAC1B,cAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAC;AACxC,sBAAe,OAAO,KACpB,+DACD;;cAGE,GAAG;AACR,qBAAe,OAAO,MACpB,8EAA8E,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE,GACzH;;OAEF,IAAI;KACP;;EAEL"}
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { AnyEnvDefinition } from './types'\n\nexport function buildClientModule(\n def: AnyEnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set(Object.keys(def.client ?? {}))\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: AnyEnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { AnyEnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateStandardDts } from './dts'\nimport { formatStandardSchemaError } from './format'\nimport { detectServerLeak } from './leak'\nimport { loadEnvSources } from './sources'\nimport { isStandardEnvDefinition, validateStandardEnv } from './standard'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\n/**\n * Validates environment variables against the definition.\n * Routes to Zod or Standard Schema path based on definition type.\n * Zod modules are loaded dynamically to avoid requiring zod for Standard Schema users.\n */\nasync function validateAndFormat(\n def: AnyEnvDefinition,\n rawEnv: Record<string, string>,\n): Promise<{ data: Record<string, unknown> } | { error: string }> {\n if (isStandardEnvDefinition(def)) {\n const result = await validateStandardEnv(def, rawEnv)\n if (!result.success) {\n return { error: formatStandardSchemaError(result.errors) }\n }\n return { data: result.data }\n }\n\n const { validateEnv } = await import('./schema')\n const { formatZodError } = await import('./format')\n const result = validateEnv(def, rawEnv)\n if (!result.success) {\n return { error: formatZodError(result.errors) }\n }\n return { data: result.data }\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: AnyEnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = await validateAndFormat(envDefinition, rawEnv)\n\n if ('error' in result) {\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${result.error}`,\n )\n }\n\n lastValidated = result.data\n\n if (isStandardEnvDefinition(envDefinition)) {\n await generateStandardDts(envDefinition, resolvedConfig.root)\n }\n else {\n const { generateDts } = await import('./dts')\n await generateDts(envDefinition, resolvedConfig.root)\n }\n\n const count = Object.keys(lastValidated).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const leaks = detectServerLeak(\n envDefinition,\n lastValidated,\n bundle as Record<string, { type: string, code?: string }>,\n (keys) => {\n resolvedConfig.logger.warn(\n ` \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Leak detection skipped ${keys.length} server variable(s) with values shorter than 8 chars: ${keys.join(', ')}`,\n )\n },\n )\n\n if (leaks.length > 0) {\n const details = leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${details}\\n\\n These variables are marked as server-only and must never reach the browser.`,\n )\n }\n },\n\n configureServer(server) {\n const envDir = resolvedConfig.envDir || resolvedConfig.root\n server.watcher.add(path.join(envDir, '.env*'))\n\n let debounceTimer: ReturnType<typeof setTimeout>\n\n server.watcher.on('change', async (file) => {\n if (!path.basename(file).startsWith('.env'))\n return\n\n clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n try {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = await validateAndFormat(envDefinition, rawEnv)\n\n if ('error' in result) {\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${result.error}`,\n )\n return\n }\n\n lastValidated = result.data\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n const serverMod = server.moduleGraph.getModuleById('\\0virtual:env/server')\n if (clientMod)\n server.moduleGraph.invalidateModule(clientMod)\n if (serverMod)\n server.moduleGraph.invalidateModule(serverMod)\n if (clientMod || serverMod) {\n server.hot.send({ type: 'full-reload' })\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidated`,\n )\n }\n }\n catch (e) {\n resolvedConfig.logger.error(\n `\\n \\x1B[31m✗\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Failed to reload env files: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":"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"}
|
package/dist/schema.cjs
CHANGED
package/dist/schema.d.cts
CHANGED
package/dist/schema.d.mts
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/standard.ts
|
|
3
|
+
function defineStandardEnv(definition) {
|
|
4
|
+
if (definition.client) {
|
|
5
|
+
for (const key of Object.keys(definition.client)) if (!key.startsWith("VITE_")) throw new Error(`[vite-env] Client env var "${key}" must be prefixed with VITE_.\n Rename it to "VITE_${key}" or move it to "server" if it's secret.`);
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
...definition,
|
|
9
|
+
_standard: true
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function isStandardEnvDefinition(def) {
|
|
13
|
+
return def != null && typeof def === "object" && "_standard" in def && def._standard === true;
|
|
14
|
+
}
|
|
15
|
+
async function validateStandardEnv(def, rawEnv) {
|
|
16
|
+
const combinedShape = {
|
|
17
|
+
...def.server,
|
|
18
|
+
...def.client
|
|
19
|
+
};
|
|
20
|
+
const errors = [];
|
|
21
|
+
const data = {};
|
|
22
|
+
for (const [key, schema] of Object.entries(combinedShape)) {
|
|
23
|
+
const result = await schema["~standard"].validate(rawEnv[key]);
|
|
24
|
+
if ("issues" in result && result.issues) for (const issue of result.issues) errors.push({
|
|
25
|
+
message: issue.message,
|
|
26
|
+
path: [key, ...issue.path ?? []]
|
|
27
|
+
});
|
|
28
|
+
else data[key] = result.value;
|
|
29
|
+
}
|
|
30
|
+
if (errors.length > 0) return {
|
|
31
|
+
success: false,
|
|
32
|
+
data: null,
|
|
33
|
+
errors
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
data,
|
|
38
|
+
errors: []
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
exports.defineStandardEnv = defineStandardEnv;
|
|
43
|
+
exports.isStandardEnvDefinition = isStandardEnvDefinition;
|
|
44
|
+
exports.validateStandardEnv = validateStandardEnv;
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=standard.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standard.cjs","names":[],"sources":["../src/standard.ts"],"sourcesContent":["import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { StandardEnvDefinition, StandardValidationIssue, StandardValidationResult } from './types'\n\nexport function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(\n definition: T,\n): T & { readonly _standard: true } {\n if (definition.client) {\n for (const key of Object.keys(definition.client)) {\n if (!key.startsWith('VITE_')) {\n throw new Error(\n `[vite-env] Client env var \"${key}\" must be prefixed with VITE_.\\n`\n + ` Rename it to \"VITE_${key}\" or move it to \"server\" if it's secret.`,\n )\n }\n }\n }\n\n return { ...definition, _standard: true as const }\n}\n\nexport function isStandardEnvDefinition(\n def: unknown,\n): def is StandardEnvDefinition {\n return def != null && typeof def === 'object' && '_standard' in def && (def as any)._standard === true\n}\n\nexport async function validateStandardEnv(\n def: StandardEnvDefinition,\n rawEnv: Record<string, string>,\n): Promise<StandardValidationResult> {\n const combinedShape: Record<string, StandardSchemaV1> = {\n ...def.server,\n ...def.client,\n }\n\n const errors: StandardValidationIssue[] = []\n const data: Record<string, unknown> = {}\n\n for (const [key, schema] of Object.entries(combinedShape)) {\n const result = await schema['~standard'].validate(rawEnv[key])\n\n if ('issues' in result && result.issues) {\n for (const issue of result.issues) {\n errors.push({\n message: issue.message,\n path: [key, ...(issue.path ?? [])],\n })\n }\n }\n else {\n data[key] = (result as { value: unknown }).value\n }\n }\n\n if (errors.length > 0) {\n return { success: false, data: null, errors }\n }\n\n return { success: true, data, errors: [] as const }\n}\n"],"mappings":";;AAGA,SAAgB,kBACd,YACkC;AAClC,KAAI,WAAW;OACR,MAAM,OAAO,OAAO,KAAK,WAAW,OAAO,CAC9C,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;;AAKP,QAAO;EAAE,GAAG;EAAY,WAAW;EAAe;;AAGpD,SAAgB,wBACd,KAC8B;AAC9B,QAAO,OAAO,QAAQ,OAAO,QAAQ,YAAY,eAAe,OAAQ,IAAY,cAAc;;AAGpG,eAAsB,oBACpB,KACA,QACmC;CACnC,MAAM,gBAAkD;EACtD,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAED,MAAM,SAAoC,EAAE;CAC5C,MAAM,OAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,cAAc,EAAE;EACzD,MAAM,SAAS,MAAM,OAAO,aAAa,SAAS,OAAO,KAAK;AAE9D,MAAI,YAAY,UAAU,OAAO,OAC/B,MAAK,MAAM,SAAS,OAAO,OACzB,QAAO,KAAK;GACV,SAAS,MAAM;GACf,MAAM,CAAC,KAAK,GAAI,MAAM,QAAQ,EAAE,CAAE;GACnC,CAAC;MAIJ,MAAK,OAAQ,OAA8B;;AAI/C,KAAI,OAAO,SAAS,EAClB,QAAO;EAAE,SAAS;EAAO,MAAM;EAAM;EAAQ;AAG/C,QAAO;EAAE,SAAS;EAAM;EAAM,QAAQ,EAAE;EAAW"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { a as StandardEnvDefinition, s as StandardValidationResult } from "./types-1okexcwM.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/standard.d.ts
|
|
4
|
+
declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(definition: T): T & {
|
|
5
|
+
readonly _standard: true;
|
|
6
|
+
};
|
|
7
|
+
declare function isStandardEnvDefinition(def: unknown): def is StandardEnvDefinition;
|
|
8
|
+
declare function validateStandardEnv(def: StandardEnvDefinition, rawEnv: Record<string, string>): Promise<StandardValidationResult>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { defineStandardEnv, isStandardEnvDefinition, validateStandardEnv };
|
|
11
|
+
//# sourceMappingURL=standard.d.cts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { a as StandardEnvDefinition, s as StandardValidationResult } from "./types-DuWT_251.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/standard.d.ts
|
|
4
|
+
declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(definition: T): T & {
|
|
5
|
+
readonly _standard: true;
|
|
6
|
+
};
|
|
7
|
+
declare function isStandardEnvDefinition(def: unknown): def is StandardEnvDefinition;
|
|
8
|
+
declare function validateStandardEnv(def: StandardEnvDefinition, rawEnv: Record<string, string>): Promise<StandardValidationResult>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { defineStandardEnv, isStandardEnvDefinition, validateStandardEnv };
|
|
11
|
+
//# sourceMappingURL=standard.d.mts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/standard.ts
|
|
2
|
+
function defineStandardEnv(definition) {
|
|
3
|
+
if (definition.client) {
|
|
4
|
+
for (const key of Object.keys(definition.client)) if (!key.startsWith("VITE_")) throw new Error(`[vite-env] Client env var "${key}" must be prefixed with VITE_.\n Rename it to "VITE_${key}" or move it to "server" if it's secret.`);
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
...definition,
|
|
8
|
+
_standard: true
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function isStandardEnvDefinition(def) {
|
|
12
|
+
return def != null && typeof def === "object" && "_standard" in def && def._standard === true;
|
|
13
|
+
}
|
|
14
|
+
async function validateStandardEnv(def, rawEnv) {
|
|
15
|
+
const combinedShape = {
|
|
16
|
+
...def.server,
|
|
17
|
+
...def.client
|
|
18
|
+
};
|
|
19
|
+
const errors = [];
|
|
20
|
+
const data = {};
|
|
21
|
+
for (const [key, schema] of Object.entries(combinedShape)) {
|
|
22
|
+
const result = await schema["~standard"].validate(rawEnv[key]);
|
|
23
|
+
if ("issues" in result && result.issues) for (const issue of result.issues) errors.push({
|
|
24
|
+
message: issue.message,
|
|
25
|
+
path: [key, ...issue.path ?? []]
|
|
26
|
+
});
|
|
27
|
+
else data[key] = result.value;
|
|
28
|
+
}
|
|
29
|
+
if (errors.length > 0) return {
|
|
30
|
+
success: false,
|
|
31
|
+
data: null,
|
|
32
|
+
errors
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
data,
|
|
37
|
+
errors: []
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { defineStandardEnv, isStandardEnvDefinition, validateStandardEnv };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=standard.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standard.mjs","names":[],"sources":["../src/standard.ts"],"sourcesContent":["import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { StandardEnvDefinition, StandardValidationIssue, StandardValidationResult } from './types'\n\nexport function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(\n definition: T,\n): T & { readonly _standard: true } {\n if (definition.client) {\n for (const key of Object.keys(definition.client)) {\n if (!key.startsWith('VITE_')) {\n throw new Error(\n `[vite-env] Client env var \"${key}\" must be prefixed with VITE_.\\n`\n + ` Rename it to \"VITE_${key}\" or move it to \"server\" if it's secret.`,\n )\n }\n }\n }\n\n return { ...definition, _standard: true as const }\n}\n\nexport function isStandardEnvDefinition(\n def: unknown,\n): def is StandardEnvDefinition {\n return def != null && typeof def === 'object' && '_standard' in def && (def as any)._standard === true\n}\n\nexport async function validateStandardEnv(\n def: StandardEnvDefinition,\n rawEnv: Record<string, string>,\n): Promise<StandardValidationResult> {\n const combinedShape: Record<string, StandardSchemaV1> = {\n ...def.server,\n ...def.client,\n }\n\n const errors: StandardValidationIssue[] = []\n const data: Record<string, unknown> = {}\n\n for (const [key, schema] of Object.entries(combinedShape)) {\n const result = await schema['~standard'].validate(rawEnv[key])\n\n if ('issues' in result && result.issues) {\n for (const issue of result.issues) {\n errors.push({\n message: issue.message,\n path: [key, ...(issue.path ?? [])],\n })\n }\n }\n else {\n data[key] = (result as { value: unknown }).value\n }\n }\n\n if (errors.length > 0) {\n return { success: false, data: null, errors }\n }\n\n return { success: true, data, errors: [] as const }\n}\n"],"mappings":";AAGA,SAAgB,kBACd,YACkC;AAClC,KAAI,WAAW;OACR,MAAM,OAAO,OAAO,KAAK,WAAW,OAAO,CAC9C,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;;AAKP,QAAO;EAAE,GAAG;EAAY,WAAW;EAAe;;AAGpD,SAAgB,wBACd,KAC8B;AAC9B,QAAO,OAAO,QAAQ,OAAO,QAAQ,YAAY,eAAe,OAAQ,IAAY,cAAc;;AAGpG,eAAsB,oBACpB,KACA,QACmC;CACnC,MAAM,gBAAkD;EACtD,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAED,MAAM,SAAoC,EAAE;CAC5C,MAAM,OAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,cAAc,EAAE;EACzD,MAAM,SAAS,MAAM,OAAO,aAAa,SAAS,OAAO,KAAK;AAE9D,MAAI,YAAY,UAAU,OAAO,OAC/B,MAAK,MAAM,SAAS,OAAO,OACzB,QAAO,KAAK;GACV,SAAS,MAAM;GACf,MAAM,CAAC,KAAK,GAAI,MAAM,QAAQ,EAAE,CAAE;GACnC,CAAC;MAIJ,MAAK,OAAQ,OAA8B;;AAI/C,KAAI,OAAO,SAAS,EAClB,QAAO;EAAE,SAAS;EAAO,MAAM;EAAM;EAAQ;AAG/C,QAAO;EAAE,SAAS;EAAM;EAAM,QAAQ,EAAE;EAAW"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
interface EnvDefinition {
|
|
6
|
+
server?: z.ZodRawShape;
|
|
7
|
+
client?: z.ZodRawShape;
|
|
8
|
+
}
|
|
9
|
+
interface StandardEnvDefinition {
|
|
10
|
+
server?: Record<string, StandardSchemaV1>;
|
|
11
|
+
client?: Record<string, StandardSchemaV1>;
|
|
12
|
+
/** @internal */
|
|
13
|
+
readonly _standard: true;
|
|
14
|
+
}
|
|
15
|
+
type AnyEnvDefinition = EnvDefinition | StandardEnvDefinition;
|
|
16
|
+
type ValidationResult = {
|
|
17
|
+
success: true;
|
|
18
|
+
data: Record<string, unknown>;
|
|
19
|
+
errors: [];
|
|
20
|
+
} | {
|
|
21
|
+
success: false;
|
|
22
|
+
data: null;
|
|
23
|
+
errors: z.core.$ZodIssue[];
|
|
24
|
+
};
|
|
25
|
+
interface StandardValidationIssue {
|
|
26
|
+
message: string;
|
|
27
|
+
path: ReadonlyArray<PropertyKey | StandardSchemaV1.PathSegment>;
|
|
28
|
+
}
|
|
29
|
+
type StandardValidationResult = {
|
|
30
|
+
success: true;
|
|
31
|
+
data: Record<string, unknown>;
|
|
32
|
+
errors: [];
|
|
33
|
+
} | {
|
|
34
|
+
success: false;
|
|
35
|
+
data: null;
|
|
36
|
+
errors: StandardValidationIssue[];
|
|
37
|
+
};
|
|
38
|
+
type OrEmptyShape<T> = T extends z.ZodRawShape ? T : Record<string, never>;
|
|
39
|
+
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['client']>>>;
|
|
40
|
+
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['server']> & OrEmptyShape<T['client']>>>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { StandardEnvDefinition as a, ValidationResult as c, InferServerEnv as i, EnvDefinition as n, StandardValidationIssue as o, InferClientEnv as r, StandardValidationResult as s, AnyEnvDefinition as t };
|
|
43
|
+
//# sourceMappingURL=types-1okexcwM.d.cts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
interface EnvDefinition {
|
|
6
|
+
server?: z.ZodRawShape;
|
|
7
|
+
client?: z.ZodRawShape;
|
|
8
|
+
}
|
|
9
|
+
interface StandardEnvDefinition {
|
|
10
|
+
server?: Record<string, StandardSchemaV1>;
|
|
11
|
+
client?: Record<string, StandardSchemaV1>;
|
|
12
|
+
/** @internal */
|
|
13
|
+
readonly _standard: true;
|
|
14
|
+
}
|
|
15
|
+
type AnyEnvDefinition = EnvDefinition | StandardEnvDefinition;
|
|
16
|
+
type ValidationResult = {
|
|
17
|
+
success: true;
|
|
18
|
+
data: Record<string, unknown>;
|
|
19
|
+
errors: [];
|
|
20
|
+
} | {
|
|
21
|
+
success: false;
|
|
22
|
+
data: null;
|
|
23
|
+
errors: z.core.$ZodIssue[];
|
|
24
|
+
};
|
|
25
|
+
interface StandardValidationIssue {
|
|
26
|
+
message: string;
|
|
27
|
+
path: ReadonlyArray<PropertyKey | StandardSchemaV1.PathSegment>;
|
|
28
|
+
}
|
|
29
|
+
type StandardValidationResult = {
|
|
30
|
+
success: true;
|
|
31
|
+
data: Record<string, unknown>;
|
|
32
|
+
errors: [];
|
|
33
|
+
} | {
|
|
34
|
+
success: false;
|
|
35
|
+
data: null;
|
|
36
|
+
errors: StandardValidationIssue[];
|
|
37
|
+
};
|
|
38
|
+
type OrEmptyShape<T> = T extends z.ZodRawShape ? T : Record<string, never>;
|
|
39
|
+
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['client']>>>;
|
|
40
|
+
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['server']> & OrEmptyShape<T['client']>>>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { StandardEnvDefinition as a, ValidationResult as c, InferServerEnv as i, EnvDefinition as n, StandardValidationIssue as o, InferClientEnv as r, StandardValidationResult as s, AnyEnvDefinition as t };
|
|
43
|
+
//# sourceMappingURL=types-DuWT_251.d.mts.map
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/vitejs/vite-plugin-registry/refs/heads/main/data/schema/extended-package-json.schema.json",
|
|
3
3
|
"name": "@vite-env/core",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.0",
|
|
6
6
|
"description": "The env.ts layer for Vite — define once, validate everywhere, import with types",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"homepage": "https://github.com/pyyupsk/vite-env#readme",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"zod",
|
|
21
21
|
"validation",
|
|
22
22
|
"rolldown",
|
|
23
|
-
"dotenv"
|
|
23
|
+
"dotenv",
|
|
24
|
+
"standard-schema"
|
|
24
25
|
],
|
|
25
26
|
"exports": {
|
|
26
27
|
".": {
|
|
@@ -93,6 +94,16 @@
|
|
|
93
94
|
"default": "./dist/schema.cjs"
|
|
94
95
|
}
|
|
95
96
|
},
|
|
97
|
+
"./standard": {
|
|
98
|
+
"import": {
|
|
99
|
+
"types": "./dist/standard.d.mts",
|
|
100
|
+
"default": "./dist/standard.mjs"
|
|
101
|
+
},
|
|
102
|
+
"require": {
|
|
103
|
+
"types": "./dist/standard.d.cts",
|
|
104
|
+
"default": "./dist/standard.cjs"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
96
107
|
"./package.json": "./package.json"
|
|
97
108
|
},
|
|
98
109
|
"main": "./dist/index.cjs",
|
|
@@ -109,7 +120,13 @@
|
|
|
109
120
|
"vite": ">=8.0.0",
|
|
110
121
|
"zod": "^4.0.0"
|
|
111
122
|
},
|
|
123
|
+
"peerDependenciesMeta": {
|
|
124
|
+
"zod": {
|
|
125
|
+
"optional": true
|
|
126
|
+
}
|
|
127
|
+
},
|
|
112
128
|
"dependencies": {
|
|
129
|
+
"@standard-schema/spec": "^1.1.0",
|
|
113
130
|
"jiti": "^2.6.1"
|
|
114
131
|
},
|
|
115
132
|
"devDependencies": {
|
package/dist/dts-DF71HNdJ.cjs
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
//#endregion
|
|
23
|
-
let zod = require("zod");
|
|
24
|
-
let node_path = require("node:path");
|
|
25
|
-
node_path = __toESM(node_path);
|
|
26
|
-
let node_fs_promises = require("node:fs/promises");
|
|
27
|
-
node_fs_promises = __toESM(node_fs_promises);
|
|
28
|
-
//#region src/dts.ts
|
|
29
|
-
/**
|
|
30
|
-
* Writes vite-env.d.ts to project root.
|
|
31
|
-
* Declares virtual:env/client and virtual:env/server module types.
|
|
32
|
-
* Users never need to manually augment ImportMetaEnv again.
|
|
33
|
-
*/
|
|
34
|
-
async function generateDts(def, root) {
|
|
35
|
-
const clientKeys = { ...def.client };
|
|
36
|
-
const serverKeys = {
|
|
37
|
-
...def.server,
|
|
38
|
-
...def.client
|
|
39
|
-
};
|
|
40
|
-
const dts = `// Auto-generated by @vite-env/core
|
|
41
|
-
// Do not edit manually — re-generated on every dev server start and build
|
|
42
|
-
|
|
43
|
-
declare module 'virtual:env/client' {
|
|
44
|
-
const env: {
|
|
45
|
-
${zodShapeToTsFields(clientKeys)}
|
|
46
|
-
}
|
|
47
|
-
export { env }
|
|
48
|
-
export default env
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
declare module 'virtual:env/server' {
|
|
52
|
-
const env: {
|
|
53
|
-
${zodShapeToTsFields(serverKeys)}
|
|
54
|
-
}
|
|
55
|
-
export { env }
|
|
56
|
-
export default env
|
|
57
|
-
}
|
|
58
|
-
`;
|
|
59
|
-
const filePath = node_path.default.join(root, "vite-env.d.ts");
|
|
60
|
-
try {
|
|
61
|
-
await node_fs_promises.default.writeFile(filePath, dts, "utf-8");
|
|
62
|
-
} catch (e) {
|
|
63
|
-
throw new Error(`[vite-env] Failed to write vite-env.d.ts to ${root}. Check file permissions.`, { cause: e });
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function zodShapeToTsFields(shape) {
|
|
67
|
-
return Object.entries(shape).map(([key, schema]) => {
|
|
68
|
-
const s = schema;
|
|
69
|
-
const tsType = zodToTs(s);
|
|
70
|
-
return ` readonly ${key}${isOptional(s) ? "?" : ""}: ${tsType}`;
|
|
71
|
-
}).join("\n");
|
|
72
|
-
}
|
|
73
|
-
function zodToTs(schema) {
|
|
74
|
-
if (schema instanceof zod.z.ZodOptional) return zodToTs(schema.unwrap());
|
|
75
|
-
if (schema instanceof zod.z.ZodDefault) return zodToTs(schema.def.innerType);
|
|
76
|
-
if (schema instanceof zod.z.ZodString) return "string";
|
|
77
|
-
if (schema instanceof zod.z.ZodNumber) return "number";
|
|
78
|
-
if (schema instanceof zod.z.ZodBoolean) return "boolean";
|
|
79
|
-
if (schema instanceof zod.z.ZodEnum) return schema.options.map((o) => `'${o}'`).join(" | ");
|
|
80
|
-
if (schema instanceof zod.z.ZodPipe) return zodToTs(schema.def.out);
|
|
81
|
-
return "string";
|
|
82
|
-
}
|
|
83
|
-
function isOptional(schema) {
|
|
84
|
-
return schema instanceof zod.z.ZodOptional;
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
|
-
Object.defineProperty(exports, "__toESM", {
|
|
88
|
-
enumerable: true,
|
|
89
|
-
get: function() {
|
|
90
|
-
return __toESM;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
Object.defineProperty(exports, "generateDts", {
|
|
94
|
-
enumerable: true,
|
|
95
|
-
get: function() {
|
|
96
|
-
return generateDts;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
//# sourceMappingURL=dts-DF71HNdJ.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dts-DF71HNdJ.cjs","names":["path","fs","z"],"sources":["../src/dts.ts"],"sourcesContent":["// @env node\nimport type { EnvDefinition } from './types'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { z } from 'zod'\n\n/**\n * Writes vite-env.d.ts to project root.\n * Declares virtual:env/client and virtual:env/server module types.\n * Users never need to manually augment ImportMetaEnv again.\n */\nexport async function generateDts(\n def: EnvDefinition,\n root: string,\n): Promise<void> {\n const clientKeys = {\n ...def.client,\n }\n const serverKeys = {\n ...def.server,\n ...def.client,\n }\n\n const clientFields = zodShapeToTsFields(clientKeys)\n const serverFields = zodShapeToTsFields(serverKeys)\n\n const dts = `// Auto-generated by @vite-env/core\n// Do not edit manually — re-generated on every dev server start and build\n\ndeclare module 'virtual:env/client' {\n const env: {\n${clientFields}\n }\n export { env }\n export default env\n}\n\ndeclare module 'virtual:env/server' {\n const env: {\n${serverFields}\n }\n export { env }\n export default env\n}\n`\n\n const filePath = path.join(root, 'vite-env.d.ts')\n try {\n await fs.writeFile(filePath, dts, 'utf-8')\n }\n catch (e) {\n throw new Error(\n `[vite-env] Failed to write vite-env.d.ts to ${root}. Check file permissions.`,\n { cause: e },\n )\n }\n}\n\nfunction zodShapeToTsFields(shape: z.ZodRawShape): string {\n return Object.entries(shape)\n .map(([key, schema]) => {\n // Zod v4: ZodRawShape values are $ZodType, cast to ZodTypeAny for instanceof checks\n const s = schema as z.ZodTypeAny\n const tsType = zodToTs(s)\n const optional = isOptional(s)\n return ` readonly ${key}${optional ? '?' : ''}: ${tsType}`\n })\n .join('\\n')\n}\n\nfunction zodToTs(schema: z.ZodTypeAny): string {\n if (schema instanceof z.ZodOptional)\n return zodToTs(schema.unwrap() as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodDefault)\n return zodToTs(schema.def.innerType as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodString)\n return 'string'\n if (schema instanceof z.ZodNumber)\n return 'number'\n if (schema instanceof z.ZodBoolean)\n return 'boolean'\n if (schema instanceof z.ZodEnum)\n return (schema.options as string[]).map(o => `'${o}'`).join(' | ')\n if (schema instanceof z.ZodPipe)\n return zodToTs(schema.def.out as unknown as z.ZodTypeAny)\n return 'string'\n}\n\nfunction isOptional(schema: z.ZodTypeAny): boolean {\n return schema instanceof z.ZodOptional\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,eAAsB,YACpB,KACA,MACe;CACf,MAAM,aAAa,EACjB,GAAG,IAAI,QACR;CACD,MAAM,aAAa;EACjB,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAKD,MAAM,MAAM;;;;;EAHS,mBAAmB,WAAW,CAQtC;;;;;;;;EAPQ,mBAAmB,WAAW,CAetC;;;;;;CAOb,MAAM,WAAWA,UAAAA,QAAK,KAAK,MAAM,gBAAgB;AACjD,KAAI;AACF,QAAMC,iBAAAA,QAAG,UAAU,UAAU,KAAK,QAAQ;UAErC,GAAG;AACR,QAAM,IAAI,MACR,+CAA+C,KAAK,4BACpD,EAAE,OAAO,GAAG,CACb;;;AAIL,SAAS,mBAAmB,OAA8B;AACxD,QAAO,OAAO,QAAQ,MAAM,CACzB,KAAK,CAAC,KAAK,YAAY;EAEtB,MAAM,IAAI;EACV,MAAM,SAAS,QAAQ,EAAE;AAEzB,SAAO,gBAAgB,MADN,WAAW,EAAE,GACU,MAAM,GAAG,IAAI;GACrD,CACD,KAAK,KAAK;;AAGf,SAAS,QAAQ,QAA8B;AAC7C,KAAI,kBAAkBC,IAAAA,EAAE,YACtB,QAAO,QAAQ,OAAO,QAAQ,CAA4B;AAC5D,KAAI,kBAAkBA,IAAAA,EAAE,WACtB,QAAO,QAAQ,OAAO,IAAI,UAAqC;AACjE,KAAI,kBAAkBA,IAAAA,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,WACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,QACtB,QAAQ,OAAO,QAAqB,KAAI,MAAK,IAAI,EAAE,GAAG,CAAC,KAAK,MAAM;AACpE,KAAI,kBAAkBA,IAAAA,EAAE,QACtB,QAAO,QAAQ,OAAO,IAAI,IAA+B;AAC3D,QAAO;;AAGT,SAAS,WAAW,QAA+B;AACjD,QAAO,kBAAkBA,IAAAA,EAAE"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
//#region src/types.d.ts
|
|
4
|
-
interface EnvDefinition {
|
|
5
|
-
server?: z.ZodRawShape;
|
|
6
|
-
client?: z.ZodRawShape;
|
|
7
|
-
}
|
|
8
|
-
type ValidationResult = {
|
|
9
|
-
success: true;
|
|
10
|
-
data: Record<string, unknown>;
|
|
11
|
-
errors: [];
|
|
12
|
-
} | {
|
|
13
|
-
success: false;
|
|
14
|
-
data: null;
|
|
15
|
-
errors: z.core.$ZodIssue[];
|
|
16
|
-
};
|
|
17
|
-
type OrEmptyShape<T> = T extends z.ZodRawShape ? T : Record<string, never>;
|
|
18
|
-
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['client']>>>;
|
|
19
|
-
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['server']> & OrEmptyShape<T['client']>>>;
|
|
20
|
-
//#endregion
|
|
21
|
-
export { ValidationResult as i, InferClientEnv as n, InferServerEnv as r, EnvDefinition as t };
|
|
22
|
-
//# sourceMappingURL=types-CluiDKAQ.d.mts.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
//#region src/types.d.ts
|
|
4
|
-
interface EnvDefinition {
|
|
5
|
-
server?: z.ZodRawShape;
|
|
6
|
-
client?: z.ZodRawShape;
|
|
7
|
-
}
|
|
8
|
-
type ValidationResult = {
|
|
9
|
-
success: true;
|
|
10
|
-
data: Record<string, unknown>;
|
|
11
|
-
errors: [];
|
|
12
|
-
} | {
|
|
13
|
-
success: false;
|
|
14
|
-
data: null;
|
|
15
|
-
errors: z.core.$ZodIssue[];
|
|
16
|
-
};
|
|
17
|
-
type OrEmptyShape<T> = T extends z.ZodRawShape ? T : Record<string, never>;
|
|
18
|
-
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['client']>>>;
|
|
19
|
-
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<OrEmptyShape<T['server']> & OrEmptyShape<T['client']>>>;
|
|
20
|
-
//#endregion
|
|
21
|
-
export { ValidationResult as i, InferClientEnv as n, InferServerEnv as r, EnvDefinition as t };
|
|
22
|
-
//# sourceMappingURL=types-DqTMuWwc.d.cts.map
|