@vite-env/core 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +33 -17
  2. package/dist/chunk-CKQMccvm.cjs +28 -0
  3. package/dist/config.cjs +1 -1
  4. package/dist/config.cjs.map +1 -1
  5. package/dist/config.d.cts +1 -1
  6. package/dist/config.d.mts +1 -1
  7. package/dist/config.mjs.map +1 -1
  8. package/dist/dts.cjs +102 -3
  9. package/dist/dts.cjs.map +1 -0
  10. package/dist/dts.d.cts +1 -1
  11. package/dist/dts.d.mts +1 -1
  12. package/dist/dts.mjs +1 -1
  13. package/dist/dts.mjs.map +1 -1
  14. package/dist/format.cjs.map +1 -1
  15. package/dist/format.d.cts +2 -2
  16. package/dist/format.d.mts +2 -2
  17. package/dist/format.mjs.map +1 -1
  18. package/dist/index.d.cts +1 -1
  19. package/dist/index.d.mts +1 -1
  20. package/dist/leak.cjs.map +1 -1
  21. package/dist/leak.d.cts +1 -1
  22. package/dist/leak.d.mts +1 -1
  23. package/dist/leak.mjs.map +1 -1
  24. package/dist/load.cjs +50 -0
  25. package/dist/load.cjs.map +1 -0
  26. package/dist/load.d.cts +29 -0
  27. package/dist/load.d.mts +29 -0
  28. package/dist/load.mjs +46 -0
  29. package/dist/load.mjs.map +1 -0
  30. package/dist/plugin.cjs +5 -4
  31. package/dist/plugin.cjs.map +1 -1
  32. package/dist/plugin.d.cts +1 -1
  33. package/dist/plugin.d.mts +1 -1
  34. package/dist/plugin.mjs.map +1 -1
  35. package/dist/presets/index.cjs +1 -1
  36. package/dist/presets/index.cjs.map +1 -1
  37. package/dist/presets/index.mjs.map +1 -1
  38. package/dist/schema.cjs +1 -1
  39. package/dist/schema.cjs.map +1 -1
  40. package/dist/schema.d.cts +2 -2
  41. package/dist/schema.d.mts +2 -2
  42. package/dist/schema.mjs.map +1 -1
  43. package/dist/standard.cjs.map +1 -1
  44. package/dist/standard.d.cts +2 -2
  45. package/dist/standard.d.mts +2 -2
  46. package/dist/standard.mjs.map +1 -1
  47. package/dist/{types-B61nsO8q.d.cts → types-Ctg8aeXQ.d.mts} +4 -4
  48. package/dist/{types-KniR_Oqf.d.mts → types-DudMh278.d.cts} +4 -4
  49. package/package.json +43 -33
  50. package/dist/dts-BX0Cnqo-.cjs +0 -139
  51. package/dist/dts-BX0Cnqo-.cjs.map +0 -1
@@ -0,0 +1,29 @@
1
+ import { o as StandardEnvDefinition, r as EnvPreset } from "./types-Ctg8aeXQ.mjs";
2
+ import { z } from "zod";
3
+
4
+ //#region src/load.d.ts
5
+ type LoadEnvOptions = {
6
+ mode?: string;
7
+ envDir?: string;
8
+ };
9
+ type ZodShape = z.ZodRawShape;
10
+ type KnownKeys<T> = keyof { [K in keyof T as string extends K ? never : K]: T[K] };
11
+ type StripIndex<T extends ZodShape> = Pick<T, KnownKeys<T>>;
12
+ type InferShape<TServer extends ZodShape, TClient extends ZodShape> = {
13
+ server: z.infer<z.ZodObject<StripIndex<TServer> & StripIndex<TClient>>>;
14
+ client: z.infer<z.ZodObject<StripIndex<TClient>>>;
15
+ all: z.infer<z.ZodObject<StripIndex<TServer> & StripIndex<TClient>>>;
16
+ };
17
+ declare function loadEnv<TServer extends ZodShape = Record<never, never>, TClient extends ZodShape = Record<never, never>>(config: {
18
+ server?: TServer;
19
+ client?: TClient;
20
+ presets?: EnvPreset[];
21
+ }, options?: LoadEnvOptions): Promise<InferShape<TServer, TClient>>;
22
+ declare function loadEnv(config: StandardEnvDefinition, options?: LoadEnvOptions): Promise<{
23
+ server: Record<string, unknown>;
24
+ client: Record<string, unknown>;
25
+ all: Record<string, unknown>;
26
+ }>;
27
+ //#endregion
28
+ export { LoadEnvOptions, loadEnv };
29
+ //# sourceMappingURL=load.d.mts.map
package/dist/load.mjs ADDED
@@ -0,0 +1,46 @@
1
+ import { validateEnv } from "./schema.mjs";
2
+ import { isStandardEnvDefinition, validateStandardEnv } from "./standard.mjs";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+ import { loadEnv as loadEnv$1 } from "vite";
6
+ //#region src/load.ts
7
+ async function loadEnv(config, options = {}) {
8
+ const rawEnv = {
9
+ ...loadEnv$1(options.mode ?? process.env["NODE_ENV"] ?? "development", options.envDir ? path.resolve(options.envDir) : process.cwd(), ""),
10
+ ...filterStrings(process.env)
11
+ };
12
+ if (isStandardEnvDefinition(config)) {
13
+ const result = await validateStandardEnv(config, rawEnv);
14
+ if (!result.success) throwValidationError(result.errors.map((e) => e.message));
15
+ const server = Object.freeze(result.data);
16
+ const clientKeys = new Set(Object.keys(config.client ?? {}));
17
+ return {
18
+ server,
19
+ client: Object.freeze(filterByKeys(server, clientKeys)),
20
+ all: server
21
+ };
22
+ }
23
+ const result = validateEnv(config, rawEnv);
24
+ if (!result.success) throwValidationError(result.errors.map((e) => e.message));
25
+ const server = Object.freeze(result.data);
26
+ const clientKeys = new Set(Object.keys(config.client ?? {}));
27
+ return {
28
+ server,
29
+ client: Object.freeze(filterByKeys(server, clientKeys)),
30
+ all: server
31
+ };
32
+ }
33
+ function filterByKeys(data, keys) {
34
+ return Object.fromEntries(Object.entries(data).filter(([k]) => keys.has(k)));
35
+ }
36
+ function filterStrings(env) {
37
+ return Object.fromEntries(Object.entries(env).filter((e) => typeof e[1] === "string"));
38
+ }
39
+ function throwValidationError(messages) {
40
+ const lines = messages.map((m) => " - " + m).join("\n");
41
+ throw new Error("[vite-env] Validation failed:\n" + lines);
42
+ }
43
+ //#endregion
44
+ export { loadEnv };
45
+
46
+ //# sourceMappingURL=load.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.mjs","names":["viteLoadEnv"],"sources":["../src/load.ts"],"sourcesContent":["import type { EnvPreset, StandardEnvDefinition } from \"./types\";\nimport type { z } from \"zod\";\nimport process from \"node:process\";\nimport path from \"node:path\";\nimport { loadEnv as viteLoadEnv } from \"vite\";\nimport { isStandardEnvDefinition, validateStandardEnv } from \"./standard\";\nimport { validateEnv } from \"./schema\";\n\nexport type LoadEnvOptions = {\n mode?: string;\n envDir?: string;\n};\n\ntype ZodShape = z.ZodRawShape;\n\ntype KnownKeys<T> = keyof { [K in keyof T as string extends K ? never : K]: T[K] };\ntype StripIndex<T extends ZodShape> = Pick<T, KnownKeys<T>>;\n\ntype InferShape<TServer extends ZodShape, TClient extends ZodShape> = {\n server: z.infer<z.ZodObject<StripIndex<TServer> & StripIndex<TClient>>>;\n client: z.infer<z.ZodObject<StripIndex<TClient>>>;\n all: z.infer<z.ZodObject<StripIndex<TServer> & StripIndex<TClient>>>;\n};\n\nexport async function loadEnv<\n TServer extends ZodShape = Record<never, never>,\n TClient extends ZodShape = Record<never, never>,\n>(\n config: { server?: TServer; client?: TClient; presets?: EnvPreset[] },\n options?: LoadEnvOptions,\n): Promise<InferShape<TServer, TClient>>;\n\nexport async function loadEnv(\n config: StandardEnvDefinition,\n options?: LoadEnvOptions,\n): Promise<{\n server: Record<string, unknown>;\n client: Record<string, unknown>;\n all: Record<string, unknown>;\n}>;\n\nexport async function loadEnv(\n config: { server?: ZodShape; client?: ZodShape; presets?: EnvPreset[] } | StandardEnvDefinition,\n options: LoadEnvOptions = {},\n): Promise<{\n server: Record<string, unknown>;\n client: Record<string, unknown>;\n all: Record<string, unknown>;\n}> {\n const mode = options.mode ?? process.env[\"NODE_ENV\"] ?? \"development\";\n const envDir = options.envDir ? path.resolve(options.envDir) : process.cwd();\n\n const fileEnv = viteLoadEnv(mode, envDir, \"\");\n const rawEnv: Record<string, string> = {\n ...fileEnv,\n ...filterStrings(process.env),\n };\n\n if (isStandardEnvDefinition(config)) {\n const result = await validateStandardEnv(config, rawEnv);\n if (!result.success) throwValidationError(result.errors.map((e) => e.message));\n\n const server = Object.freeze(result.data);\n const clientKeys = new Set(Object.keys(config.client ?? {}));\n const client = Object.freeze(filterByKeys(server, clientKeys));\n\n return { server, client, all: server };\n }\n\n const result = validateEnv(config, rawEnv);\n if (!result.success) throwValidationError(result.errors.map((e) => e.message));\n\n const server = Object.freeze(result.data);\n const clientKeys = new Set(Object.keys(config.client ?? {}));\n const client = Object.freeze(filterByKeys(server, clientKeys));\n\n return { server, client, all: server };\n}\n\nfunction filterByKeys(data: Record<string, unknown>, keys: Set<string>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(data).filter(([k]) => keys.has(k)));\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter((e): e is [string, string] => typeof e[1] === \"string\"),\n );\n}\n\nfunction throwValidationError(messages: string[]): never {\n const lines = messages.map((m) => \" - \" + m).join(\"\\n\");\n throw new Error(\"[vite-env] Validation failed:\\n\" + lines);\n}\n"],"mappings":";;;;;;AAyCA,eAAsB,QACpB,QACA,UAA0B,EAAE,EAK3B;CAKD,MAAM,SAAiC;EACrC,GAFcA,UAHH,QAAQ,QAAQ,QAAQ,IAAI,eAAe,eACzC,QAAQ,SAAS,KAAK,QAAQ,QAAQ,OAAO,GAAG,QAAQ,KAAK,EAElC,GAE9B;EACV,GAAG,cAAc,QAAQ,IAAI;EAC9B;AAED,KAAI,wBAAwB,OAAO,EAAE;EACnC,MAAM,SAAS,MAAM,oBAAoB,QAAQ,OAAO;AACxD,MAAI,CAAC,OAAO,QAAS,sBAAqB,OAAO,OAAO,KAAK,MAAM,EAAE,QAAQ,CAAC;EAE9E,MAAM,SAAS,OAAO,OAAO,OAAO,KAAK;EACzC,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,CAAC;AAG5D,SAAO;GAAE;GAAQ,QAFF,OAAO,OAAO,aAAa,QAAQ,WAAW,CAEtC;GAAE,KAAK;GAAQ;;CAGxC,MAAM,SAAS,YAAY,QAAQ,OAAO;AAC1C,KAAI,CAAC,OAAO,QAAS,sBAAqB,OAAO,OAAO,KAAK,MAAM,EAAE,QAAQ,CAAC;CAE9E,MAAM,SAAS,OAAO,OAAO,OAAO,KAAK;CACzC,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,CAAC;AAG5D,QAAO;EAAE;EAAQ,QAFF,OAAO,OAAO,aAAa,QAAQ,WAAW,CAEtC;EAAE,KAAK;EAAQ;;AAGxC,SAAS,aAAa,MAA+B,MAA4C;AAC/F,QAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,QAAQ,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC;;AAG9E,SAAS,cAAc,KAAgD;AACrE,QAAO,OAAO,YACZ,OAAO,QAAQ,IAAI,CAAC,QAAQ,MAA6B,OAAO,EAAE,OAAO,SAAS,CACnF;;AAGH,SAAS,qBAAqB,UAA2B;CACvD,MAAM,QAAQ,SAAS,KAAK,MAAM,SAAS,EAAE,CAAC,KAAK,KAAK;AACxD,OAAM,IAAI,MAAM,oCAAoC,MAAM"}
package/dist/plugin.cjs CHANGED
@@ -1,14 +1,15 @@
1
- const require_dts = require("./dts-BX0Cnqo-.cjs");
1
+ const require_chunk = require("./chunk-CKQMccvm.cjs");
2
2
  const require_standard = require("./standard.cjs");
3
3
  const require_config = require("./config.cjs");
4
+ const require_dts = require("./dts.cjs");
4
5
  const require_format = require("./format.cjs");
5
6
  const require_leak = require("./leak.cjs");
6
7
  let node_path = require("node:path");
7
- node_path = require_dts.__toESM(node_path, 1);
8
+ node_path = require_chunk.__toESM(node_path, 1);
8
9
  let node_process = require("node:process");
9
- node_process = require_dts.__toESM(node_process, 1);
10
+ node_process = require_chunk.__toESM(node_process, 1);
10
11
  let node_fs_promises = require("node:fs/promises");
11
- node_fs_promises = require_dts.__toESM(node_fs_promises, 1);
12
+ node_fs_promises = require_chunk.__toESM(node_fs_promises, 1);
12
13
  let vite = require("vite");
13
14
  //#region src/guard.ts
14
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs","names":["formatGuardLogEntry","path","fs","process","isStandardEnvDefinition","validateStandardEnv","formatStandardSchemaError","path","loadEnvConfig","generateStandardDts","formatHardError","formatGuardWarning","detectServerLeak"],"sources":["../src/guard.ts","../src/log.ts","../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["export type GuardMode = 'error' | 'stub' | 'warn'\n\nexport type GuardResult\n = | { allowed: true }\n | { allowed: false, mode: GuardMode, envName: string, importer: string | undefined }\n\nexport type GuardFail = Extract<GuardResult, { allowed: false }>\n\n/**\n * Determines whether the given Vite environment is allowed to import virtual:env/server.\n * Returns a GuardResult discriminated union — allowed or fail with context.\n * When this.environment is undefined (should not occur with Vite ≥ 8), callers default\n * envName to 'client' — failing closed (restrictive) is safer than failing open.\n */\nexport function checkServerModuleAccess(\n envName: string,\n serverEnvironments: string[],\n mode: GuardMode,\n importer: string | undefined,\n): GuardResult {\n if (serverEnvironments.includes(envName))\n return { allowed: true }\n return { allowed: false, mode, envName, importer }\n}\n\n/**\n * Generates the stub virtual module returned when onClientAccessOfServerModule is 'stub'.\n * The stub throws at runtime if executed — its message reflects that this import was\n * expected to be unreachable and the assumption was wrong.\n */\nexport function buildServerStubModule(envName: string): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — server-only module stub\nthrow new Error(\n '[vite-env] virtual:env/server was imported in the \"${envName}\" environment. ' +\n 'This module is server-only and was replaced with a stub. ' +\n 'To allow this environment: add it to serverEnvironments. ' +\n 'To suppress this stub: ensure this import never executes in the \"${envName}\" environment.'\n);`,\n }\n}\n","// @env node\nimport type { GuardFail } from './guard'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatGuardLogEntry } from './format'\n\nconst LOG_HEADER = `# vite-env warnings — generated by @vite-env/core\n# These warnings will become hard errors in 1.0.0.\n# To enforce immediately: ViteEnv({ onClientAccessOfServerModule: 'error' })\n# To acknowledge and suppress: ViteEnv({ onClientAccessOfServerModule: 'stub' })\n# To allow specific environments: ViteEnv({ serverEnvironments: ['ssr', 'workerd'] })`\n\n/**\n * Writes accumulated GuardFail entries to vite-env-warnings.log in the project root.\n * Overwrites on each build — stale entries from previous builds must not persist.\n * Called only in 'warn' mode from buildEnd, after verifying the build succeeded.\n */\nexport async function writeWarningsLog(fails: GuardFail[], root: string): Promise<void> {\n const seen = new Set<string>()\n const unique = fails.filter((fail) => {\n const key = `${fail.envName}::${fail.importer ?? ''}`\n if (seen.has(key))\n return false\n seen.add(key)\n return true\n })\n const timestamp = new Date().toISOString()\n const entries = unique.map(fail => formatGuardLogEntry(fail, timestamp)).join('\\n\\n')\n const content = `${LOG_HEADER}\\n\\n${entries}\\n`\n const filePath = path.join(root, 'vite-env-warnings.log')\n try {\n await fs.writeFile(filePath, content, 'utf-8')\n }\n catch (e) {\n throw new Error(\n `[vite-env] Failed to write vite-env-warnings.log to ${root}. Check file permissions.`,\n { cause: e },\n )\n }\n}\n","// @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, Rollup } from 'vite'\nimport type { GuardFail } from './guard'\nimport type { AnyEnvDefinition } from './types'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { loadEnvConfig } from './config'\nimport { generateStandardDts } from './dts'\nimport { formatGuardWarning, formatHardError, formatStandardSchemaError } from './format'\nimport { buildServerStubModule, checkServerModuleAccess } from './guard'\nimport { detectServerLeak } from './leak'\nimport { writeWarningsLog } from './log'\nimport { loadEnvSources } from './sources'\nimport { isStandardEnvDefinition, validateStandardEnv } from './standard'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport type ViteEnvOptions = {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n\n /**\n * Vite 8 environment names that are allowed to import virtual:env/server.\n * Use this to allow edge runtimes (Cloudflare Workers → 'workerd', Deno Deploy → 'ssr').\n * @default ['ssr']\n */\n serverEnvironments?: string[]\n\n /**\n * Behavior when virtual:env/server is imported from a disallowed environment.\n *\n * - 'warn' — Deprecation warning printed to terminal + vite-env-warnings.log written.\n * Build succeeds but exits with code 1. Default in 0.x releases.\n * The default will change to 'error' in 1.0.0.\n *\n * - 'error' — Hard build error. No artifacts emitted.\n *\n * - 'stub' — Returns a module that throws at runtime if the import executes.\n * Use for testing environments (Vitest jsdom) or framework isomorphic files\n * where the import exists but the code path is never reached in a server context.\n *\n * @default 'warn'\n */\n onClientAccessOfServerModule?: 'error' | 'stub' | 'warn'\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 let serverModuleGuardFails: GuardFail[] = []\n let didSetExitCode = false\n\n const serverEnvs = options.serverEnvironments ?? ['ssr']\n const guardMode = options.onClientAccessOfServerModule ?? 'warn'\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 serverModuleGuardFails = []\n if (didSetExitCode) {\n process.exitCode = 0\n didSetExitCode = false\n }\n\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(this: Rollup.PluginContext, source, importer) {\n if (source === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (source === 'virtual:env/server') {\n const envName = this.environment?.name ?? 'client'\n const result = checkServerModuleAccess(envName, serverEnvs, guardMode, importer)\n if (!result.allowed)\n serverModuleGuardFails.push(result)\n return '\\0virtual:env/server'\n }\n },\n\n load(this: Rollup.PluginContext, id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server') {\n const envName = this.environment?.name ?? 'client'\n // Filter to fails from this environment only — other envs may have recorded fails for their own loads\n const envFails = serverModuleGuardFails.filter(f => f.envName === envName)\n if (envFails.length > 0) {\n // warn once per load cycle using the last recorded fail; unique importers are written to the log file\n const latest = envFails.at(-1)!\n if (latest.mode === 'error')\n throw new Error(formatHardError(latest))\n if (latest.mode === 'stub')\n return buildServerStubModule(envName)\n resolvedConfig.logger.warn(`\\n${formatGuardWarning(latest)}`)\n }\n return buildServerModule(envDefinition, lastValidated)\n }\n },\n\n async buildEnd(error) {\n if (error)\n return\n if (serverModuleGuardFails.length === 0)\n return\n if (guardMode !== 'warn')\n return\n await writeWarningsLog(serverModuleGuardFails, resolvedConfig.root)\n process.exitCode = 1\n didSetExitCode = true\n },\n\n generateBundle(this: Rollup.PluginContext, _options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const envName = this.environment?.name ?? 'client'\n if (serverEnvs.includes(envName))\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 serverModuleGuardFails = []\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)\n })\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.cjs","names":["formatGuardLogEntry","path","fs","process","isStandardEnvDefinition","validateStandardEnv","formatStandardSchemaError","path","loadEnvConfig","generateStandardDts","formatHardError","formatGuardWarning","detectServerLeak"],"sources":["../src/guard.ts","../src/log.ts","../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["export type GuardMode = \"error\" | \"stub\" | \"warn\";\n\nexport type GuardResult =\n | { allowed: true }\n | { allowed: false; mode: GuardMode; envName: string; importer: string | undefined };\n\nexport type GuardFail = Extract<GuardResult, { allowed: false }>;\n\n/**\n * Determines whether the given Vite environment is allowed to import virtual:env/server.\n * Returns a GuardResult discriminated union — allowed or fail with context.\n * When this.environment is undefined (should not occur with Vite ≥ 8), callers default\n * envName to 'client' — failing closed (restrictive) is safer than failing open.\n */\nexport function checkServerModuleAccess(\n envName: string,\n serverEnvironments: string[],\n mode: GuardMode,\n importer: string | undefined,\n): GuardResult {\n if (serverEnvironments.includes(envName)) return { allowed: true };\n return { allowed: false, mode, envName, importer };\n}\n\n/**\n * Generates the stub virtual module returned when onClientAccessOfServerModule is 'stub'.\n * The stub throws at runtime if executed — its message reflects that this import was\n * expected to be unreachable and the assumption was wrong.\n */\nexport function buildServerStubModule(envName: string): { code: string; moduleType: \"js\" } {\n return {\n moduleType: \"js\",\n code: `// Auto-generated by @vite-env/core — server-only module stub\nthrow new Error(\n '[vite-env] virtual:env/server was imported in the \"${envName}\" environment. ' +\n 'This module is server-only and was replaced with a stub. ' +\n 'To allow this environment: add it to serverEnvironments. ' +\n 'To suppress this stub: ensure this import never executes in the \"${envName}\" environment.'\n);`,\n };\n}\n","// @env node\nimport type { GuardFail } from \"./guard\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { formatGuardLogEntry } from \"./format\";\n\nconst LOG_HEADER = `# vite-env warnings — generated by @vite-env/core\n# These warnings will become hard errors in 1.0.0.\n# To enforce immediately: ViteEnv({ onClientAccessOfServerModule: 'error' })\n# To acknowledge and suppress: ViteEnv({ onClientAccessOfServerModule: 'stub' })\n# To allow specific environments: ViteEnv({ serverEnvironments: ['ssr', 'workerd'] })`;\n\n/**\n * Writes accumulated GuardFail entries to vite-env-warnings.log in the project root.\n * Overwrites on each build — stale entries from previous builds must not persist.\n * Called only in 'warn' mode from buildEnd, after verifying the build succeeded.\n */\nexport async function writeWarningsLog(fails: GuardFail[], root: string): Promise<void> {\n const seen = new Set<string>();\n const unique = fails.filter((fail) => {\n const key = `${fail.envName}::${fail.importer ?? \"\"}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n const timestamp = new Date().toISOString();\n const entries = unique.map((fail) => formatGuardLogEntry(fail, timestamp)).join(\"\\n\\n\");\n const content = `${LOG_HEADER}\\n\\n${entries}\\n`;\n const filePath = path.join(root, \"vite-env-warnings.log\");\n try {\n await fs.writeFile(filePath, content, \"utf-8\");\n } catch (e) {\n throw new Error(\n `[vite-env] Failed to write vite-env-warnings.log to ${root}. Check file permissions.`,\n { cause: e },\n );\n }\n}\n","// @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(config: ResolvedConfig): 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((entry): entry is [string, string] => typeof entry[1] === \"string\"),\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(Object.entries(data).filter(([k]) => clientKeys.has(k)));\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, Rollup } from \"vite\";\nimport type { GuardFail } from \"./guard\";\nimport type { AnyEnvDefinition } from \"./types\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { loadEnvConfig } from \"./config\";\nimport { generateStandardDts } from \"./dts\";\nimport { formatGuardWarning, formatHardError, formatStandardSchemaError } from \"./format\";\nimport { buildServerStubModule, checkServerModuleAccess } from \"./guard\";\nimport { detectServerLeak } from \"./leak\";\nimport { writeWarningsLog } from \"./log\";\nimport { loadEnvSources } from \"./sources\";\nimport { isStandardEnvDefinition, validateStandardEnv } from \"./standard\";\nimport { buildClientModule, buildServerModule } from \"./virtual\";\n\nexport type ViteEnvOptions = {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string;\n\n /**\n * Vite 8 environment names that are allowed to import virtual:env/server.\n * Use this to allow edge runtimes (Cloudflare Workers → 'workerd', Deno Deploy → 'ssr').\n * @default ['ssr']\n */\n serverEnvironments?: string[];\n\n /**\n * Behavior when virtual:env/server is imported from a disallowed environment.\n *\n * - 'warn' — Deprecation warning printed to terminal + vite-env-warnings.log written.\n * Build succeeds but exits with code 1. Default in 0.x releases.\n * The default will change to 'error' in 1.0.0.\n *\n * - 'error' — Hard build error. No artifacts emitted.\n *\n * - 'stub' — Returns a module that throws at runtime if the import executes.\n * Use for testing environments (Vitest jsdom) or framework isomorphic files\n * where the import exists but the code path is never reached in a server context.\n *\n * @default 'warn'\n */\n onClientAccessOfServerModule?: \"error\" | \"stub\" | \"warn\";\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 let serverModuleGuardFails: GuardFail[] = [];\n let didSetExitCode = false;\n\n const serverEnvs = options.serverEnvironments ?? [\"ssr\"];\n const guardMode = options.onClientAccessOfServerModule ?? \"warn\";\n\n return {\n name: \"vite-env\",\n enforce: \"pre\",\n\n async configResolved(config) {\n resolvedConfig = config;\n\n const configPath = path.resolve(config.root, options.configFile ?? \"env.ts\");\n\n try {\n envDefinition = await loadEnvConfig(configPath);\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 serverModuleGuardFails = [];\n if (didSetExitCode) {\n process.exitCode = 0;\n didSetExitCode = false;\n }\n\n const rawEnv = await loadEnvSources(resolvedConfig);\n const result = await validateAndFormat(envDefinition, rawEnv);\n\n if (\"error\" in result) {\n throw new Error(`[vite-env] Environment validation failed:\\n\\n${result.error}`);\n }\n\n lastValidated = result.data;\n\n if (isStandardEnvDefinition(envDefinition)) {\n await generateStandardDts(envDefinition, resolvedConfig.root);\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(this: Rollup.PluginContext, source, importer) {\n if (source === \"virtual:env/client\") return \"\\0virtual:env/client\";\n if (source === \"virtual:env/server\") {\n const envName = this.environment?.name ?? \"client\";\n const result = checkServerModuleAccess(envName, serverEnvs, guardMode, importer);\n if (!result.allowed) serverModuleGuardFails.push(result);\n return \"\\0virtual:env/server\";\n }\n },\n\n load(this: Rollup.PluginContext, id) {\n if (id === \"\\0virtual:env/client\") return buildClientModule(envDefinition, lastValidated);\n if (id === \"\\0virtual:env/server\") {\n const envName = this.environment?.name ?? \"client\";\n // Filter to fails from this environment only — other envs may have recorded fails for their own loads\n const envFails = serverModuleGuardFails.filter((f) => f.envName === envName);\n if (envFails.length > 0) {\n // warn once per load cycle using the last recorded fail; unique importers are written to the log file\n const latest = envFails.at(-1)!;\n if (latest.mode === \"error\") throw new Error(formatHardError(latest));\n if (latest.mode === \"stub\") return buildServerStubModule(envName);\n resolvedConfig.logger.warn(`\\n${formatGuardWarning(latest)}`);\n }\n return buildServerModule(envDefinition, lastValidated);\n }\n },\n\n async buildEnd(error) {\n if (error) return;\n if (serverModuleGuardFails.length === 0) return;\n if (guardMode !== \"warn\") return;\n await writeWarningsLog(serverModuleGuardFails, resolvedConfig.root);\n process.exitCode = 1;\n didSetExitCode = true;\n },\n\n generateBundle(this: Rollup.PluginContext, _options, bundle) {\n if (resolvedConfig.build.ssr) return;\n\n const envName = this.environment?.name ?? \"client\";\n if (serverEnvs.includes(envName)) 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\")) 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) server.moduleGraph.invalidateModule(clientMod);\n if (serverMod) server.moduleGraph.invalidateModule(serverMod);\n if (clientMod || serverMod) {\n serverModuleGuardFails = [];\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 } 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);\n });\n },\n };\n}\n"],"mappings":"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"}
package/dist/plugin.d.cts CHANGED
@@ -28,7 +28,7 @@ type ViteEnvOptions = {
28
28
  *
29
29
  * @default 'warn'
30
30
  */
31
- onClientAccessOfServerModule?: 'error' | 'stub' | 'warn';
31
+ onClientAccessOfServerModule?: "error" | "stub" | "warn";
32
32
  };
33
33
  declare function ViteEnv(options?: ViteEnvOptions): Plugin;
34
34
  //#endregion
package/dist/plugin.d.mts CHANGED
@@ -28,7 +28,7 @@ type ViteEnvOptions = {
28
28
  *
29
29
  * @default 'warn'
30
30
  */
31
- onClientAccessOfServerModule?: 'error' | 'stub' | 'warn';
31
+ onClientAccessOfServerModule?: "error" | "stub" | "warn";
32
32
  };
33
33
  declare function ViteEnv(options?: ViteEnvOptions): Plugin;
34
34
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/guard.ts","../src/log.ts","../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["export type GuardMode = 'error' | 'stub' | 'warn'\n\nexport type GuardResult\n = | { allowed: true }\n | { allowed: false, mode: GuardMode, envName: string, importer: string | undefined }\n\nexport type GuardFail = Extract<GuardResult, { allowed: false }>\n\n/**\n * Determines whether the given Vite environment is allowed to import virtual:env/server.\n * Returns a GuardResult discriminated union — allowed or fail with context.\n * When this.environment is undefined (should not occur with Vite ≥ 8), callers default\n * envName to 'client' — failing closed (restrictive) is safer than failing open.\n */\nexport function checkServerModuleAccess(\n envName: string,\n serverEnvironments: string[],\n mode: GuardMode,\n importer: string | undefined,\n): GuardResult {\n if (serverEnvironments.includes(envName))\n return { allowed: true }\n return { allowed: false, mode, envName, importer }\n}\n\n/**\n * Generates the stub virtual module returned when onClientAccessOfServerModule is 'stub'.\n * The stub throws at runtime if executed — its message reflects that this import was\n * expected to be unreachable and the assumption was wrong.\n */\nexport function buildServerStubModule(envName: string): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — server-only module stub\nthrow new Error(\n '[vite-env] virtual:env/server was imported in the \"${envName}\" environment. ' +\n 'This module is server-only and was replaced with a stub. ' +\n 'To allow this environment: add it to serverEnvironments. ' +\n 'To suppress this stub: ensure this import never executes in the \"${envName}\" environment.'\n);`,\n }\n}\n","// @env node\nimport type { GuardFail } from './guard'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatGuardLogEntry } from './format'\n\nconst LOG_HEADER = `# vite-env warnings — generated by @vite-env/core\n# These warnings will become hard errors in 1.0.0.\n# To enforce immediately: ViteEnv({ onClientAccessOfServerModule: 'error' })\n# To acknowledge and suppress: ViteEnv({ onClientAccessOfServerModule: 'stub' })\n# To allow specific environments: ViteEnv({ serverEnvironments: ['ssr', 'workerd'] })`\n\n/**\n * Writes accumulated GuardFail entries to vite-env-warnings.log in the project root.\n * Overwrites on each build — stale entries from previous builds must not persist.\n * Called only in 'warn' mode from buildEnd, after verifying the build succeeded.\n */\nexport async function writeWarningsLog(fails: GuardFail[], root: string): Promise<void> {\n const seen = new Set<string>()\n const unique = fails.filter((fail) => {\n const key = `${fail.envName}::${fail.importer ?? ''}`\n if (seen.has(key))\n return false\n seen.add(key)\n return true\n })\n const timestamp = new Date().toISOString()\n const entries = unique.map(fail => formatGuardLogEntry(fail, timestamp)).join('\\n\\n')\n const content = `${LOG_HEADER}\\n\\n${entries}\\n`\n const filePath = path.join(root, 'vite-env-warnings.log')\n try {\n await fs.writeFile(filePath, content, 'utf-8')\n }\n catch (e) {\n throw new Error(\n `[vite-env] Failed to write vite-env-warnings.log to ${root}. Check file permissions.`,\n { cause: e },\n )\n }\n}\n","// @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, Rollup } from 'vite'\nimport type { GuardFail } from './guard'\nimport type { AnyEnvDefinition } from './types'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { loadEnvConfig } from './config'\nimport { generateStandardDts } from './dts'\nimport { formatGuardWarning, formatHardError, formatStandardSchemaError } from './format'\nimport { buildServerStubModule, checkServerModuleAccess } from './guard'\nimport { detectServerLeak } from './leak'\nimport { writeWarningsLog } from './log'\nimport { loadEnvSources } from './sources'\nimport { isStandardEnvDefinition, validateStandardEnv } from './standard'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport type ViteEnvOptions = {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n\n /**\n * Vite 8 environment names that are allowed to import virtual:env/server.\n * Use this to allow edge runtimes (Cloudflare Workers → 'workerd', Deno Deploy → 'ssr').\n * @default ['ssr']\n */\n serverEnvironments?: string[]\n\n /**\n * Behavior when virtual:env/server is imported from a disallowed environment.\n *\n * - 'warn' — Deprecation warning printed to terminal + vite-env-warnings.log written.\n * Build succeeds but exits with code 1. Default in 0.x releases.\n * The default will change to 'error' in 1.0.0.\n *\n * - 'error' — Hard build error. No artifacts emitted.\n *\n * - 'stub' — Returns a module that throws at runtime if the import executes.\n * Use for testing environments (Vitest jsdom) or framework isomorphic files\n * where the import exists but the code path is never reached in a server context.\n *\n * @default 'warn'\n */\n onClientAccessOfServerModule?: 'error' | 'stub' | 'warn'\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 let serverModuleGuardFails: GuardFail[] = []\n let didSetExitCode = false\n\n const serverEnvs = options.serverEnvironments ?? ['ssr']\n const guardMode = options.onClientAccessOfServerModule ?? 'warn'\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 serverModuleGuardFails = []\n if (didSetExitCode) {\n process.exitCode = 0\n didSetExitCode = false\n }\n\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(this: Rollup.PluginContext, source, importer) {\n if (source === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (source === 'virtual:env/server') {\n const envName = this.environment?.name ?? 'client'\n const result = checkServerModuleAccess(envName, serverEnvs, guardMode, importer)\n if (!result.allowed)\n serverModuleGuardFails.push(result)\n return '\\0virtual:env/server'\n }\n },\n\n load(this: Rollup.PluginContext, id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server') {\n const envName = this.environment?.name ?? 'client'\n // Filter to fails from this environment only — other envs may have recorded fails for their own loads\n const envFails = serverModuleGuardFails.filter(f => f.envName === envName)\n if (envFails.length > 0) {\n // warn once per load cycle using the last recorded fail; unique importers are written to the log file\n const latest = envFails.at(-1)!\n if (latest.mode === 'error')\n throw new Error(formatHardError(latest))\n if (latest.mode === 'stub')\n return buildServerStubModule(envName)\n resolvedConfig.logger.warn(`\\n${formatGuardWarning(latest)}`)\n }\n return buildServerModule(envDefinition, lastValidated)\n }\n },\n\n async buildEnd(error) {\n if (error)\n return\n if (serverModuleGuardFails.length === 0)\n return\n if (guardMode !== 'warn')\n return\n await writeWarningsLog(serverModuleGuardFails, resolvedConfig.root)\n process.exitCode = 1\n didSetExitCode = true\n },\n\n generateBundle(this: Rollup.PluginContext, _options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const envName = this.environment?.name ?? 'client'\n if (serverEnvs.includes(envName))\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 serverModuleGuardFails = []\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)\n })\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/guard.ts","../src/log.ts","../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["export type GuardMode = \"error\" | \"stub\" | \"warn\";\n\nexport type GuardResult =\n | { allowed: true }\n | { allowed: false; mode: GuardMode; envName: string; importer: string | undefined };\n\nexport type GuardFail = Extract<GuardResult, { allowed: false }>;\n\n/**\n * Determines whether the given Vite environment is allowed to import virtual:env/server.\n * Returns a GuardResult discriminated union — allowed or fail with context.\n * When this.environment is undefined (should not occur with Vite ≥ 8), callers default\n * envName to 'client' — failing closed (restrictive) is safer than failing open.\n */\nexport function checkServerModuleAccess(\n envName: string,\n serverEnvironments: string[],\n mode: GuardMode,\n importer: string | undefined,\n): GuardResult {\n if (serverEnvironments.includes(envName)) return { allowed: true };\n return { allowed: false, mode, envName, importer };\n}\n\n/**\n * Generates the stub virtual module returned when onClientAccessOfServerModule is 'stub'.\n * The stub throws at runtime if executed — its message reflects that this import was\n * expected to be unreachable and the assumption was wrong.\n */\nexport function buildServerStubModule(envName: string): { code: string; moduleType: \"js\" } {\n return {\n moduleType: \"js\",\n code: `// Auto-generated by @vite-env/core — server-only module stub\nthrow new Error(\n '[vite-env] virtual:env/server was imported in the \"${envName}\" environment. ' +\n 'This module is server-only and was replaced with a stub. ' +\n 'To allow this environment: add it to serverEnvironments. ' +\n 'To suppress this stub: ensure this import never executes in the \"${envName}\" environment.'\n);`,\n };\n}\n","// @env node\nimport type { GuardFail } from \"./guard\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { formatGuardLogEntry } from \"./format\";\n\nconst LOG_HEADER = `# vite-env warnings — generated by @vite-env/core\n# These warnings will become hard errors in 1.0.0.\n# To enforce immediately: ViteEnv({ onClientAccessOfServerModule: 'error' })\n# To acknowledge and suppress: ViteEnv({ onClientAccessOfServerModule: 'stub' })\n# To allow specific environments: ViteEnv({ serverEnvironments: ['ssr', 'workerd'] })`;\n\n/**\n * Writes accumulated GuardFail entries to vite-env-warnings.log in the project root.\n * Overwrites on each build — stale entries from previous builds must not persist.\n * Called only in 'warn' mode from buildEnd, after verifying the build succeeded.\n */\nexport async function writeWarningsLog(fails: GuardFail[], root: string): Promise<void> {\n const seen = new Set<string>();\n const unique = fails.filter((fail) => {\n const key = `${fail.envName}::${fail.importer ?? \"\"}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n const timestamp = new Date().toISOString();\n const entries = unique.map((fail) => formatGuardLogEntry(fail, timestamp)).join(\"\\n\\n\");\n const content = `${LOG_HEADER}\\n\\n${entries}\\n`;\n const filePath = path.join(root, \"vite-env-warnings.log\");\n try {\n await fs.writeFile(filePath, content, \"utf-8\");\n } catch (e) {\n throw new Error(\n `[vite-env] Failed to write vite-env-warnings.log to ${root}. Check file permissions.`,\n { cause: e },\n );\n }\n}\n","// @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(config: ResolvedConfig): 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((entry): entry is [string, string] => typeof entry[1] === \"string\"),\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(Object.entries(data).filter(([k]) => clientKeys.has(k)));\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, Rollup } from \"vite\";\nimport type { GuardFail } from \"./guard\";\nimport type { AnyEnvDefinition } from \"./types\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { loadEnvConfig } from \"./config\";\nimport { generateStandardDts } from \"./dts\";\nimport { formatGuardWarning, formatHardError, formatStandardSchemaError } from \"./format\";\nimport { buildServerStubModule, checkServerModuleAccess } from \"./guard\";\nimport { detectServerLeak } from \"./leak\";\nimport { writeWarningsLog } from \"./log\";\nimport { loadEnvSources } from \"./sources\";\nimport { isStandardEnvDefinition, validateStandardEnv } from \"./standard\";\nimport { buildClientModule, buildServerModule } from \"./virtual\";\n\nexport type ViteEnvOptions = {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string;\n\n /**\n * Vite 8 environment names that are allowed to import virtual:env/server.\n * Use this to allow edge runtimes (Cloudflare Workers → 'workerd', Deno Deploy → 'ssr').\n * @default ['ssr']\n */\n serverEnvironments?: string[];\n\n /**\n * Behavior when virtual:env/server is imported from a disallowed environment.\n *\n * - 'warn' — Deprecation warning printed to terminal + vite-env-warnings.log written.\n * Build succeeds but exits with code 1. Default in 0.x releases.\n * The default will change to 'error' in 1.0.0.\n *\n * - 'error' — Hard build error. No artifacts emitted.\n *\n * - 'stub' — Returns a module that throws at runtime if the import executes.\n * Use for testing environments (Vitest jsdom) or framework isomorphic files\n * where the import exists but the code path is never reached in a server context.\n *\n * @default 'warn'\n */\n onClientAccessOfServerModule?: \"error\" | \"stub\" | \"warn\";\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 let serverModuleGuardFails: GuardFail[] = [];\n let didSetExitCode = false;\n\n const serverEnvs = options.serverEnvironments ?? [\"ssr\"];\n const guardMode = options.onClientAccessOfServerModule ?? \"warn\";\n\n return {\n name: \"vite-env\",\n enforce: \"pre\",\n\n async configResolved(config) {\n resolvedConfig = config;\n\n const configPath = path.resolve(config.root, options.configFile ?? \"env.ts\");\n\n try {\n envDefinition = await loadEnvConfig(configPath);\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 serverModuleGuardFails = [];\n if (didSetExitCode) {\n process.exitCode = 0;\n didSetExitCode = false;\n }\n\n const rawEnv = await loadEnvSources(resolvedConfig);\n const result = await validateAndFormat(envDefinition, rawEnv);\n\n if (\"error\" in result) {\n throw new Error(`[vite-env] Environment validation failed:\\n\\n${result.error}`);\n }\n\n lastValidated = result.data;\n\n if (isStandardEnvDefinition(envDefinition)) {\n await generateStandardDts(envDefinition, resolvedConfig.root);\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(this: Rollup.PluginContext, source, importer) {\n if (source === \"virtual:env/client\") return \"\\0virtual:env/client\";\n if (source === \"virtual:env/server\") {\n const envName = this.environment?.name ?? \"client\";\n const result = checkServerModuleAccess(envName, serverEnvs, guardMode, importer);\n if (!result.allowed) serverModuleGuardFails.push(result);\n return \"\\0virtual:env/server\";\n }\n },\n\n load(this: Rollup.PluginContext, id) {\n if (id === \"\\0virtual:env/client\") return buildClientModule(envDefinition, lastValidated);\n if (id === \"\\0virtual:env/server\") {\n const envName = this.environment?.name ?? \"client\";\n // Filter to fails from this environment only — other envs may have recorded fails for their own loads\n const envFails = serverModuleGuardFails.filter((f) => f.envName === envName);\n if (envFails.length > 0) {\n // warn once per load cycle using the last recorded fail; unique importers are written to the log file\n const latest = envFails.at(-1)!;\n if (latest.mode === \"error\") throw new Error(formatHardError(latest));\n if (latest.mode === \"stub\") return buildServerStubModule(envName);\n resolvedConfig.logger.warn(`\\n${formatGuardWarning(latest)}`);\n }\n return buildServerModule(envDefinition, lastValidated);\n }\n },\n\n async buildEnd(error) {\n if (error) return;\n if (serverModuleGuardFails.length === 0) return;\n if (guardMode !== \"warn\") return;\n await writeWarningsLog(serverModuleGuardFails, resolvedConfig.root);\n process.exitCode = 1;\n didSetExitCode = true;\n },\n\n generateBundle(this: Rollup.PluginContext, _options, bundle) {\n if (resolvedConfig.build.ssr) return;\n\n const envName = this.environment?.name ?? \"client\";\n if (serverEnvs.includes(envName)) 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\")) 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) server.moduleGraph.invalidateModule(clientMod);\n if (serverMod) server.moduleGraph.invalidateModule(serverMod);\n if (clientMod || serverMod) {\n serverModuleGuardFails = [];\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 } 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);\n });\n },\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("../dts-BX0Cnqo-.cjs");
2
+ require("../chunk-CKQMccvm.cjs");
3
3
  let zod = require("zod");
4
4
  //#region src/presets/netlify.ts
5
5
  const netlify = {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["z","z","z"],"sources":["../../src/presets/netlify.ts","../../src/presets/railway.ts","../../src/presets/vercel.ts"],"sourcesContent":["import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const netlify = {\n server: {\n // Set to 'true' by Netlify to indicate a Netlify build (note: Vercel uses '1', not 'true')\n NETLIFY: z.enum(['true']),\n BUILD_ID: z.string().min(1),\n CONTEXT: z.enum(['production', 'deploy-preview', 'branch-deploy', 'dev']),\n DEPLOY_ID: z.string().min(1),\n // Full https:// URLs — z.url() is correct here unlike VERCEL_URL\n DEPLOY_URL: z.url(),\n DEPLOY_PRIME_URL: z.url(),\n URL: z.url(),\n BRANCH: z.string().min(1),\n COMMIT_REF: z.string().min(1),\n // Netlify sets this to 'true' on PR deploys; absent (not 'false') on non-PR builds\n PULL_REQUEST: z.enum(['true']).optional(),\n REVIEW_ID: z.string().optional(),\n REPOSITORY_URL: z.url().optional(),\n INCOMING_HOOK_TITLE: z.string().optional(),\n INCOMING_HOOK_URL: z.url().optional(),\n },\n // Netlify sets NETLIFY=true during builds and under `netlify dev`\n detect: env => env.NETLIFY === 'true',\n} satisfies EnvPreset\n","import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const railway = {\n server: {\n RAILWAY_ENVIRONMENT_ID: z.string().min(1),\n RAILWAY_ENVIRONMENT_NAME: z.string().min(1),\n RAILWAY_SERVICE_ID: z.string().min(1),\n RAILWAY_SERVICE_NAME: z.string().min(1),\n RAILWAY_PROJECT_ID: z.string().min(1),\n RAILWAY_PROJECT_NAME: z.string().min(1),\n RAILWAY_DEPLOYMENT_ID: z.string().min(1),\n RAILWAY_REPLICA_ID: z.string().optional(),\n RAILWAY_GIT_COMMIT_SHA: z.string().optional(),\n RAILWAY_GIT_BRANCH: z.string().optional(),\n RAILWAY_GIT_REPO_NAME: z.string().optional(),\n RAILWAY_GIT_REPO_OWNER: z.string().optional(),\n RAILWAY_PUBLIC_DOMAIN: z.string().min(1).optional(),\n RAILWAY_PRIVATE_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_PORT: z.coerce.number().int().min(1).max(65535).optional(),\n // PORT excluded: generic name set by many tools independently; handle it in your own server config\n },\n // Railway always injects the environment id at runtime\n detect: env => !!env.RAILWAY_ENVIRONMENT_ID,\n} satisfies EnvPreset\n","import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const vercel = {\n server: {\n // Set to '1' by Vercel to indicate a Vercel environment\n VERCEL: z.enum(['1']),\n VERCEL_ENV: z.enum(['production', 'preview', 'development']),\n // Bare hostname (e.g. myapp-abc123.vercel.app) — no scheme, z.url() would reject it\n VERCEL_URL: z.string().min(1),\n VERCEL_BRANCH_URL: z.string().min(1).optional(),\n VERCEL_PROJECT_PRODUCTION_URL: z.string().min(1),\n VERCEL_DEPLOYMENT_ID: z.string().min(1),\n VERCEL_REGION: z.string().optional(),\n // z.string() not enum — Vercel may add providers (Azure DevOps, self-hosted GitLab) without notice\n VERCEL_GIT_PROVIDER: z.string().optional(),\n VERCEL_GIT_REPO_SLUG: z.string().optional(),\n VERCEL_GIT_REPO_OWNER: z.string().optional(),\n VERCEL_GIT_COMMIT_REF: z.string().optional(),\n VERCEL_GIT_COMMIT_SHA: z.string().optional(),\n VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(),\n VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(),\n VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(),\n VERCEL_SKEW_PROTECTION_ENABLED: z.enum(['1']).optional(),\n },\n // Vercel sets VERCEL=1 on builds and under `vercel dev`\n detect: env => env.VERCEL === '1',\n} satisfies EnvPreset\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["z","z","z"],"sources":["../../src/presets/netlify.ts","../../src/presets/railway.ts","../../src/presets/vercel.ts"],"sourcesContent":["import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const netlify = {\n server: {\n // Set to 'true' by Netlify to indicate a Netlify build (note: Vercel uses '1', not 'true')\n NETLIFY: z.enum([\"true\"]),\n BUILD_ID: z.string().min(1),\n CONTEXT: z.enum([\"production\", \"deploy-preview\", \"branch-deploy\", \"dev\"]),\n DEPLOY_ID: z.string().min(1),\n // Full https:// URLs — z.url() is correct here unlike VERCEL_URL\n DEPLOY_URL: z.url(),\n DEPLOY_PRIME_URL: z.url(),\n URL: z.url(),\n BRANCH: z.string().min(1),\n COMMIT_REF: z.string().min(1),\n // Netlify sets this to 'true' on PR deploys; absent (not 'false') on non-PR builds\n PULL_REQUEST: z.enum([\"true\"]).optional(),\n REVIEW_ID: z.string().optional(),\n REPOSITORY_URL: z.url().optional(),\n INCOMING_HOOK_TITLE: z.string().optional(),\n INCOMING_HOOK_URL: z.url().optional(),\n },\n // Netlify sets NETLIFY=true during builds and under `netlify dev`\n detect: (env) => env.NETLIFY === \"true\",\n} satisfies EnvPreset;\n","import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const railway = {\n server: {\n RAILWAY_ENVIRONMENT_ID: z.string().min(1),\n RAILWAY_ENVIRONMENT_NAME: z.string().min(1),\n RAILWAY_SERVICE_ID: z.string().min(1),\n RAILWAY_SERVICE_NAME: z.string().min(1),\n RAILWAY_PROJECT_ID: z.string().min(1),\n RAILWAY_PROJECT_NAME: z.string().min(1),\n RAILWAY_DEPLOYMENT_ID: z.string().min(1),\n RAILWAY_REPLICA_ID: z.string().optional(),\n RAILWAY_GIT_COMMIT_SHA: z.string().optional(),\n RAILWAY_GIT_BRANCH: z.string().optional(),\n RAILWAY_GIT_REPO_NAME: z.string().optional(),\n RAILWAY_GIT_REPO_OWNER: z.string().optional(),\n RAILWAY_PUBLIC_DOMAIN: z.string().min(1).optional(),\n RAILWAY_PRIVATE_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_PORT: z.coerce.number().int().min(1).max(65535).optional(),\n // PORT excluded: generic name set by many tools independently; handle it in your own server config\n },\n // Railway always injects the environment id at runtime\n detect: (env) => !!env.RAILWAY_ENVIRONMENT_ID,\n} satisfies EnvPreset;\n","import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const vercel = {\n server: {\n // Set to '1' by Vercel to indicate a Vercel environment\n VERCEL: z.enum([\"1\"]),\n VERCEL_ENV: z.enum([\"production\", \"preview\", \"development\"]),\n // Bare hostname (e.g. myapp-abc123.vercel.app) — no scheme, z.url() would reject it\n VERCEL_URL: z.string().min(1),\n VERCEL_BRANCH_URL: z.string().min(1).optional(),\n VERCEL_PROJECT_PRODUCTION_URL: z.string().min(1),\n VERCEL_DEPLOYMENT_ID: z.string().min(1),\n VERCEL_REGION: z.string().optional(),\n // z.string() not enum — Vercel may add providers (Azure DevOps, self-hosted GitLab) without notice\n VERCEL_GIT_PROVIDER: z.string().optional(),\n VERCEL_GIT_REPO_SLUG: z.string().optional(),\n VERCEL_GIT_REPO_OWNER: z.string().optional(),\n VERCEL_GIT_COMMIT_REF: z.string().optional(),\n VERCEL_GIT_COMMIT_SHA: z.string().optional(),\n VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(),\n VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(),\n VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(),\n VERCEL_SKEW_PROTECTION_ENABLED: z.enum([\"1\"]).optional(),\n },\n // Vercel sets VERCEL=1 on builds and under `vercel dev`\n detect: (env) => env.VERCEL === \"1\",\n} satisfies EnvPreset;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/presets/netlify.ts","../../src/presets/railway.ts","../../src/presets/vercel.ts"],"sourcesContent":["import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const netlify = {\n server: {\n // Set to 'true' by Netlify to indicate a Netlify build (note: Vercel uses '1', not 'true')\n NETLIFY: z.enum(['true']),\n BUILD_ID: z.string().min(1),\n CONTEXT: z.enum(['production', 'deploy-preview', 'branch-deploy', 'dev']),\n DEPLOY_ID: z.string().min(1),\n // Full https:// URLs — z.url() is correct here unlike VERCEL_URL\n DEPLOY_URL: z.url(),\n DEPLOY_PRIME_URL: z.url(),\n URL: z.url(),\n BRANCH: z.string().min(1),\n COMMIT_REF: z.string().min(1),\n // Netlify sets this to 'true' on PR deploys; absent (not 'false') on non-PR builds\n PULL_REQUEST: z.enum(['true']).optional(),\n REVIEW_ID: z.string().optional(),\n REPOSITORY_URL: z.url().optional(),\n INCOMING_HOOK_TITLE: z.string().optional(),\n INCOMING_HOOK_URL: z.url().optional(),\n },\n // Netlify sets NETLIFY=true during builds and under `netlify dev`\n detect: env => env.NETLIFY === 'true',\n} satisfies EnvPreset\n","import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const railway = {\n server: {\n RAILWAY_ENVIRONMENT_ID: z.string().min(1),\n RAILWAY_ENVIRONMENT_NAME: z.string().min(1),\n RAILWAY_SERVICE_ID: z.string().min(1),\n RAILWAY_SERVICE_NAME: z.string().min(1),\n RAILWAY_PROJECT_ID: z.string().min(1),\n RAILWAY_PROJECT_NAME: z.string().min(1),\n RAILWAY_DEPLOYMENT_ID: z.string().min(1),\n RAILWAY_REPLICA_ID: z.string().optional(),\n RAILWAY_GIT_COMMIT_SHA: z.string().optional(),\n RAILWAY_GIT_BRANCH: z.string().optional(),\n RAILWAY_GIT_REPO_NAME: z.string().optional(),\n RAILWAY_GIT_REPO_OWNER: z.string().optional(),\n RAILWAY_PUBLIC_DOMAIN: z.string().min(1).optional(),\n RAILWAY_PRIVATE_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_PORT: z.coerce.number().int().min(1).max(65535).optional(),\n // PORT excluded: generic name set by many tools independently; handle it in your own server config\n },\n // Railway always injects the environment id at runtime\n detect: env => !!env.RAILWAY_ENVIRONMENT_ID,\n} satisfies EnvPreset\n","import type { EnvPreset } from '../types'\nimport { z } from 'zod'\n\nexport const vercel = {\n server: {\n // Set to '1' by Vercel to indicate a Vercel environment\n VERCEL: z.enum(['1']),\n VERCEL_ENV: z.enum(['production', 'preview', 'development']),\n // Bare hostname (e.g. myapp-abc123.vercel.app) — no scheme, z.url() would reject it\n VERCEL_URL: z.string().min(1),\n VERCEL_BRANCH_URL: z.string().min(1).optional(),\n VERCEL_PROJECT_PRODUCTION_URL: z.string().min(1),\n VERCEL_DEPLOYMENT_ID: z.string().min(1),\n VERCEL_REGION: z.string().optional(),\n // z.string() not enum — Vercel may add providers (Azure DevOps, self-hosted GitLab) without notice\n VERCEL_GIT_PROVIDER: z.string().optional(),\n VERCEL_GIT_REPO_SLUG: z.string().optional(),\n VERCEL_GIT_REPO_OWNER: z.string().optional(),\n VERCEL_GIT_COMMIT_REF: z.string().optional(),\n VERCEL_GIT_COMMIT_SHA: z.string().optional(),\n VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(),\n VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(),\n VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(),\n VERCEL_SKEW_PROTECTION_ENABLED: z.enum(['1']).optional(),\n },\n // Vercel sets VERCEL=1 on builds and under `vercel dev`\n detect: env => env.VERCEL === '1',\n} satisfies EnvPreset\n"],"mappings":";;AAGA,MAAa,UAAU;CACrB,QAAQ;EAEN,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;EACzB,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC3B,SAAS,EAAE,KAAK;GAAC;GAAc;GAAkB;GAAiB;GAAM,CAAC;EACzE,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE;EAE5B,YAAY,EAAE,KAAK;EACnB,kBAAkB,EAAE,KAAK;EACzB,KAAK,EAAE,KAAK;EACZ,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;EACzB,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE;EAE7B,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,UAAU;EACzC,WAAW,EAAE,QAAQ,CAAC,UAAU;EAChC,gBAAgB,EAAE,KAAK,CAAC,UAAU;EAClC,qBAAqB,EAAE,QAAQ,CAAC,UAAU;EAC1C,mBAAmB,EAAE,KAAK,CAAC,UAAU;EACtC;CAED,SAAQ,QAAO,IAAI,YAAY;CAChC;;;ACtBD,MAAa,UAAU;CACrB,QAAQ;EACN,wBAAwB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACzC,0BAA0B,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC3C,oBAAoB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACrC,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,oBAAoB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACrC,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,uBAAuB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACxC,oBAAoB,EAAE,QAAQ,CAAC,UAAU;EACzC,wBAAwB,EAAE,QAAQ,CAAC,UAAU;EAC7C,oBAAoB,EAAE,QAAQ,CAAC,UAAU;EACzC,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,wBAAwB,EAAE,QAAQ,CAAC,UAAU;EAC7C,uBAAuB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACnD,wBAAwB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACpD,0BAA0B,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACtD,wBAAwB,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,MAAM,CAAC,UAAU;EAE7E;CAED,SAAQ,QAAO,CAAC,CAAC,IAAI;CACtB;;;ACtBD,MAAa,SAAS;CACpB,QAAQ;EAEN,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;EACrB,YAAY,EAAE,KAAK;GAAC;GAAc;GAAW;GAAc,CAAC;EAE5D,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC7B,mBAAmB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EAC/C,+BAA+B,EAAE,QAAQ,CAAC,IAAI,EAAE;EAChD,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,eAAe,EAAE,QAAQ,CAAC,UAAU;EAEpC,qBAAqB,EAAE,QAAQ,CAAC,UAAU;EAC1C,sBAAsB,EAAE,QAAQ,CAAC,UAAU;EAC3C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,2BAA2B,EAAE,QAAQ,CAAC,UAAU;EAChD,gCAAgC,EAAE,QAAQ,CAAC,UAAU;EACrD,4BAA4B,EAAE,QAAQ,CAAC,UAAU;EACjD,gCAAgC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU;EACzD;CAED,SAAQ,QAAO,IAAI,WAAW;CAC/B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/presets/netlify.ts","../../src/presets/railway.ts","../../src/presets/vercel.ts"],"sourcesContent":["import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const netlify = {\n server: {\n // Set to 'true' by Netlify to indicate a Netlify build (note: Vercel uses '1', not 'true')\n NETLIFY: z.enum([\"true\"]),\n BUILD_ID: z.string().min(1),\n CONTEXT: z.enum([\"production\", \"deploy-preview\", \"branch-deploy\", \"dev\"]),\n DEPLOY_ID: z.string().min(1),\n // Full https:// URLs — z.url() is correct here unlike VERCEL_URL\n DEPLOY_URL: z.url(),\n DEPLOY_PRIME_URL: z.url(),\n URL: z.url(),\n BRANCH: z.string().min(1),\n COMMIT_REF: z.string().min(1),\n // Netlify sets this to 'true' on PR deploys; absent (not 'false') on non-PR builds\n PULL_REQUEST: z.enum([\"true\"]).optional(),\n REVIEW_ID: z.string().optional(),\n REPOSITORY_URL: z.url().optional(),\n INCOMING_HOOK_TITLE: z.string().optional(),\n INCOMING_HOOK_URL: z.url().optional(),\n },\n // Netlify sets NETLIFY=true during builds and under `netlify dev`\n detect: (env) => env.NETLIFY === \"true\",\n} satisfies EnvPreset;\n","import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const railway = {\n server: {\n RAILWAY_ENVIRONMENT_ID: z.string().min(1),\n RAILWAY_ENVIRONMENT_NAME: z.string().min(1),\n RAILWAY_SERVICE_ID: z.string().min(1),\n RAILWAY_SERVICE_NAME: z.string().min(1),\n RAILWAY_PROJECT_ID: z.string().min(1),\n RAILWAY_PROJECT_NAME: z.string().min(1),\n RAILWAY_DEPLOYMENT_ID: z.string().min(1),\n RAILWAY_REPLICA_ID: z.string().optional(),\n RAILWAY_GIT_COMMIT_SHA: z.string().optional(),\n RAILWAY_GIT_BRANCH: z.string().optional(),\n RAILWAY_GIT_REPO_NAME: z.string().optional(),\n RAILWAY_GIT_REPO_OWNER: z.string().optional(),\n RAILWAY_PUBLIC_DOMAIN: z.string().min(1).optional(),\n RAILWAY_PRIVATE_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_DOMAIN: z.string().min(1).optional(),\n RAILWAY_TCP_PROXY_PORT: z.coerce.number().int().min(1).max(65535).optional(),\n // PORT excluded: generic name set by many tools independently; handle it in your own server config\n },\n // Railway always injects the environment id at runtime\n detect: (env) => !!env.RAILWAY_ENVIRONMENT_ID,\n} satisfies EnvPreset;\n","import type { EnvPreset } from \"../types\";\nimport { z } from \"zod\";\n\nexport const vercel = {\n server: {\n // Set to '1' by Vercel to indicate a Vercel environment\n VERCEL: z.enum([\"1\"]),\n VERCEL_ENV: z.enum([\"production\", \"preview\", \"development\"]),\n // Bare hostname (e.g. myapp-abc123.vercel.app) — no scheme, z.url() would reject it\n VERCEL_URL: z.string().min(1),\n VERCEL_BRANCH_URL: z.string().min(1).optional(),\n VERCEL_PROJECT_PRODUCTION_URL: z.string().min(1),\n VERCEL_DEPLOYMENT_ID: z.string().min(1),\n VERCEL_REGION: z.string().optional(),\n // z.string() not enum — Vercel may add providers (Azure DevOps, self-hosted GitLab) without notice\n VERCEL_GIT_PROVIDER: z.string().optional(),\n VERCEL_GIT_REPO_SLUG: z.string().optional(),\n VERCEL_GIT_REPO_OWNER: z.string().optional(),\n VERCEL_GIT_COMMIT_REF: z.string().optional(),\n VERCEL_GIT_COMMIT_SHA: z.string().optional(),\n VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(),\n VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(),\n VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(),\n VERCEL_SKEW_PROTECTION_ENABLED: z.enum([\"1\"]).optional(),\n },\n // Vercel sets VERCEL=1 on builds and under `vercel dev`\n detect: (env) => env.VERCEL === \"1\",\n} satisfies EnvPreset;\n"],"mappings":";;AAGA,MAAa,UAAU;CACrB,QAAQ;EAEN,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;EACzB,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC3B,SAAS,EAAE,KAAK;GAAC;GAAc;GAAkB;GAAiB;GAAM,CAAC;EACzE,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE;EAE5B,YAAY,EAAE,KAAK;EACnB,kBAAkB,EAAE,KAAK;EACzB,KAAK,EAAE,KAAK;EACZ,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;EACzB,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE;EAE7B,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,UAAU;EACzC,WAAW,EAAE,QAAQ,CAAC,UAAU;EAChC,gBAAgB,EAAE,KAAK,CAAC,UAAU;EAClC,qBAAqB,EAAE,QAAQ,CAAC,UAAU;EAC1C,mBAAmB,EAAE,KAAK,CAAC,UAAU;EACtC;CAED,SAAS,QAAQ,IAAI,YAAY;CAClC;;;ACtBD,MAAa,UAAU;CACrB,QAAQ;EACN,wBAAwB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACzC,0BAA0B,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC3C,oBAAoB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACrC,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,oBAAoB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACrC,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,uBAAuB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACxC,oBAAoB,EAAE,QAAQ,CAAC,UAAU;EACzC,wBAAwB,EAAE,QAAQ,CAAC,UAAU;EAC7C,oBAAoB,EAAE,QAAQ,CAAC,UAAU;EACzC,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,wBAAwB,EAAE,QAAQ,CAAC,UAAU;EAC7C,uBAAuB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACnD,wBAAwB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACpD,0BAA0B,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EACtD,wBAAwB,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,MAAM,CAAC,UAAU;EAE7E;CAED,SAAS,QAAQ,CAAC,CAAC,IAAI;CACxB;;;ACtBD,MAAa,SAAS;CACpB,QAAQ;EAEN,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;EACrB,YAAY,EAAE,KAAK;GAAC;GAAc;GAAW;GAAc,CAAC;EAE5D,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE;EAC7B,mBAAmB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU;EAC/C,+BAA+B,EAAE,QAAQ,CAAC,IAAI,EAAE;EAChD,sBAAsB,EAAE,QAAQ,CAAC,IAAI,EAAE;EACvC,eAAe,EAAE,QAAQ,CAAC,UAAU;EAEpC,qBAAqB,EAAE,QAAQ,CAAC,UAAU;EAC1C,sBAAsB,EAAE,QAAQ,CAAC,UAAU;EAC3C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,uBAAuB,EAAE,QAAQ,CAAC,UAAU;EAC5C,2BAA2B,EAAE,QAAQ,CAAC,UAAU;EAChD,gCAAgC,EAAE,QAAQ,CAAC,UAAU;EACrD,4BAA4B,EAAE,QAAQ,CAAC,UAAU;EACjD,gCAAgC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU;EACzD;CAED,SAAS,QAAQ,IAAI,WAAW;CACjC"}
package/dist/schema.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./dts-BX0Cnqo-.cjs");
2
+ require("./chunk-CKQMccvm.cjs");
3
3
  let zod = require("zod");
4
4
  //#region src/schema.ts
5
5
  function warnSideConflicts(keys, seen, userKeys, side) {
@@ -1 +1 @@
1
- {"version":3,"file":"schema.cjs","names":["z"],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, EnvPreset, ValidationResult } from './types'\nimport { z } from 'zod'\n\ntype DefineEnvInput = {\n presets?: EnvPreset[]\n} & EnvDefinition\n\nfunction warnSideConflicts(\n keys: string[],\n seen: Set<string>,\n userKeys: Set<string>,\n side: 'server' | 'client',\n): void {\n for (const key of keys) {\n const duplicate = seen.has(key)\n if (duplicate)\n console.warn(`[vite-env] \"${key}\" is defined in multiple presets. The last preset wins.`)\n seen.add(key)\n if (!duplicate && userKeys.has(key))\n console.warn(`[vite-env] \"${key}\" is defined in both a preset and your ${side} config. Your definition wins.`)\n }\n}\n\nfunction warnConflicts(\n presets: EnvPreset[],\n userServerKeys: Set<string>,\n userClientKeys: Set<string>,\n): void {\n const seenServerKeys = new Set<string>()\n const seenClientKeys = new Set<string>()\n\n for (const preset of presets) {\n warnSideConflicts(Object.keys(preset.server ?? {}), seenServerKeys, userServerKeys, 'server')\n warnSideConflicts(Object.keys(preset.client ?? {}), seenClientKeys, userClientKeys, 'client')\n }\n}\n\nexport function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, 'presets'> & Pick<EnvDefinition, 'server' | 'client' | 'presets'> {\n const { presets = [], server, client, ...rest } = definition\n // ...rest intentionally forwarded — T may carry extra keys beyond EnvDefinition\n\n const mergedServer: z.ZodRawShape = Object.assign({}, ...presets.map(p => p.server ?? {}), server)\n const mergedClient: z.ZodRawShape = Object.assign({}, ...presets.map(p => p.client ?? {}), client)\n\n warnConflicts(\n presets,\n new Set(Object.keys(server ?? {})),\n new Set(Object.keys(client ?? {})),\n )\n\n for (const key of Object.keys(mergedClient)) {\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 const result: Record<string, unknown> = { ...rest }\n if (Object.keys(mergedServer).length > 0 || server !== undefined)\n result.server = mergedServer\n if (Object.keys(mergedClient).length > 0 || client !== undefined)\n result.client = mergedClient\n if (presets.length > 0)\n result.presets = presets\n\n return result as Omit<T, 'presets'> & Pick<EnvDefinition, 'presets'>\n}\n\nexport function validateEnv(\n def: EnvDefinition,\n rawEnv: Record<string, string>,\n): ValidationResult {\n const combinedShape: Record<string, z.ZodType> = {\n ...def.server,\n ...def.client,\n } as Record<string, z.ZodType>\n\n // Undetected-platform preset vars validate as optional — they only exist on\n // the platform; requiring them would break local dev. User overrides stay strict.\n // Mutating combinedShape also prevents double-wrapping when two undetected\n // presets share a key: after the first wrap, the identity check fails.\n for (const preset of def.presets ?? []) {\n if (!preset.detect || preset.detect(rawEnv))\n continue\n for (const side of [preset.server, preset.client]) {\n for (const [key, presetSchema] of Object.entries(side ?? {})) {\n if (combinedShape[key] === presetSchema)\n combinedShape[key] = z.optional(combinedShape[key])\n }\n }\n }\n\n const schema = z.object(combinedShape)\n const result = schema.safeParse(rawEnv)\n\n if (result.success) {\n return { success: true, data: result.data, errors: [] as const }\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n }\n}\n"],"mappings":";;;;AAOA,SAAS,kBACP,MACA,MACA,UACA,MACM;AACN,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,MAAI,UACF,SAAQ,KAAK,eAAe,IAAI,yDAAyD;AAC3F,OAAK,IAAI,IAAI;AACb,MAAI,CAAC,aAAa,SAAS,IAAI,IAAI,CACjC,SAAQ,KAAK,eAAe,IAAI,yCAAyC,KAAK,gCAAgC;;;AAIpH,SAAS,cACP,SACA,gBACA,gBACM;CACN,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,iCAAiB,IAAI,KAAa;AAExC,MAAK,MAAM,UAAU,SAAS;AAC5B,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;AAC7F,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;;;AAIjG,SAAgB,UAAoC,YAA0F;CAC5I,MAAM,EAAE,UAAU,EAAE,EAAE,QAAQ,QAAQ,GAAG,SAAS;CAGlD,MAAM,eAA8B,OAAO,OAAO,EAAE,EAAE,GAAG,QAAQ,KAAI,MAAK,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;CAClG,MAAM,eAA8B,OAAO,OAAO,EAAE,EAAE,GAAG,QAAQ,KAAI,MAAK,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;AAElG,eACE,SACA,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,EAClC,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,CACnC;AAED,MAAK,MAAM,OAAO,OAAO,KAAK,aAAa,CACzC,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;CAIL,MAAM,SAAkC,EAAE,GAAG,MAAM;AACnD,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EACrD,QAAO,SAAS;AAClB,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EACrD,QAAO,SAAS;AAClB,KAAI,QAAQ,SAAS,EACnB,QAAO,UAAU;AAEnB,QAAO;;AAGT,SAAgB,YACd,KACA,QACkB;CAClB,MAAM,gBAA2C;EAC/C,GAAG,IAAI;EACP,GAAG,IAAI;EACR;AAMD,MAAK,MAAM,UAAU,IAAI,WAAW,EAAE,EAAE;AACtC,MAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,CACzC;AACF,OAAK,MAAM,QAAQ,CAAC,OAAO,QAAQ,OAAO,OAAO,CAC/C,MAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAC1D,KAAI,cAAc,SAAS,aACzB,eAAc,OAAOA,IAAAA,EAAE,SAAS,cAAc,KAAK;;CAM3D,MAAM,SADSA,IAAAA,EAAE,OAAO,cACH,CAAC,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAW;AAGlE,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
1
+ {"version":3,"file":"schema.cjs","names":["z"],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, EnvPreset, ValidationResult } from \"./types\";\nimport { z } from \"zod\";\n\ntype DefineEnvInput = {\n presets?: EnvPreset[];\n} & EnvDefinition;\n\nfunction warnSideConflicts(\n keys: string[],\n seen: Set<string>,\n userKeys: Set<string>,\n side: \"server\" | \"client\",\n): void {\n for (const key of keys) {\n const duplicate = seen.has(key);\n if (duplicate)\n console.warn(`[vite-env] \"${key}\" is defined in multiple presets. The last preset wins.`);\n seen.add(key);\n if (!duplicate && userKeys.has(key))\n console.warn(\n `[vite-env] \"${key}\" is defined in both a preset and your ${side} config. Your definition wins.`,\n );\n }\n}\n\nfunction warnConflicts(\n presets: EnvPreset[],\n userServerKeys: Set<string>,\n userClientKeys: Set<string>,\n): void {\n const seenServerKeys = new Set<string>();\n const seenClientKeys = new Set<string>();\n\n for (const preset of presets) {\n warnSideConflicts(Object.keys(preset.server ?? {}), seenServerKeys, userServerKeys, \"server\");\n warnSideConflicts(Object.keys(preset.client ?? {}), seenClientKeys, userClientKeys, \"client\");\n }\n}\n\nexport function defineEnv<T extends DefineEnvInput>(\n definition: T,\n): Omit<T, \"presets\"> & Pick<EnvDefinition, \"server\" | \"client\" | \"presets\"> {\n const { presets = [], server, client, ...rest } = definition;\n // ...rest intentionally forwarded — T may carry extra keys beyond EnvDefinition\n\n const mergedServer: z.ZodRawShape = Object.assign(\n {},\n ...presets.map((p) => p.server ?? {}),\n server,\n );\n const mergedClient: z.ZodRawShape = Object.assign(\n {},\n ...presets.map((p) => p.client ?? {}),\n client,\n );\n\n warnConflicts(presets, new Set(Object.keys(server ?? {})), new Set(Object.keys(client ?? {})));\n\n for (const key of Object.keys(mergedClient)) {\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 const result: Record<string, unknown> = { ...rest };\n if (Object.keys(mergedServer).length > 0 || server !== undefined) result.server = mergedServer;\n if (Object.keys(mergedClient).length > 0 || client !== undefined) result.client = mergedClient;\n if (presets.length > 0) result.presets = presets;\n\n return result as Omit<T, \"presets\"> & Pick<EnvDefinition, \"presets\">;\n}\n\nexport function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult {\n const combinedShape: Record<string, z.ZodType> = {\n ...def.server,\n ...def.client,\n } as Record<string, z.ZodType>;\n\n // Undetected-platform preset vars validate as optional — they only exist on\n // the platform; requiring them would break local dev. User overrides stay strict.\n // Mutating combinedShape also prevents double-wrapping when two undetected\n // presets share a key: after the first wrap, the identity check fails.\n for (const preset of def.presets ?? []) {\n if (!preset.detect || preset.detect(rawEnv)) continue;\n for (const side of [preset.server, preset.client]) {\n for (const [key, presetSchema] of Object.entries(side ?? {})) {\n if (combinedShape[key] === presetSchema)\n combinedShape[key] = z.optional(combinedShape[key]);\n }\n }\n }\n\n const schema = z.object(combinedShape);\n const result = schema.safeParse(rawEnv);\n\n if (result.success) {\n return { success: true, data: result.data, errors: [] as const };\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n };\n}\n"],"mappings":";;;;AAOA,SAAS,kBACP,MACA,MACA,UACA,MACM;AACN,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,MAAI,UACF,SAAQ,KAAK,eAAe,IAAI,yDAAyD;AAC3F,OAAK,IAAI,IAAI;AACb,MAAI,CAAC,aAAa,SAAS,IAAI,IAAI,CACjC,SAAQ,KACN,eAAe,IAAI,yCAAyC,KAAK,gCAClE;;;AAIP,SAAS,cACP,SACA,gBACA,gBACM;CACN,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,iCAAiB,IAAI,KAAa;AAExC,MAAK,MAAM,UAAU,SAAS;AAC5B,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;AAC7F,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;;;AAIjG,SAAgB,UACd,YAC2E;CAC3E,MAAM,EAAE,UAAU,EAAE,EAAE,QAAQ,QAAQ,GAAG,SAAS;CAGlD,MAAM,eAA8B,OAAO,OACzC,EAAE,EACF,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,EAAE,CAAC,EACrC,OACD;CACD,MAAM,eAA8B,OAAO,OACzC,EAAE,EACF,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,EAAE,CAAC,EACrC,OACD;AAED,eAAc,SAAS,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,CAAC;AAE9F,MAAK,MAAM,OAAO,OAAO,KAAK,aAAa,CACzC,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;CAIL,MAAM,SAAkC,EAAE,GAAG,MAAM;AACnD,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EAAW,QAAO,SAAS;AAClF,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EAAW,QAAO,SAAS;AAClF,KAAI,QAAQ,SAAS,EAAG,QAAO,UAAU;AAEzC,QAAO;;AAGT,SAAgB,YAAY,KAAoB,QAAkD;CAChG,MAAM,gBAA2C;EAC/C,GAAG,IAAI;EACP,GAAG,IAAI;EACR;AAMD,MAAK,MAAM,UAAU,IAAI,WAAW,EAAE,EAAE;AACtC,MAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,CAAE;AAC7C,OAAK,MAAM,QAAQ,CAAC,OAAO,QAAQ,OAAO,OAAO,CAC/C,MAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAC1D,KAAI,cAAc,SAAS,aACzB,eAAc,OAAOA,IAAAA,EAAE,SAAS,cAAc,KAAK;;CAM3D,MAAM,SADSA,IAAAA,EAAE,OAAO,cACH,CAAC,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAW;AAGlE,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
package/dist/schema.d.cts CHANGED
@@ -1,10 +1,10 @@
1
- import { l as ValidationResult, n as EnvDefinition, r as EnvPreset } from "./types-B61nsO8q.cjs";
1
+ import { l as ValidationResult, n as EnvDefinition, r as EnvPreset } from "./types-DudMh278.cjs";
2
2
 
3
3
  //#region src/schema.d.ts
4
4
  type DefineEnvInput = {
5
5
  presets?: EnvPreset[];
6
6
  } & EnvDefinition;
7
- declare function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, 'presets'> & Pick<EnvDefinition, 'server' | 'client' | 'presets'>;
7
+ declare function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, "presets"> & Pick<EnvDefinition, "server" | "client" | "presets">;
8
8
  declare function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult;
9
9
  //#endregion
10
10
  export { defineEnv, validateEnv };
package/dist/schema.d.mts CHANGED
@@ -1,10 +1,10 @@
1
- import { l as ValidationResult, n as EnvDefinition, r as EnvPreset } from "./types-KniR_Oqf.mjs";
1
+ import { l as ValidationResult, n as EnvDefinition, r as EnvPreset } from "./types-Ctg8aeXQ.mjs";
2
2
 
3
3
  //#region src/schema.d.ts
4
4
  type DefineEnvInput = {
5
5
  presets?: EnvPreset[];
6
6
  } & EnvDefinition;
7
- declare function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, 'presets'> & Pick<EnvDefinition, 'server' | 'client' | 'presets'>;
7
+ declare function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, "presets"> & Pick<EnvDefinition, "server" | "client" | "presets">;
8
8
  declare function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult;
9
9
  //#endregion
10
10
  export { defineEnv, validateEnv };
@@ -1 +1 @@
1
- {"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, EnvPreset, ValidationResult } from './types'\nimport { z } from 'zod'\n\ntype DefineEnvInput = {\n presets?: EnvPreset[]\n} & EnvDefinition\n\nfunction warnSideConflicts(\n keys: string[],\n seen: Set<string>,\n userKeys: Set<string>,\n side: 'server' | 'client',\n): void {\n for (const key of keys) {\n const duplicate = seen.has(key)\n if (duplicate)\n console.warn(`[vite-env] \"${key}\" is defined in multiple presets. The last preset wins.`)\n seen.add(key)\n if (!duplicate && userKeys.has(key))\n console.warn(`[vite-env] \"${key}\" is defined in both a preset and your ${side} config. Your definition wins.`)\n }\n}\n\nfunction warnConflicts(\n presets: EnvPreset[],\n userServerKeys: Set<string>,\n userClientKeys: Set<string>,\n): void {\n const seenServerKeys = new Set<string>()\n const seenClientKeys = new Set<string>()\n\n for (const preset of presets) {\n warnSideConflicts(Object.keys(preset.server ?? {}), seenServerKeys, userServerKeys, 'server')\n warnSideConflicts(Object.keys(preset.client ?? {}), seenClientKeys, userClientKeys, 'client')\n }\n}\n\nexport function defineEnv<T extends DefineEnvInput>(definition: T): Omit<T, 'presets'> & Pick<EnvDefinition, 'server' | 'client' | 'presets'> {\n const { presets = [], server, client, ...rest } = definition\n // ...rest intentionally forwarded — T may carry extra keys beyond EnvDefinition\n\n const mergedServer: z.ZodRawShape = Object.assign({}, ...presets.map(p => p.server ?? {}), server)\n const mergedClient: z.ZodRawShape = Object.assign({}, ...presets.map(p => p.client ?? {}), client)\n\n warnConflicts(\n presets,\n new Set(Object.keys(server ?? {})),\n new Set(Object.keys(client ?? {})),\n )\n\n for (const key of Object.keys(mergedClient)) {\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 const result: Record<string, unknown> = { ...rest }\n if (Object.keys(mergedServer).length > 0 || server !== undefined)\n result.server = mergedServer\n if (Object.keys(mergedClient).length > 0 || client !== undefined)\n result.client = mergedClient\n if (presets.length > 0)\n result.presets = presets\n\n return result as Omit<T, 'presets'> & Pick<EnvDefinition, 'presets'>\n}\n\nexport function validateEnv(\n def: EnvDefinition,\n rawEnv: Record<string, string>,\n): ValidationResult {\n const combinedShape: Record<string, z.ZodType> = {\n ...def.server,\n ...def.client,\n } as Record<string, z.ZodType>\n\n // Undetected-platform preset vars validate as optional — they only exist on\n // the platform; requiring them would break local dev. User overrides stay strict.\n // Mutating combinedShape also prevents double-wrapping when two undetected\n // presets share a key: after the first wrap, the identity check fails.\n for (const preset of def.presets ?? []) {\n if (!preset.detect || preset.detect(rawEnv))\n continue\n for (const side of [preset.server, preset.client]) {\n for (const [key, presetSchema] of Object.entries(side ?? {})) {\n if (combinedShape[key] === presetSchema)\n combinedShape[key] = z.optional(combinedShape[key])\n }\n }\n }\n\n const schema = z.object(combinedShape)\n const result = schema.safeParse(rawEnv)\n\n if (result.success) {\n return { success: true, data: result.data, errors: [] as const }\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n }\n}\n"],"mappings":";;AAOA,SAAS,kBACP,MACA,MACA,UACA,MACM;AACN,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,MAAI,UACF,SAAQ,KAAK,eAAe,IAAI,yDAAyD;AAC3F,OAAK,IAAI,IAAI;AACb,MAAI,CAAC,aAAa,SAAS,IAAI,IAAI,CACjC,SAAQ,KAAK,eAAe,IAAI,yCAAyC,KAAK,gCAAgC;;;AAIpH,SAAS,cACP,SACA,gBACA,gBACM;CACN,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,iCAAiB,IAAI,KAAa;AAExC,MAAK,MAAM,UAAU,SAAS;AAC5B,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;AAC7F,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;;;AAIjG,SAAgB,UAAoC,YAA0F;CAC5I,MAAM,EAAE,UAAU,EAAE,EAAE,QAAQ,QAAQ,GAAG,SAAS;CAGlD,MAAM,eAA8B,OAAO,OAAO,EAAE,EAAE,GAAG,QAAQ,KAAI,MAAK,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;CAClG,MAAM,eAA8B,OAAO,OAAO,EAAE,EAAE,GAAG,QAAQ,KAAI,MAAK,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;AAElG,eACE,SACA,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,EAClC,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,CACnC;AAED,MAAK,MAAM,OAAO,OAAO,KAAK,aAAa,CACzC,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;CAIL,MAAM,SAAkC,EAAE,GAAG,MAAM;AACnD,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EACrD,QAAO,SAAS;AAClB,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EACrD,QAAO,SAAS;AAClB,KAAI,QAAQ,SAAS,EACnB,QAAO,UAAU;AAEnB,QAAO;;AAGT,SAAgB,YACd,KACA,QACkB;CAClB,MAAM,gBAA2C;EAC/C,GAAG,IAAI;EACP,GAAG,IAAI;EACR;AAMD,MAAK,MAAM,UAAU,IAAI,WAAW,EAAE,EAAE;AACtC,MAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,CACzC;AACF,OAAK,MAAM,QAAQ,CAAC,OAAO,QAAQ,OAAO,OAAO,CAC/C,MAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAC1D,KAAI,cAAc,SAAS,aACzB,eAAc,OAAO,EAAE,SAAS,cAAc,KAAK;;CAM3D,MAAM,SADS,EAAE,OAAO,cACH,CAAC,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAW;AAGlE,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
1
+ {"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, EnvPreset, ValidationResult } from \"./types\";\nimport { z } from \"zod\";\n\ntype DefineEnvInput = {\n presets?: EnvPreset[];\n} & EnvDefinition;\n\nfunction warnSideConflicts(\n keys: string[],\n seen: Set<string>,\n userKeys: Set<string>,\n side: \"server\" | \"client\",\n): void {\n for (const key of keys) {\n const duplicate = seen.has(key);\n if (duplicate)\n console.warn(`[vite-env] \"${key}\" is defined in multiple presets. The last preset wins.`);\n seen.add(key);\n if (!duplicate && userKeys.has(key))\n console.warn(\n `[vite-env] \"${key}\" is defined in both a preset and your ${side} config. Your definition wins.`,\n );\n }\n}\n\nfunction warnConflicts(\n presets: EnvPreset[],\n userServerKeys: Set<string>,\n userClientKeys: Set<string>,\n): void {\n const seenServerKeys = new Set<string>();\n const seenClientKeys = new Set<string>();\n\n for (const preset of presets) {\n warnSideConflicts(Object.keys(preset.server ?? {}), seenServerKeys, userServerKeys, \"server\");\n warnSideConflicts(Object.keys(preset.client ?? {}), seenClientKeys, userClientKeys, \"client\");\n }\n}\n\nexport function defineEnv<T extends DefineEnvInput>(\n definition: T,\n): Omit<T, \"presets\"> & Pick<EnvDefinition, \"server\" | \"client\" | \"presets\"> {\n const { presets = [], server, client, ...rest } = definition;\n // ...rest intentionally forwarded — T may carry extra keys beyond EnvDefinition\n\n const mergedServer: z.ZodRawShape = Object.assign(\n {},\n ...presets.map((p) => p.server ?? {}),\n server,\n );\n const mergedClient: z.ZodRawShape = Object.assign(\n {},\n ...presets.map((p) => p.client ?? {}),\n client,\n );\n\n warnConflicts(presets, new Set(Object.keys(server ?? {})), new Set(Object.keys(client ?? {})));\n\n for (const key of Object.keys(mergedClient)) {\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 const result: Record<string, unknown> = { ...rest };\n if (Object.keys(mergedServer).length > 0 || server !== undefined) result.server = mergedServer;\n if (Object.keys(mergedClient).length > 0 || client !== undefined) result.client = mergedClient;\n if (presets.length > 0) result.presets = presets;\n\n return result as Omit<T, \"presets\"> & Pick<EnvDefinition, \"presets\">;\n}\n\nexport function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult {\n const combinedShape: Record<string, z.ZodType> = {\n ...def.server,\n ...def.client,\n } as Record<string, z.ZodType>;\n\n // Undetected-platform preset vars validate as optional — they only exist on\n // the platform; requiring them would break local dev. User overrides stay strict.\n // Mutating combinedShape also prevents double-wrapping when two undetected\n // presets share a key: after the first wrap, the identity check fails.\n for (const preset of def.presets ?? []) {\n if (!preset.detect || preset.detect(rawEnv)) continue;\n for (const side of [preset.server, preset.client]) {\n for (const [key, presetSchema] of Object.entries(side ?? {})) {\n if (combinedShape[key] === presetSchema)\n combinedShape[key] = z.optional(combinedShape[key]);\n }\n }\n }\n\n const schema = z.object(combinedShape);\n const result = schema.safeParse(rawEnv);\n\n if (result.success) {\n return { success: true, data: result.data, errors: [] as const };\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n };\n}\n"],"mappings":";;AAOA,SAAS,kBACP,MACA,MACA,UACA,MACM;AACN,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,MAAI,UACF,SAAQ,KAAK,eAAe,IAAI,yDAAyD;AAC3F,OAAK,IAAI,IAAI;AACb,MAAI,CAAC,aAAa,SAAS,IAAI,IAAI,CACjC,SAAQ,KACN,eAAe,IAAI,yCAAyC,KAAK,gCAClE;;;AAIP,SAAS,cACP,SACA,gBACA,gBACM;CACN,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,iCAAiB,IAAI,KAAa;AAExC,MAAK,MAAM,UAAU,SAAS;AAC5B,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;AAC7F,oBAAkB,OAAO,KAAK,OAAO,UAAU,EAAE,CAAC,EAAE,gBAAgB,gBAAgB,SAAS;;;AAIjG,SAAgB,UACd,YAC2E;CAC3E,MAAM,EAAE,UAAU,EAAE,EAAE,QAAQ,QAAQ,GAAG,SAAS;CAGlD,MAAM,eAA8B,OAAO,OACzC,EAAE,EACF,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,EAAE,CAAC,EACrC,OACD;CACD,MAAM,eAA8B,OAAO,OACzC,EAAE,EACF,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,EAAE,CAAC,EACrC,OACD;AAED,eAAc,SAAS,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,CAAC;AAE9F,MAAK,MAAM,OAAO,OAAO,KAAK,aAAa,CACzC,KAAI,CAAC,IAAI,WAAW,QAAQ,CAC1B,OAAM,IAAI,MACR,8BAA8B,IAAI,uDACR,IAAI,0CAC/B;CAIL,MAAM,SAAkC,EAAE,GAAG,MAAM;AACnD,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EAAW,QAAO,SAAS;AAClF,KAAI,OAAO,KAAK,aAAa,CAAC,SAAS,KAAK,WAAW,KAAA,EAAW,QAAO,SAAS;AAClF,KAAI,QAAQ,SAAS,EAAG,QAAO,UAAU;AAEzC,QAAO;;AAGT,SAAgB,YAAY,KAAoB,QAAkD;CAChG,MAAM,gBAA2C;EAC/C,GAAG,IAAI;EACP,GAAG,IAAI;EACR;AAMD,MAAK,MAAM,UAAU,IAAI,WAAW,EAAE,EAAE;AACtC,MAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,CAAE;AAC7C,OAAK,MAAM,QAAQ,CAAC,OAAO,QAAQ,OAAO,OAAO,CAC/C,MAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAC1D,KAAI,cAAc,SAAS,aACzB,eAAc,OAAO,EAAE,SAAS,cAAc,KAAK;;CAM3D,MAAM,SADS,EAAE,OAAO,cACH,CAAC,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAW;AAGlE,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
@@ -1 +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 Record<string, unknown>)._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,IAAgC,cAAc;;AAGxH,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"}
1
+ {"version":3,"file":"standard.cjs","names":[],"sources":["../src/standard.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type {\n StandardEnvDefinition,\n StandardValidationIssue,\n StandardValidationResult,\n} 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(def: unknown): def is StandardEnvDefinition {\n return (\n def != null &&\n typeof def === \"object\" &&\n \"_standard\" in def &&\n (def as Record<string, unknown>)._standard === true\n );\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 } 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":";;AAOA,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,wBAAwB,KAA4C;AAClF,QACE,OAAO,QACP,OAAO,QAAQ,YACf,eAAe,OACd,IAAgC,cAAc;;AAInD,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;MAGJ,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"}
@@ -1,7 +1,7 @@
1
- import { c as StandardValidationResult, o as StandardEnvDefinition } from "./types-B61nsO8q.cjs";
1
+ import { c as StandardValidationResult, o as StandardEnvDefinition } from "./types-DudMh278.cjs";
2
2
 
3
3
  //#region src/standard.d.ts
4
- declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(definition: T): T & {
4
+ declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, "_standard">>(definition: T): T & {
5
5
  readonly _standard: true;
6
6
  };
7
7
  declare function isStandardEnvDefinition(def: unknown): def is StandardEnvDefinition;
@@ -1,7 +1,7 @@
1
- import { c as StandardValidationResult, o as StandardEnvDefinition } from "./types-KniR_Oqf.mjs";
1
+ import { c as StandardValidationResult, o as StandardEnvDefinition } from "./types-Ctg8aeXQ.mjs";
2
2
 
3
3
  //#region src/standard.d.ts
4
- declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, '_standard'>>(definition: T): T & {
4
+ declare function defineStandardEnv<T extends Omit<StandardEnvDefinition, "_standard">>(definition: T): T & {
5
5
  readonly _standard: true;
6
6
  };
7
7
  declare function isStandardEnvDefinition(def: unknown): def is StandardEnvDefinition;
@@ -1 +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 Record<string, unknown>)._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,IAAgC,cAAc;;AAGxH,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"}
1
+ {"version":3,"file":"standard.mjs","names":[],"sources":["../src/standard.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type {\n StandardEnvDefinition,\n StandardValidationIssue,\n StandardValidationResult,\n} 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(def: unknown): def is StandardEnvDefinition {\n return (\n def != null &&\n typeof def === \"object\" &&\n \"_standard\" in def &&\n (def as Record<string, unknown>)._standard === true\n );\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 } 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":";AAOA,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,wBAAwB,KAA4C;AAClF,QACE,OAAO,QACP,OAAO,QAAQ,YACf,eAAe,OACd,IAAgC,cAAc;;AAInD,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;MAGJ,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"}