@vite-env/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/config.cjs +12 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +7 -0
- package/dist/config.d.mts +7 -0
- package/dist/config.mjs +10 -0
- package/dist/config.mjs.map +1 -0
- package/dist/dts-DT7HjKrz.cjs +99 -0
- package/dist/dts-DT7HjKrz.cjs.map +1 -0
- package/dist/dts.cjs +3 -0
- package/dist/dts.d.cts +12 -0
- package/dist/dts.d.mts +12 -0
- package/dist/dts.mjs +64 -0
- package/dist/dts.mjs.map +1 -0
- package/dist/format.cjs +11 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +7 -0
- package/dist/format.d.mts +7 -0
- package/dist/format.mjs +10 -0
- package/dist/format.mjs.map +1 -0
- package/dist/index.cjs +11 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +3 -0
- package/dist/leak.cjs +25 -0
- package/dist/leak.cjs.map +1 -0
- package/dist/leak.d.cts +22 -0
- package/dist/leak.d.mts +22 -0
- package/dist/leak.mjs +24 -0
- package/dist/leak.mjs.map +1 -0
- package/dist/plugin.cjs +130 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +14 -0
- package/dist/plugin.d.mts +14 -0
- package/dist/plugin.mjs +128 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/schema.cjs +33 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +8 -0
- package/dist/schema.d.mts +8 -0
- package/dist/schema.mjs +30 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/types-BmEBJZdy.d.cts +18 -0
- package/dist/types-CLfG9amO.d.mts +18 -0
- package/package.json +111 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pyyupsk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/config.cjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./dts-DT7HjKrz.cjs");
|
|
3
|
+
let jiti = require("jiti");
|
|
4
|
+
//#region src/config.ts
|
|
5
|
+
async function loadEnvConfig(configPath) {
|
|
6
|
+
const mod = await (0, jiti.createJiti)(configPath).import(configPath);
|
|
7
|
+
return mod.default ?? mod;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
exports.loadEnvConfig = loadEnvConfig;
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=config.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.cjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { EnvDefinition } from './types'\nimport { createJiti } from 'jiti'\n\nexport async function loadEnvConfig(configPath: string): Promise<EnvDefinition> {\n const jiti = createJiti(configPath)\n const mod = await jiti.import(configPath) as any\n return (mod.default ?? mod) as EnvDefinition\n}\n"],"mappings":";;;;AAGA,eAAsB,cAAc,YAA4C;CAE9E,MAAM,MAAM,OAAA,GAAA,KAAA,YADY,WAAW,CACZ,OAAO,WAAW;AACzC,QAAQ,IAAI,WAAW"}
|
package/dist/config.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createJiti } from "jiti";
|
|
2
|
+
//#region src/config.ts
|
|
3
|
+
async function loadEnvConfig(configPath) {
|
|
4
|
+
const mod = await createJiti(configPath).import(configPath);
|
|
5
|
+
return mod.default ?? mod;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { loadEnvConfig };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=config.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { EnvDefinition } from './types'\nimport { createJiti } from 'jiti'\n\nexport async function loadEnvConfig(configPath: string): Promise<EnvDefinition> {\n const jiti = createJiti(configPath)\n const mod = await jiti.import(configPath) as any\n return (mod.default ?? mod) as EnvDefinition\n}\n"],"mappings":";;AAGA,eAAsB,cAAc,YAA4C;CAE9E,MAAM,MAAM,MADC,WAAW,WAAW,CACZ,OAAO,WAAW;AACzC,QAAQ,IAAI,WAAW"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
let zod = require("zod");
|
|
24
|
+
let node_path = require("node:path");
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let node_fs_promises = require("node:fs/promises");
|
|
27
|
+
node_fs_promises = __toESM(node_fs_promises);
|
|
28
|
+
//#region src/dts.ts
|
|
29
|
+
/**
|
|
30
|
+
* Writes vite-env.d.ts to project root.
|
|
31
|
+
* Declares virtual:env/client and virtual:env/server module types.
|
|
32
|
+
* Users never need to manually augment ImportMetaEnv again.
|
|
33
|
+
*/
|
|
34
|
+
async function generateDts(def, root) {
|
|
35
|
+
const clientKeys = {
|
|
36
|
+
...def.client,
|
|
37
|
+
...def.shared
|
|
38
|
+
};
|
|
39
|
+
const serverKeys = {
|
|
40
|
+
...def.server,
|
|
41
|
+
...def.client,
|
|
42
|
+
...def.shared
|
|
43
|
+
};
|
|
44
|
+
const dts = `// Auto-generated by @vite-env/core
|
|
45
|
+
// Do not edit manually — re-generated on every dev server start and build
|
|
46
|
+
|
|
47
|
+
declare module 'virtual:env/client' {
|
|
48
|
+
const env: {
|
|
49
|
+
${zodShapeToTsFields(clientKeys)}
|
|
50
|
+
}
|
|
51
|
+
export { env }
|
|
52
|
+
export default env
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
declare module 'virtual:env/server' {
|
|
56
|
+
const env: {
|
|
57
|
+
${zodShapeToTsFields(serverKeys)}
|
|
58
|
+
}
|
|
59
|
+
export { env }
|
|
60
|
+
export default env
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
await node_fs_promises.default.writeFile(node_path.default.join(root, "vite-env.d.ts"), dts, "utf-8");
|
|
64
|
+
}
|
|
65
|
+
function zodShapeToTsFields(shape) {
|
|
66
|
+
return Object.entries(shape).map(([key, schema]) => {
|
|
67
|
+
const s = schema;
|
|
68
|
+
const tsType = zodToTs(s);
|
|
69
|
+
return ` readonly ${key}${isOptional(s) ? "?" : ""}: ${tsType}`;
|
|
70
|
+
}).join("\n");
|
|
71
|
+
}
|
|
72
|
+
function zodToTs(schema) {
|
|
73
|
+
if (schema instanceof zod.z.ZodOptional) return zodToTs(schema.unwrap());
|
|
74
|
+
if (schema instanceof zod.z.ZodDefault) return zodToTs(schema.def.innerType);
|
|
75
|
+
if (schema instanceof zod.z.ZodString) return "string";
|
|
76
|
+
if (schema instanceof zod.z.ZodNumber) return "number";
|
|
77
|
+
if (schema instanceof zod.z.ZodBoolean) return "boolean";
|
|
78
|
+
if (schema instanceof zod.z.ZodEnum) return schema.options.map((o) => `'${o}'`).join(" | ");
|
|
79
|
+
if (schema instanceof zod.z.ZodPipe) return zodToTs(schema.def.out);
|
|
80
|
+
return "string";
|
|
81
|
+
}
|
|
82
|
+
function isOptional(schema) {
|
|
83
|
+
return schema instanceof zod.z.ZodOptional || schema instanceof zod.z.ZodDefault;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
Object.defineProperty(exports, "__toESM", {
|
|
87
|
+
enumerable: true,
|
|
88
|
+
get: function() {
|
|
89
|
+
return __toESM;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
Object.defineProperty(exports, "generateDts", {
|
|
93
|
+
enumerable: true,
|
|
94
|
+
get: function() {
|
|
95
|
+
return generateDts;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=dts-DT7HjKrz.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dts-DT7HjKrz.cjs","names":["fs","path","z"],"sources":["../src/dts.ts"],"sourcesContent":["// @env node\nimport type { EnvDefinition } from './types'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { z } from 'zod'\n\n/**\n * Writes vite-env.d.ts to project root.\n * Declares virtual:env/client and virtual:env/server module types.\n * Users never need to manually augment ImportMetaEnv again.\n */\nexport async function generateDts(\n def: EnvDefinition,\n root: string,\n): Promise<void> {\n const clientKeys = {\n ...def.client,\n ...def.shared,\n }\n const serverKeys = {\n ...def.server,\n ...def.client,\n ...def.shared,\n }\n\n const clientFields = zodShapeToTsFields(clientKeys)\n const serverFields = zodShapeToTsFields(serverKeys)\n\n const dts = `// Auto-generated by @vite-env/core\n// Do not edit manually — re-generated on every dev server start and build\n\ndeclare module 'virtual:env/client' {\n const env: {\n${clientFields}\n }\n export { env }\n export default env\n}\n\ndeclare module 'virtual:env/server' {\n const env: {\n${serverFields}\n }\n export { env }\n export default env\n}\n`\n\n await fs.writeFile(path.join(root, 'vite-env.d.ts'), dts, 'utf-8')\n}\n\nfunction zodShapeToTsFields(shape: z.ZodRawShape): string {\n return Object.entries(shape)\n .map(([key, schema]) => {\n // Zod v4: ZodRawShape values are $ZodType, cast to ZodTypeAny for instanceof checks\n const s = schema as unknown as z.ZodTypeAny\n const tsType = zodToTs(s)\n const optional = isOptional(s)\n return ` readonly ${key}${optional ? '?' : ''}: ${tsType}`\n })\n .join('\\n')\n}\n\nfunction zodToTs(schema: z.ZodTypeAny): string {\n if (schema instanceof z.ZodOptional)\n return zodToTs(schema.unwrap() as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodDefault)\n return zodToTs(schema.def.innerType as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodString)\n return 'string'\n if (schema instanceof z.ZodNumber)\n return 'number'\n if (schema instanceof z.ZodBoolean)\n return 'boolean'\n if (schema instanceof z.ZodEnum)\n return (schema.options as string[]).map(o => `'${o}'`).join(' | ')\n if (schema instanceof z.ZodPipe)\n return zodToTs(schema.def.out as unknown as z.ZodTypeAny)\n return 'string'\n}\n\nfunction isOptional(schema: z.ZodTypeAny): boolean {\n return schema instanceof z.ZodOptional || schema instanceof z.ZodDefault\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,eAAsB,YACpB,KACA,MACe;CACf,MAAM,aAAa;EACjB,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CACD,MAAM,aAAa;EACjB,GAAG,IAAI;EACP,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAKD,MAAM,MAAM;;;;;EAHS,mBAAmB,WAAW,CAQtC;;;;;;;;EAPQ,mBAAmB,WAAW,CAetC;;;;;;AAOb,OAAMA,iBAAAA,QAAG,UAAUC,UAAAA,QAAK,KAAK,MAAM,gBAAgB,EAAE,KAAK,QAAQ;;AAGpE,SAAS,mBAAmB,OAA8B;AACxD,QAAO,OAAO,QAAQ,MAAM,CACzB,KAAK,CAAC,KAAK,YAAY;EAEtB,MAAM,IAAI;EACV,MAAM,SAAS,QAAQ,EAAE;AAEzB,SAAO,gBAAgB,MADN,WAAW,EAAE,GACU,MAAM,GAAG,IAAI;GACrD,CACD,KAAK,KAAK;;AAGf,SAAS,QAAQ,QAA8B;AAC7C,KAAI,kBAAkBC,IAAAA,EAAE,YACtB,QAAO,QAAQ,OAAO,QAAQ,CAA4B;AAC5D,KAAI,kBAAkBA,IAAAA,EAAE,WACtB,QAAO,QAAQ,OAAO,IAAI,UAAqC;AACjE,KAAI,kBAAkBA,IAAAA,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,WACtB,QAAO;AACT,KAAI,kBAAkBA,IAAAA,EAAE,QACtB,QAAQ,OAAO,QAAqB,KAAI,MAAK,IAAI,EAAE,GAAG,CAAC,KAAK,MAAM;AACpE,KAAI,kBAAkBA,IAAAA,EAAE,QACtB,QAAO,QAAQ,OAAO,IAAI,IAA+B;AAC3D,QAAO;;AAGT,SAAS,WAAW,QAA+B;AACjD,QAAO,kBAAkBA,IAAAA,EAAE,eAAe,kBAAkBA,IAAAA,EAAE"}
|
package/dist/dts.cjs
ADDED
package/dist/dts.d.cts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as EnvDefinition } from "./types-BmEBJZdy.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/dts.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Writes vite-env.d.ts to project root.
|
|
6
|
+
* Declares virtual:env/client and virtual:env/server module types.
|
|
7
|
+
* Users never need to manually augment ImportMetaEnv again.
|
|
8
|
+
*/
|
|
9
|
+
declare function generateDts(def: EnvDefinition, root: string): Promise<void>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { generateDts };
|
|
12
|
+
//# sourceMappingURL=dts.d.cts.map
|
package/dist/dts.d.mts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as EnvDefinition } from "./types-CLfG9amO.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/dts.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Writes vite-env.d.ts to project root.
|
|
6
|
+
* Declares virtual:env/client and virtual:env/server module types.
|
|
7
|
+
* Users never need to manually augment ImportMetaEnv again.
|
|
8
|
+
*/
|
|
9
|
+
declare function generateDts(def: EnvDefinition, root: string): Promise<void>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { generateDts };
|
|
12
|
+
//# sourceMappingURL=dts.d.mts.map
|
package/dist/dts.mjs
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
//#region src/dts.ts
|
|
5
|
+
/**
|
|
6
|
+
* Writes vite-env.d.ts to project root.
|
|
7
|
+
* Declares virtual:env/client and virtual:env/server module types.
|
|
8
|
+
* Users never need to manually augment ImportMetaEnv again.
|
|
9
|
+
*/
|
|
10
|
+
async function generateDts(def, root) {
|
|
11
|
+
const clientKeys = {
|
|
12
|
+
...def.client,
|
|
13
|
+
...def.shared
|
|
14
|
+
};
|
|
15
|
+
const serverKeys = {
|
|
16
|
+
...def.server,
|
|
17
|
+
...def.client,
|
|
18
|
+
...def.shared
|
|
19
|
+
};
|
|
20
|
+
const dts = `// Auto-generated by @vite-env/core
|
|
21
|
+
// Do not edit manually — re-generated on every dev server start and build
|
|
22
|
+
|
|
23
|
+
declare module 'virtual:env/client' {
|
|
24
|
+
const env: {
|
|
25
|
+
${zodShapeToTsFields(clientKeys)}
|
|
26
|
+
}
|
|
27
|
+
export { env }
|
|
28
|
+
export default env
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare module 'virtual:env/server' {
|
|
32
|
+
const env: {
|
|
33
|
+
${zodShapeToTsFields(serverKeys)}
|
|
34
|
+
}
|
|
35
|
+
export { env }
|
|
36
|
+
export default env
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
await fs.writeFile(path.join(root, "vite-env.d.ts"), dts, "utf-8");
|
|
40
|
+
}
|
|
41
|
+
function zodShapeToTsFields(shape) {
|
|
42
|
+
return Object.entries(shape).map(([key, schema]) => {
|
|
43
|
+
const s = schema;
|
|
44
|
+
const tsType = zodToTs(s);
|
|
45
|
+
return ` readonly ${key}${isOptional(s) ? "?" : ""}: ${tsType}`;
|
|
46
|
+
}).join("\n");
|
|
47
|
+
}
|
|
48
|
+
function zodToTs(schema) {
|
|
49
|
+
if (schema instanceof z.ZodOptional) return zodToTs(schema.unwrap());
|
|
50
|
+
if (schema instanceof z.ZodDefault) return zodToTs(schema.def.innerType);
|
|
51
|
+
if (schema instanceof z.ZodString) return "string";
|
|
52
|
+
if (schema instanceof z.ZodNumber) return "number";
|
|
53
|
+
if (schema instanceof z.ZodBoolean) return "boolean";
|
|
54
|
+
if (schema instanceof z.ZodEnum) return schema.options.map((o) => `'${o}'`).join(" | ");
|
|
55
|
+
if (schema instanceof z.ZodPipe) return zodToTs(schema.def.out);
|
|
56
|
+
return "string";
|
|
57
|
+
}
|
|
58
|
+
function isOptional(schema) {
|
|
59
|
+
return schema instanceof z.ZodOptional || schema instanceof z.ZodDefault;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { generateDts };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=dts.mjs.map
|
package/dist/dts.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dts.mjs","names":[],"sources":["../src/dts.ts"],"sourcesContent":["// @env node\nimport type { EnvDefinition } from './types'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { z } from 'zod'\n\n/**\n * Writes vite-env.d.ts to project root.\n * Declares virtual:env/client and virtual:env/server module types.\n * Users never need to manually augment ImportMetaEnv again.\n */\nexport async function generateDts(\n def: EnvDefinition,\n root: string,\n): Promise<void> {\n const clientKeys = {\n ...def.client,\n ...def.shared,\n }\n const serverKeys = {\n ...def.server,\n ...def.client,\n ...def.shared,\n }\n\n const clientFields = zodShapeToTsFields(clientKeys)\n const serverFields = zodShapeToTsFields(serverKeys)\n\n const dts = `// Auto-generated by @vite-env/core\n// Do not edit manually — re-generated on every dev server start and build\n\ndeclare module 'virtual:env/client' {\n const env: {\n${clientFields}\n }\n export { env }\n export default env\n}\n\ndeclare module 'virtual:env/server' {\n const env: {\n${serverFields}\n }\n export { env }\n export default env\n}\n`\n\n await fs.writeFile(path.join(root, 'vite-env.d.ts'), dts, 'utf-8')\n}\n\nfunction zodShapeToTsFields(shape: z.ZodRawShape): string {\n return Object.entries(shape)\n .map(([key, schema]) => {\n // Zod v4: ZodRawShape values are $ZodType, cast to ZodTypeAny for instanceof checks\n const s = schema as unknown as z.ZodTypeAny\n const tsType = zodToTs(s)\n const optional = isOptional(s)\n return ` readonly ${key}${optional ? '?' : ''}: ${tsType}`\n })\n .join('\\n')\n}\n\nfunction zodToTs(schema: z.ZodTypeAny): string {\n if (schema instanceof z.ZodOptional)\n return zodToTs(schema.unwrap() as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodDefault)\n return zodToTs(schema.def.innerType as unknown as z.ZodTypeAny)\n if (schema instanceof z.ZodString)\n return 'string'\n if (schema instanceof z.ZodNumber)\n return 'number'\n if (schema instanceof z.ZodBoolean)\n return 'boolean'\n if (schema instanceof z.ZodEnum)\n return (schema.options as string[]).map(o => `'${o}'`).join(' | ')\n if (schema instanceof z.ZodPipe)\n return zodToTs(schema.def.out as unknown as z.ZodTypeAny)\n return 'string'\n}\n\nfunction isOptional(schema: z.ZodTypeAny): boolean {\n return schema instanceof z.ZodOptional || schema instanceof z.ZodDefault\n}\n"],"mappings":";;;;;;;;;AAWA,eAAsB,YACpB,KACA,MACe;CACf,MAAM,aAAa;EACjB,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CACD,MAAM,aAAa;EACjB,GAAG,IAAI;EACP,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAKD,MAAM,MAAM;;;;;EAHS,mBAAmB,WAAW,CAQtC;;;;;;;;EAPQ,mBAAmB,WAAW,CAetC;;;;;;AAOb,OAAM,GAAG,UAAU,KAAK,KAAK,MAAM,gBAAgB,EAAE,KAAK,QAAQ;;AAGpE,SAAS,mBAAmB,OAA8B;AACxD,QAAO,OAAO,QAAQ,MAAM,CACzB,KAAK,CAAC,KAAK,YAAY;EAEtB,MAAM,IAAI;EACV,MAAM,SAAS,QAAQ,EAAE;AAEzB,SAAO,gBAAgB,MADN,WAAW,EAAE,GACU,MAAM,GAAG,IAAI;GACrD,CACD,KAAK,KAAK;;AAGf,SAAS,QAAQ,QAA8B;AAC7C,KAAI,kBAAkB,EAAE,YACtB,QAAO,QAAQ,OAAO,QAAQ,CAA4B;AAC5D,KAAI,kBAAkB,EAAE,WACtB,QAAO,QAAQ,OAAO,IAAI,UAAqC;AACjE,KAAI,kBAAkB,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkB,EAAE,UACtB,QAAO;AACT,KAAI,kBAAkB,EAAE,WACtB,QAAO;AACT,KAAI,kBAAkB,EAAE,QACtB,QAAQ,OAAO,QAAqB,KAAI,MAAK,IAAI,EAAE,GAAG,CAAC,KAAK,MAAM;AACpE,KAAI,kBAAkB,EAAE,QACtB,QAAO,QAAQ,OAAO,IAAI,IAA+B;AAC3D,QAAO;;AAGT,SAAS,WAAW,QAA+B;AACjD,QAAO,kBAAkB,EAAE,eAAe,kBAAkB,EAAE"}
|
package/dist/format.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/format.ts
|
|
3
|
+
function formatZodError(issues) {
|
|
4
|
+
return issues.map((issue) => {
|
|
5
|
+
return ` \x1B[31m✗\x1B[0m ${(issue.path.length > 0 ? issue.path.join(".") : "(root)").padEnd(28)} ${issue.message}`;
|
|
6
|
+
}).join("\n");
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
exports.formatZodError = formatZodError;
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=format.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.cjs","names":[],"sources":["../src/format.ts"],"sourcesContent":["import type { core } from 'zod'\n\nexport function formatZodError(issues: core.$ZodIssue[]): string {\n return issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)'\n return ` \\x1B[31m✗\\x1B[0m ${path.padEnd(28)} ${issue.message}`\n })\n .join('\\n')\n}\n"],"mappings":";;AAEA,SAAgB,eAAe,QAAkC;AAC/D,QAAO,OACJ,KAAK,UAAU;AAEd,SAAO,uBADM,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,UAC1B,OAAO,GAAG,CAAC,GAAG,MAAM;GACtD,CACD,KAAK,KAAK"}
|
package/dist/format.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/format.ts
|
|
2
|
+
function formatZodError(issues) {
|
|
3
|
+
return issues.map((issue) => {
|
|
4
|
+
return ` \x1B[31m✗\x1B[0m ${(issue.path.length > 0 ? issue.path.join(".") : "(root)").padEnd(28)} ${issue.message}`;
|
|
5
|
+
}).join("\n");
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { formatZodError };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=format.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.mjs","names":[],"sources":["../src/format.ts"],"sourcesContent":["import type { core } from 'zod'\n\nexport function formatZodError(issues: core.$ZodIssue[]): string {\n return issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)'\n return ` \\x1B[31m✗\\x1B[0m ${path.padEnd(28)} ${issue.message}`\n })\n .join('\\n')\n}\n"],"mappings":";AAEA,SAAgB,eAAe,QAAkC;AAC/D,QAAO,OACJ,KAAK,UAAU;AAEd,SAAO,uBADM,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,IAAI,GAAG,UAC1B,OAAO,GAAG,CAAC,GAAG,MAAM;GACtD,CACD,KAAK,KAAK"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./dts-DT7HjKrz.cjs");
|
|
3
|
+
const require_schema = require("./schema.cjs");
|
|
4
|
+
let zod = require("zod");
|
|
5
|
+
exports.defineEnv = require_schema.defineEnv;
|
|
6
|
+
Object.defineProperty(exports, "z", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return zod.z;
|
|
10
|
+
}
|
|
11
|
+
});
|
package/dist/index.d.cts
ADDED
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
package/dist/leak.cjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/leak.ts
|
|
3
|
+
/**
|
|
4
|
+
* Scans all client-destined chunks for literal values of server-only vars.
|
|
5
|
+
* Fires in generateBundle() — Rolldown sequential hook, safe.
|
|
6
|
+
*
|
|
7
|
+
* Strategy: for each server-only key, check if its actual runtime value
|
|
8
|
+
* appears as a literal string in any output chunk's source code.
|
|
9
|
+
* Short/common values (< 8 chars) are skipped to avoid false positives.
|
|
10
|
+
*/
|
|
11
|
+
function detectServerLeak(def, data, bundle) {
|
|
12
|
+
const serverKeys = new Set(Object.keys(def.server ?? {}));
|
|
13
|
+
const serverSecrets = Object.entries(data).filter((entry) => serverKeys.has(entry[0]) && typeof entry[1] === "string" && entry[1].length >= 8);
|
|
14
|
+
const chunks = Object.entries(bundle).filter(([, chunk]) => chunk.type === "chunk" && !!chunk.code);
|
|
15
|
+
const leaks = [];
|
|
16
|
+
for (const [key, value] of serverSecrets) for (const [chunkName, chunk] of chunks) if (chunk.code.includes(value)) leaks.push({
|
|
17
|
+
key,
|
|
18
|
+
chunk: chunkName
|
|
19
|
+
});
|
|
20
|
+
return leaks;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.detectServerLeak = detectServerLeak;
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=leak.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leak.cjs","names":[],"sources":["../src/leak.ts"],"sourcesContent":["import type { EnvDefinition } from './types'\n\ninterface LeakReport {\n key: string\n chunk: string\n}\n\n/**\n * Scans all client-destined chunks for literal values of server-only vars.\n * Fires in generateBundle() — Rolldown sequential hook, safe.\n *\n * Strategy: for each server-only key, check if its actual runtime value\n * appears as a literal string in any output chunk's source code.\n * Short/common values (< 8 chars) are skipped to avoid false positives.\n */\nexport function detectServerLeak(\n def: EnvDefinition,\n data: Record<string, unknown>,\n bundle: Record<string, { type: string, code?: string }>,\n): LeakReport[] {\n const serverKeys = new Set(Object.keys(def.server ?? {}))\n\n const serverSecrets = Object.entries(data).filter(\n (entry): entry is [string, string] =>\n serverKeys.has(entry[0])\n && typeof entry[1] === 'string'\n && entry[1].length >= 8,\n )\n\n const chunks = Object.entries(bundle).filter(\n ([, chunk]) => chunk.type === 'chunk' && !!chunk.code,\n )\n\n const leaks: LeakReport[] = []\n for (const [key, value] of serverSecrets) {\n for (const [chunkName, chunk] of chunks) {\n if (chunk.code!.includes(value)) {\n leaks.push({ key, chunk: chunkName })\n }\n }\n }\n\n return leaks\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,iBACd,KACA,MACA,QACc;CACd,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;CAEzD,MAAM,gBAAgB,OAAO,QAAQ,KAAK,CAAC,QACxC,UACC,WAAW,IAAI,MAAM,GAAG,IACrB,OAAO,MAAM,OAAO,YACpB,MAAM,GAAG,UAAU,EACzB;CAED,MAAM,SAAS,OAAO,QAAQ,OAAO,CAAC,QACnC,GAAG,WAAW,MAAM,SAAS,WAAW,CAAC,CAAC,MAAM,KAClD;CAED,MAAM,QAAsB,EAAE;AAC9B,MAAK,MAAM,CAAC,KAAK,UAAU,cACzB,MAAK,MAAM,CAAC,WAAW,UAAU,OAC/B,KAAI,MAAM,KAAM,SAAS,MAAM,CAC7B,OAAM,KAAK;EAAE;EAAK,OAAO;EAAW,CAAC;AAK3C,QAAO"}
|
package/dist/leak.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { t as EnvDefinition } from "./types-BmEBJZdy.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/leak.d.ts
|
|
4
|
+
interface LeakReport {
|
|
5
|
+
key: string;
|
|
6
|
+
chunk: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Scans all client-destined chunks for literal values of server-only vars.
|
|
10
|
+
* Fires in generateBundle() — Rolldown sequential hook, safe.
|
|
11
|
+
*
|
|
12
|
+
* Strategy: for each server-only key, check if its actual runtime value
|
|
13
|
+
* appears as a literal string in any output chunk's source code.
|
|
14
|
+
* Short/common values (< 8 chars) are skipped to avoid false positives.
|
|
15
|
+
*/
|
|
16
|
+
declare function detectServerLeak(def: EnvDefinition, data: Record<string, unknown>, bundle: Record<string, {
|
|
17
|
+
type: string;
|
|
18
|
+
code?: string;
|
|
19
|
+
}>): LeakReport[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { detectServerLeak };
|
|
22
|
+
//# sourceMappingURL=leak.d.cts.map
|
package/dist/leak.d.mts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { t as EnvDefinition } from "./types-CLfG9amO.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/leak.d.ts
|
|
4
|
+
interface LeakReport {
|
|
5
|
+
key: string;
|
|
6
|
+
chunk: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Scans all client-destined chunks for literal values of server-only vars.
|
|
10
|
+
* Fires in generateBundle() — Rolldown sequential hook, safe.
|
|
11
|
+
*
|
|
12
|
+
* Strategy: for each server-only key, check if its actual runtime value
|
|
13
|
+
* appears as a literal string in any output chunk's source code.
|
|
14
|
+
* Short/common values (< 8 chars) are skipped to avoid false positives.
|
|
15
|
+
*/
|
|
16
|
+
declare function detectServerLeak(def: EnvDefinition, data: Record<string, unknown>, bundle: Record<string, {
|
|
17
|
+
type: string;
|
|
18
|
+
code?: string;
|
|
19
|
+
}>): LeakReport[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { detectServerLeak };
|
|
22
|
+
//# sourceMappingURL=leak.d.mts.map
|
package/dist/leak.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/leak.ts
|
|
2
|
+
/**
|
|
3
|
+
* Scans all client-destined chunks for literal values of server-only vars.
|
|
4
|
+
* Fires in generateBundle() — Rolldown sequential hook, safe.
|
|
5
|
+
*
|
|
6
|
+
* Strategy: for each server-only key, check if its actual runtime value
|
|
7
|
+
* appears as a literal string in any output chunk's source code.
|
|
8
|
+
* Short/common values (< 8 chars) are skipped to avoid false positives.
|
|
9
|
+
*/
|
|
10
|
+
function detectServerLeak(def, data, bundle) {
|
|
11
|
+
const serverKeys = new Set(Object.keys(def.server ?? {}));
|
|
12
|
+
const serverSecrets = Object.entries(data).filter((entry) => serverKeys.has(entry[0]) && typeof entry[1] === "string" && entry[1].length >= 8);
|
|
13
|
+
const chunks = Object.entries(bundle).filter(([, chunk]) => chunk.type === "chunk" && !!chunk.code);
|
|
14
|
+
const leaks = [];
|
|
15
|
+
for (const [key, value] of serverSecrets) for (const [chunkName, chunk] of chunks) if (chunk.code.includes(value)) leaks.push({
|
|
16
|
+
key,
|
|
17
|
+
chunk: chunkName
|
|
18
|
+
});
|
|
19
|
+
return leaks;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { detectServerLeak };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=leak.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leak.mjs","names":[],"sources":["../src/leak.ts"],"sourcesContent":["import type { EnvDefinition } from './types'\n\ninterface LeakReport {\n key: string\n chunk: string\n}\n\n/**\n * Scans all client-destined chunks for literal values of server-only vars.\n * Fires in generateBundle() — Rolldown sequential hook, safe.\n *\n * Strategy: for each server-only key, check if its actual runtime value\n * appears as a literal string in any output chunk's source code.\n * Short/common values (< 8 chars) are skipped to avoid false positives.\n */\nexport function detectServerLeak(\n def: EnvDefinition,\n data: Record<string, unknown>,\n bundle: Record<string, { type: string, code?: string }>,\n): LeakReport[] {\n const serverKeys = new Set(Object.keys(def.server ?? {}))\n\n const serverSecrets = Object.entries(data).filter(\n (entry): entry is [string, string] =>\n serverKeys.has(entry[0])\n && typeof entry[1] === 'string'\n && entry[1].length >= 8,\n )\n\n const chunks = Object.entries(bundle).filter(\n ([, chunk]) => chunk.type === 'chunk' && !!chunk.code,\n )\n\n const leaks: LeakReport[] = []\n for (const [key, value] of serverSecrets) {\n for (const [chunkName, chunk] of chunks) {\n if (chunk.code!.includes(value)) {\n leaks.push({ key, chunk: chunkName })\n }\n }\n }\n\n return leaks\n}\n"],"mappings":";;;;;;;;;AAeA,SAAgB,iBACd,KACA,MACA,QACc;CACd,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;CAEzD,MAAM,gBAAgB,OAAO,QAAQ,KAAK,CAAC,QACxC,UACC,WAAW,IAAI,MAAM,GAAG,IACrB,OAAO,MAAM,OAAO,YACpB,MAAM,GAAG,UAAU,EACzB;CAED,MAAM,SAAS,OAAO,QAAQ,OAAO,CAAC,QACnC,GAAG,WAAW,MAAM,SAAS,WAAW,CAAC,CAAC,MAAM,KAClD;CAED,MAAM,QAAsB,EAAE;AAC9B,MAAK,MAAM,CAAC,KAAK,UAAU,cACzB,MAAK,MAAM,CAAC,WAAW,UAAU,OAC/B,KAAI,MAAM,KAAM,SAAS,MAAM,CAC7B,OAAM,KAAK;EAAE;EAAK,OAAO;EAAW,CAAC;AAK3C,QAAO"}
|
package/dist/plugin.cjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const require_dts = require("./dts-DT7HjKrz.cjs");
|
|
2
|
+
const require_schema = require("./schema.cjs");
|
|
3
|
+
const require_config = require("./config.cjs");
|
|
4
|
+
const require_format = require("./format.cjs");
|
|
5
|
+
const require_leak = require("./leak.cjs");
|
|
6
|
+
let node_path = require("node:path");
|
|
7
|
+
node_path = require_dts.__toESM(node_path);
|
|
8
|
+
let node_process = require("node:process");
|
|
9
|
+
node_process = require_dts.__toESM(node_process);
|
|
10
|
+
let vite = require("vite");
|
|
11
|
+
//#region src/sources.ts
|
|
12
|
+
/**
|
|
13
|
+
* Merge priority (highest → lowest):
|
|
14
|
+
* 1. process.env (CI pipeline secrets win)
|
|
15
|
+
* 2. .env.[mode].local
|
|
16
|
+
* 3. .env.[mode]
|
|
17
|
+
* 4. .env.local
|
|
18
|
+
* 5. .env
|
|
19
|
+
*
|
|
20
|
+
* Prefix '' = load everything, schema decides what's valid.
|
|
21
|
+
*/
|
|
22
|
+
async function loadEnvSources(config) {
|
|
23
|
+
return {
|
|
24
|
+
...(0, vite.loadEnv)(config.mode, config.envDir || config.root, ""),
|
|
25
|
+
...filterStrings(node_process.default.env)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function filterStrings(env) {
|
|
29
|
+
return Object.fromEntries(Object.entries(env).filter((entry) => typeof entry[1] === "string"));
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/virtual.ts
|
|
33
|
+
function buildClientModule(def, data) {
|
|
34
|
+
const clientKeys = new Set([...Object.keys(def.client ?? {}), ...Object.keys(def.shared ?? {})]);
|
|
35
|
+
const clientData = Object.fromEntries(Object.entries(data).filter(([k]) => clientKeys.has(k)));
|
|
36
|
+
return {
|
|
37
|
+
moduleType: "js",
|
|
38
|
+
code: `// Auto-generated by @vite-env/core — do not edit
|
|
39
|
+
export const env = Object.freeze(${JSON.stringify(clientData, null, 2)});
|
|
40
|
+
export default env;`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function buildServerModule(_def, data) {
|
|
44
|
+
return {
|
|
45
|
+
moduleType: "js",
|
|
46
|
+
code: `// Auto-generated by @vite-env/core — do not edit
|
|
47
|
+
export const env = Object.freeze(${JSON.stringify(data, null, 2)});
|
|
48
|
+
export default env;`
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/plugin.ts
|
|
53
|
+
function ViteEnv(options = {}) {
|
|
54
|
+
let resolvedConfig;
|
|
55
|
+
let envDefinition;
|
|
56
|
+
let lastValidated = {};
|
|
57
|
+
return {
|
|
58
|
+
name: "vite-env",
|
|
59
|
+
enforce: "pre",
|
|
60
|
+
async configResolved(config) {
|
|
61
|
+
resolvedConfig = config;
|
|
62
|
+
const configPath = node_path.default.resolve(config.root, options.configFile ?? "env.ts");
|
|
63
|
+
try {
|
|
64
|
+
envDefinition = await require_config.loadEnvConfig(configPath);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
throw new Error(`[vite-env] Could not load env definition file at: ${configPath}\n Create an env.ts file and export default defineEnv({ ... })`, { cause: e });
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async buildStart() {
|
|
70
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
71
|
+
const result = require_schema.validateEnv(envDefinition, rawEnv);
|
|
72
|
+
if (!result.success) {
|
|
73
|
+
const formatted = require_format.formatZodError(result.errors);
|
|
74
|
+
throw new Error(`[vite-env] Environment validation failed:\n\n${formatted}`);
|
|
75
|
+
}
|
|
76
|
+
lastValidated = result.data;
|
|
77
|
+
await require_dts.generateDts(envDefinition, resolvedConfig.root);
|
|
78
|
+
const count = Object.keys(result.data ?? {}).length;
|
|
79
|
+
resolvedConfig.logger.info(` \x1B[32m✓\x1B[0m \x1B[36m[vite-env]\x1B[0m ${count} variables validated`);
|
|
80
|
+
},
|
|
81
|
+
resolveId(id) {
|
|
82
|
+
if (id === "virtual:env/client") return "\0virtual:env/client";
|
|
83
|
+
if (id === "virtual:env/server") return "\0virtual:env/server";
|
|
84
|
+
},
|
|
85
|
+
load(id) {
|
|
86
|
+
if (id === "\0virtual:env/client") return buildClientModule(envDefinition, lastValidated);
|
|
87
|
+
if (id === "\0virtual:env/server") return buildServerModule(envDefinition, lastValidated);
|
|
88
|
+
},
|
|
89
|
+
async generateBundle(_options, bundle) {
|
|
90
|
+
if (resolvedConfig.build.ssr) return;
|
|
91
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
92
|
+
const result = require_schema.validateEnv(envDefinition, rawEnv);
|
|
93
|
+
if (!result.success) {
|
|
94
|
+
const formatted = require_format.formatZodError(result.errors);
|
|
95
|
+
throw new Error(`[vite-env] Env validation failed at bundle emit:\n\n${formatted}`);
|
|
96
|
+
}
|
|
97
|
+
const leaks = require_leak.detectServerLeak(envDefinition, result.data || {}, bundle);
|
|
98
|
+
if (leaks.length > 0) throw new Error(`[vite-env] Server environment variables detected in client bundle!\n\n${leaks.map((l) => ` ✗ ${l.key} found in ${l.chunk}`).join("\n")}\n\n These variables are marked as server-only and must never reach the browser.`);
|
|
99
|
+
},
|
|
100
|
+
configureServer(server) {
|
|
101
|
+
const envDir = resolvedConfig.envDir || resolvedConfig.root;
|
|
102
|
+
server.watcher.add(node_path.default.join(envDir, ".env*"));
|
|
103
|
+
let debounceTimer;
|
|
104
|
+
server.watcher.on("change", async (file) => {
|
|
105
|
+
if (!node_path.default.basename(file).startsWith(".env")) return;
|
|
106
|
+
clearTimeout(debounceTimer);
|
|
107
|
+
debounceTimer = setTimeout(async () => {
|
|
108
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
109
|
+
const result = require_schema.validateEnv(envDefinition, rawEnv);
|
|
110
|
+
if (!result.success) {
|
|
111
|
+
const formatted = require_format.formatZodError(result.errors);
|
|
112
|
+
resolvedConfig.logger.warn(`\n \x1B[33m⚠\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidation failed:\n${formatted}`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
lastValidated = result.data;
|
|
116
|
+
const clientMod = server.moduleGraph.getModuleById("\0virtual:env/client");
|
|
117
|
+
if (clientMod) {
|
|
118
|
+
server.moduleGraph.invalidateModule(clientMod);
|
|
119
|
+
server.hot.send({ type: "full-reload" });
|
|
120
|
+
resolvedConfig.logger.info(` \x1B[32m✓\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidated`);
|
|
121
|
+
}
|
|
122
|
+
}, 150);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
module.exports = ViteEnv;
|
|
129
|
+
|
|
130
|
+
//# sourceMappingURL=plugin.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":["process","path","loadEnvConfig","validateEnv","formatZodError","generateDts","detectServerLeak"],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { EnvDefinition } from './types'\n\nexport function buildClientModule(\n def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set([\n ...Object.keys(def.client ?? {}),\n ...Object.keys(def.shared ?? {}),\n ])\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { EnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateDts } from './dts'\nimport { formatZodError } from './format'\nimport { detectServerLeak } from './leak'\nimport { validateEnv } from './schema'\nimport { loadEnvSources } from './sources'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: EnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${formatted}`,\n )\n }\n\n lastValidated = result.data!\n\n await generateDts(envDefinition, resolvedConfig.root)\n\n const count = Object.keys(result.data ?? {}).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n async generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Env validation failed at bundle emit:\\n\\n${formatted}`,\n )\n }\n\n const leaks = detectServerLeak(\n envDefinition,\n result.data || {},\n bundle as Record<string, { type: string, code?: string }>,\n )\n\n if (leaks.length > 0) {\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n }\\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 const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${formatted}`,\n )\n return\n }\n\n lastValidated = result.data!\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n if (clientMod) {\n server.moduleGraph.invalidateModule(clientMod)\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 }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
//#region src/plugin.d.ts
|
|
4
|
+
interface ViteEnvOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Path to env definition file.
|
|
7
|
+
* @default './env.ts' (resolved from project root)
|
|
8
|
+
*/
|
|
9
|
+
configFile?: string;
|
|
10
|
+
}
|
|
11
|
+
declare function ViteEnv(options?: ViteEnvOptions): Plugin;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ViteEnvOptions, ViteEnv as default };
|
|
14
|
+
//# sourceMappingURL=plugin.d.cts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
//#region src/plugin.d.ts
|
|
4
|
+
interface ViteEnvOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Path to env definition file.
|
|
7
|
+
* @default './env.ts' (resolved from project root)
|
|
8
|
+
*/
|
|
9
|
+
configFile?: string;
|
|
10
|
+
}
|
|
11
|
+
declare function ViteEnv(options?: ViteEnvOptions): Plugin;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ViteEnvOptions, ViteEnv as default };
|
|
14
|
+
//# sourceMappingURL=plugin.d.mts.map
|
package/dist/plugin.mjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { validateEnv } from "./schema.mjs";
|
|
2
|
+
import { loadEnvConfig } from "./config.mjs";
|
|
3
|
+
import { generateDts } from "./dts.mjs";
|
|
4
|
+
import { formatZodError } from "./format.mjs";
|
|
5
|
+
import { detectServerLeak } from "./leak.mjs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import process from "node:process";
|
|
8
|
+
import { loadEnv } from "vite";
|
|
9
|
+
//#region src/sources.ts
|
|
10
|
+
/**
|
|
11
|
+
* Merge priority (highest → lowest):
|
|
12
|
+
* 1. process.env (CI pipeline secrets win)
|
|
13
|
+
* 2. .env.[mode].local
|
|
14
|
+
* 3. .env.[mode]
|
|
15
|
+
* 4. .env.local
|
|
16
|
+
* 5. .env
|
|
17
|
+
*
|
|
18
|
+
* Prefix '' = load everything, schema decides what's valid.
|
|
19
|
+
*/
|
|
20
|
+
async function loadEnvSources(config) {
|
|
21
|
+
return {
|
|
22
|
+
...loadEnv(config.mode, config.envDir || config.root, ""),
|
|
23
|
+
...filterStrings(process.env)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function filterStrings(env) {
|
|
27
|
+
return Object.fromEntries(Object.entries(env).filter((entry) => typeof entry[1] === "string"));
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/virtual.ts
|
|
31
|
+
function buildClientModule(def, data) {
|
|
32
|
+
const clientKeys = new Set([...Object.keys(def.client ?? {}), ...Object.keys(def.shared ?? {})]);
|
|
33
|
+
const clientData = Object.fromEntries(Object.entries(data).filter(([k]) => clientKeys.has(k)));
|
|
34
|
+
return {
|
|
35
|
+
moduleType: "js",
|
|
36
|
+
code: `// Auto-generated by @vite-env/core — do not edit
|
|
37
|
+
export const env = Object.freeze(${JSON.stringify(clientData, null, 2)});
|
|
38
|
+
export default env;`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function buildServerModule(_def, data) {
|
|
42
|
+
return {
|
|
43
|
+
moduleType: "js",
|
|
44
|
+
code: `// Auto-generated by @vite-env/core — do not edit
|
|
45
|
+
export const env = Object.freeze(${JSON.stringify(data, null, 2)});
|
|
46
|
+
export default env;`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/plugin.ts
|
|
51
|
+
function ViteEnv(options = {}) {
|
|
52
|
+
let resolvedConfig;
|
|
53
|
+
let envDefinition;
|
|
54
|
+
let lastValidated = {};
|
|
55
|
+
return {
|
|
56
|
+
name: "vite-env",
|
|
57
|
+
enforce: "pre",
|
|
58
|
+
async configResolved(config) {
|
|
59
|
+
resolvedConfig = config;
|
|
60
|
+
const configPath = path.resolve(config.root, options.configFile ?? "env.ts");
|
|
61
|
+
try {
|
|
62
|
+
envDefinition = await loadEnvConfig(configPath);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
throw new Error(`[vite-env] Could not load env definition file at: ${configPath}\n Create an env.ts file and export default defineEnv({ ... })`, { cause: e });
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
async buildStart() {
|
|
68
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
69
|
+
const result = validateEnv(envDefinition, rawEnv);
|
|
70
|
+
if (!result.success) {
|
|
71
|
+
const formatted = formatZodError(result.errors);
|
|
72
|
+
throw new Error(`[vite-env] Environment validation failed:\n\n${formatted}`);
|
|
73
|
+
}
|
|
74
|
+
lastValidated = result.data;
|
|
75
|
+
await generateDts(envDefinition, resolvedConfig.root);
|
|
76
|
+
const count = Object.keys(result.data ?? {}).length;
|
|
77
|
+
resolvedConfig.logger.info(` \x1B[32m✓\x1B[0m \x1B[36m[vite-env]\x1B[0m ${count} variables validated`);
|
|
78
|
+
},
|
|
79
|
+
resolveId(id) {
|
|
80
|
+
if (id === "virtual:env/client") return "\0virtual:env/client";
|
|
81
|
+
if (id === "virtual:env/server") return "\0virtual:env/server";
|
|
82
|
+
},
|
|
83
|
+
load(id) {
|
|
84
|
+
if (id === "\0virtual:env/client") return buildClientModule(envDefinition, lastValidated);
|
|
85
|
+
if (id === "\0virtual:env/server") return buildServerModule(envDefinition, lastValidated);
|
|
86
|
+
},
|
|
87
|
+
async generateBundle(_options, bundle) {
|
|
88
|
+
if (resolvedConfig.build.ssr) return;
|
|
89
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
90
|
+
const result = validateEnv(envDefinition, rawEnv);
|
|
91
|
+
if (!result.success) {
|
|
92
|
+
const formatted = formatZodError(result.errors);
|
|
93
|
+
throw new Error(`[vite-env] Env validation failed at bundle emit:\n\n${formatted}`);
|
|
94
|
+
}
|
|
95
|
+
const leaks = detectServerLeak(envDefinition, result.data || {}, bundle);
|
|
96
|
+
if (leaks.length > 0) throw new Error(`[vite-env] Server environment variables detected in client bundle!\n\n${leaks.map((l) => ` ✗ ${l.key} found in ${l.chunk}`).join("\n")}\n\n These variables are marked as server-only and must never reach the browser.`);
|
|
97
|
+
},
|
|
98
|
+
configureServer(server) {
|
|
99
|
+
const envDir = resolvedConfig.envDir || resolvedConfig.root;
|
|
100
|
+
server.watcher.add(path.join(envDir, ".env*"));
|
|
101
|
+
let debounceTimer;
|
|
102
|
+
server.watcher.on("change", async (file) => {
|
|
103
|
+
if (!path.basename(file).startsWith(".env")) return;
|
|
104
|
+
clearTimeout(debounceTimer);
|
|
105
|
+
debounceTimer = setTimeout(async () => {
|
|
106
|
+
const rawEnv = await loadEnvSources(resolvedConfig);
|
|
107
|
+
const result = validateEnv(envDefinition, rawEnv);
|
|
108
|
+
if (!result.success) {
|
|
109
|
+
const formatted = formatZodError(result.errors);
|
|
110
|
+
resolvedConfig.logger.warn(`\n \x1B[33m⚠\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidation failed:\n${formatted}`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
lastValidated = result.data;
|
|
114
|
+
const clientMod = server.moduleGraph.getModuleById("\0virtual:env/client");
|
|
115
|
+
if (clientMod) {
|
|
116
|
+
server.moduleGraph.invalidateModule(clientMod);
|
|
117
|
+
server.hot.send({ type: "full-reload" });
|
|
118
|
+
resolvedConfig.logger.info(` \x1B[32m✓\x1B[0m \x1B[36m[vite-env]\x1B[0m Env revalidated`);
|
|
119
|
+
}
|
|
120
|
+
}, 150);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
export { ViteEnv as default };
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=plugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/sources.ts","../src/virtual.ts","../src/plugin.ts"],"sourcesContent":["// @env node\nimport type { ResolvedConfig } from 'vite'\nimport process from 'node:process'\nimport { loadEnv } from 'vite'\n\n/**\n * Merge priority (highest → lowest):\n * 1. process.env (CI pipeline secrets win)\n * 2. .env.[mode].local\n * 3. .env.[mode]\n * 4. .env.local\n * 5. .env\n *\n * Prefix '' = load everything, schema decides what's valid.\n */\nexport async function loadEnvSources(\n config: ResolvedConfig,\n): Promise<Record<string, string>> {\n const fileEnv = loadEnv(\n config.mode,\n config.envDir || config.root,\n '', // no prefix filter — schema is the filter\n )\n\n return {\n ...fileEnv,\n ...filterStrings(process.env),\n }\n}\n\nfunction filterStrings(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n}\n","import type { EnvDefinition } from './types'\n\nexport function buildClientModule(\n def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n const clientKeys = new Set([\n ...Object.keys(def.client ?? {}),\n ...Object.keys(def.shared ?? {}),\n ])\n\n const clientData = Object.fromEntries(\n Object.entries(data).filter(([k]) => clientKeys.has(k)),\n )\n\n return {\n moduleType: 'js', // Required: Vite 8 / Rolldown explicit moduleType\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(clientData, null, 2)});\nexport default env;`,\n }\n}\n\nexport function buildServerModule(\n _def: EnvDefinition,\n data: Record<string, unknown>,\n): { code: string, moduleType: 'js' } {\n return {\n moduleType: 'js',\n code: `// Auto-generated by @vite-env/core — do not edit\nexport const env = Object.freeze(${JSON.stringify(data, null, 2)});\nexport default env;`,\n }\n}\n","// @env node\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { EnvDefinition } from './types'\nimport path from 'node:path'\nimport { loadEnvConfig } from './config'\nimport { generateDts } from './dts'\nimport { formatZodError } from './format'\nimport { detectServerLeak } from './leak'\nimport { validateEnv } from './schema'\nimport { loadEnvSources } from './sources'\nimport { buildClientModule, buildServerModule } from './virtual'\n\nexport interface ViteEnvOptions {\n /**\n * Path to env definition file.\n * @default './env.ts' (resolved from project root)\n */\n configFile?: string\n}\n\nexport default function ViteEnv(options: ViteEnvOptions = {}): Plugin {\n let resolvedConfig: ResolvedConfig\n let envDefinition: EnvDefinition\n let lastValidated: Record<string, unknown> = {}\n\n return {\n name: 'vite-env',\n enforce: 'pre',\n\n async configResolved(config) {\n resolvedConfig = config\n\n const configPath = path.resolve(\n config.root,\n options.configFile ?? 'env.ts',\n )\n\n try {\n envDefinition = await loadEnvConfig(configPath)\n }\n catch (e) {\n throw new Error(\n `[vite-env] Could not load env definition file at: ${configPath}\\n`\n + ` Create an env.ts file and export default defineEnv({ ... })`,\n { cause: e },\n )\n }\n },\n\n async buildStart() {\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Environment validation failed:\\n\\n${formatted}`,\n )\n }\n\n lastValidated = result.data!\n\n await generateDts(envDefinition, resolvedConfig.root)\n\n const count = Object.keys(result.data ?? {}).length\n resolvedConfig.logger.info(\n ` \\x1B[32m✓\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m ${count} variables validated`,\n )\n },\n\n resolveId(id) {\n if (id === 'virtual:env/client')\n return '\\0virtual:env/client'\n if (id === 'virtual:env/server')\n return '\\0virtual:env/server'\n },\n\n load(id) {\n if (id === '\\0virtual:env/client')\n return buildClientModule(envDefinition, lastValidated)\n if (id === '\\0virtual:env/server')\n return buildServerModule(envDefinition, lastValidated)\n },\n\n async generateBundle(_options, bundle) {\n if (resolvedConfig.build.ssr)\n return\n\n const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n throw new Error(\n `[vite-env] Env validation failed at bundle emit:\\n\\n${formatted}`,\n )\n }\n\n const leaks = detectServerLeak(\n envDefinition,\n result.data || {},\n bundle as Record<string, { type: string, code?: string }>,\n )\n\n if (leaks.length > 0) {\n throw new Error(\n `[vite-env] Server environment variables detected in client bundle!\\n\\n${leaks.map(l => ` ✗ ${l.key} found in ${l.chunk}`).join('\\n')\n }\\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 const rawEnv = await loadEnvSources(resolvedConfig)\n const result = validateEnv(envDefinition, rawEnv)\n\n if (!result.success) {\n const formatted = formatZodError(result.errors)\n resolvedConfig.logger.warn(\n `\\n \\x1B[33m⚠\\x1B[0m \\x1B[36m[vite-env]\\x1B[0m Env revalidation failed:\\n${formatted}`,\n )\n return\n }\n\n lastValidated = result.data!\n\n const clientMod = server.moduleGraph.getModuleById('\\0virtual:env/client')\n if (clientMod) {\n server.moduleGraph.invalidateModule(clientMod)\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 }, 150) // 150ms debounce\n })\n },\n }\n}\n"],"mappings":"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"}
|
package/dist/schema.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./dts-DT7HjKrz.cjs");
|
|
3
|
+
let zod = require("zod");
|
|
4
|
+
//#region src/schema.ts
|
|
5
|
+
function defineEnv(definition) {
|
|
6
|
+
if (definition.client) {
|
|
7
|
+
for (const key of Object.keys(definition.client)) if (!key.startsWith("VITE_")) throw new Error(`[vite-env] Client env var "${key}" must be prefixed with VITE_.\n Rename it to "VITE_${key}" or move it to "server" if it's secret.`);
|
|
8
|
+
}
|
|
9
|
+
return definition;
|
|
10
|
+
}
|
|
11
|
+
function validateEnv(def, rawEnv) {
|
|
12
|
+
const combinedShape = {
|
|
13
|
+
...def.server,
|
|
14
|
+
...def.client,
|
|
15
|
+
...def.shared
|
|
16
|
+
};
|
|
17
|
+
const result = zod.z.object(combinedShape).safeParse(rawEnv);
|
|
18
|
+
if (result.success) return {
|
|
19
|
+
success: true,
|
|
20
|
+
data: result.data,
|
|
21
|
+
errors: []
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
success: false,
|
|
25
|
+
data: null,
|
|
26
|
+
errors: result.error.issues
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.defineEnv = defineEnv;
|
|
31
|
+
exports.validateEnv = validateEnv;
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=schema.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.cjs","names":["z"],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, ValidationResult } from './types'\nimport { z } from 'zod'\n\nexport function defineEnv(definition: EnvDefinition): EnvDefinition {\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 return definition\n}\n\nexport function validateEnv(\n def: EnvDefinition,\n rawEnv: Record<string, string>,\n): ValidationResult {\n const combinedShape = {\n ...def.server,\n ...def.client,\n ...def.shared,\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: [] }\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n }\n}\n"],"mappings":";;;;AAGA,SAAgB,UAAU,YAA0C;AAClE,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;;AAIP,QAAO;;AAGT,SAAgB,YACd,KACA,QACkB;CAClB,MAAM,gBAAgB;EACpB,GAAG,IAAI;EACP,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAGD,MAAM,SADSA,IAAAA,EAAE,OAAO,cAAc,CAChB,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAE;AAGzD,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { i as ValidationResult, t as EnvDefinition } from "./types-BmEBJZdy.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/schema.d.ts
|
|
4
|
+
declare function defineEnv(definition: EnvDefinition): EnvDefinition;
|
|
5
|
+
declare function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { defineEnv, validateEnv };
|
|
8
|
+
//# sourceMappingURL=schema.d.cts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { i as ValidationResult, t as EnvDefinition } from "./types-CLfG9amO.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/schema.d.ts
|
|
4
|
+
declare function defineEnv(definition: EnvDefinition): EnvDefinition;
|
|
5
|
+
declare function validateEnv(def: EnvDefinition, rawEnv: Record<string, string>): ValidationResult;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { defineEnv, validateEnv };
|
|
8
|
+
//# sourceMappingURL=schema.d.mts.map
|
package/dist/schema.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/schema.ts
|
|
3
|
+
function defineEnv(definition) {
|
|
4
|
+
if (definition.client) {
|
|
5
|
+
for (const key of Object.keys(definition.client)) if (!key.startsWith("VITE_")) throw new Error(`[vite-env] Client env var "${key}" must be prefixed with VITE_.\n Rename it to "VITE_${key}" or move it to "server" if it's secret.`);
|
|
6
|
+
}
|
|
7
|
+
return definition;
|
|
8
|
+
}
|
|
9
|
+
function validateEnv(def, rawEnv) {
|
|
10
|
+
const combinedShape = {
|
|
11
|
+
...def.server,
|
|
12
|
+
...def.client,
|
|
13
|
+
...def.shared
|
|
14
|
+
};
|
|
15
|
+
const result = z.object(combinedShape).safeParse(rawEnv);
|
|
16
|
+
if (result.success) return {
|
|
17
|
+
success: true,
|
|
18
|
+
data: result.data,
|
|
19
|
+
errors: []
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
success: false,
|
|
23
|
+
data: null,
|
|
24
|
+
errors: result.error.issues
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { defineEnv, validateEnv };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=schema.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["import type { EnvDefinition, ValidationResult } from './types'\nimport { z } from 'zod'\n\nexport function defineEnv(definition: EnvDefinition): EnvDefinition {\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 return definition\n}\n\nexport function validateEnv(\n def: EnvDefinition,\n rawEnv: Record<string, string>,\n): ValidationResult {\n const combinedShape = {\n ...def.server,\n ...def.client,\n ...def.shared,\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: [] }\n }\n\n return {\n success: false,\n data: null,\n errors: result.error.issues,\n }\n}\n"],"mappings":";;AAGA,SAAgB,UAAU,YAA0C;AAClE,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;;AAIP,QAAO;;AAGT,SAAgB,YACd,KACA,QACkB;CAClB,MAAM,gBAAgB;EACpB,GAAG,IAAI;EACP,GAAG,IAAI;EACP,GAAG,IAAI;EACR;CAGD,MAAM,SADS,EAAE,OAAO,cAAc,CAChB,UAAU,OAAO;AAEvC,KAAI,OAAO,QACT,QAAO;EAAE,SAAS;EAAM,MAAM,OAAO;EAAM,QAAQ,EAAE;EAAE;AAGzD,QAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ,OAAO,MAAM;EACtB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
interface EnvDefinition {
|
|
5
|
+
server?: z.ZodRawShape;
|
|
6
|
+
client?: z.ZodRawShape;
|
|
7
|
+
shared?: z.ZodRawShape;
|
|
8
|
+
}
|
|
9
|
+
interface ValidationResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
data: Record<string, unknown> | null;
|
|
12
|
+
errors: z.core.$ZodIssue[];
|
|
13
|
+
}
|
|
14
|
+
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<NonNullable<T['client']> & NonNullable<T['shared']>>>;
|
|
15
|
+
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<NonNullable<T['server']> & NonNullable<T['client']> & NonNullable<T['shared']>>>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ValidationResult as i, InferClientEnv as n, InferServerEnv as r, EnvDefinition as t };
|
|
18
|
+
//# sourceMappingURL=types-BmEBJZdy.d.cts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
interface EnvDefinition {
|
|
5
|
+
server?: z.ZodRawShape;
|
|
6
|
+
client?: z.ZodRawShape;
|
|
7
|
+
shared?: z.ZodRawShape;
|
|
8
|
+
}
|
|
9
|
+
interface ValidationResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
data: Record<string, unknown> | null;
|
|
12
|
+
errors: z.core.$ZodIssue[];
|
|
13
|
+
}
|
|
14
|
+
type InferClientEnv<T extends EnvDefinition> = z.infer<z.ZodObject<NonNullable<T['client']> & NonNullable<T['shared']>>>;
|
|
15
|
+
type InferServerEnv<T extends EnvDefinition> = z.infer<z.ZodObject<NonNullable<T['server']> & NonNullable<T['client']> & NonNullable<T['shared']>>>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ValidationResult as i, InferClientEnv as n, InferServerEnv as r, EnvDefinition as t };
|
|
18
|
+
//# sourceMappingURL=types-CLfG9amO.d.mts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vite-env/core",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "The env.ts layer for Vite — define once, validate everywhere, import with types",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": {
|
|
10
|
+
"types": "./dist/index.d.mts",
|
|
11
|
+
"default": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"require": {
|
|
14
|
+
"types": "./dist/index.d.cts",
|
|
15
|
+
"default": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"./config": {
|
|
19
|
+
"import": {
|
|
20
|
+
"types": "./dist/config.d.mts",
|
|
21
|
+
"default": "./dist/config.mjs"
|
|
22
|
+
},
|
|
23
|
+
"require": {
|
|
24
|
+
"types": "./dist/config.d.cts",
|
|
25
|
+
"default": "./dist/config.cjs"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"./dts": {
|
|
29
|
+
"import": {
|
|
30
|
+
"types": "./dist/dts.d.mts",
|
|
31
|
+
"default": "./dist/dts.mjs"
|
|
32
|
+
},
|
|
33
|
+
"require": {
|
|
34
|
+
"types": "./dist/dts.d.cts",
|
|
35
|
+
"default": "./dist/dts.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"./format": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./dist/format.d.mts",
|
|
41
|
+
"default": "./dist/format.mjs"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./dist/format.d.cts",
|
|
45
|
+
"default": "./dist/format.cjs"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"./leak": {
|
|
49
|
+
"import": {
|
|
50
|
+
"types": "./dist/leak.d.mts",
|
|
51
|
+
"default": "./dist/leak.mjs"
|
|
52
|
+
},
|
|
53
|
+
"require": {
|
|
54
|
+
"types": "./dist/leak.d.cts",
|
|
55
|
+
"default": "./dist/leak.cjs"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"./plugin": {
|
|
59
|
+
"import": {
|
|
60
|
+
"types": "./dist/plugin.d.mts",
|
|
61
|
+
"default": "./dist/plugin.mjs"
|
|
62
|
+
},
|
|
63
|
+
"require": {
|
|
64
|
+
"types": "./dist/plugin.d.cts",
|
|
65
|
+
"default": "./dist/plugin.cjs"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"./schema": {
|
|
69
|
+
"import": {
|
|
70
|
+
"types": "./dist/schema.d.mts",
|
|
71
|
+
"default": "./dist/schema.mjs"
|
|
72
|
+
},
|
|
73
|
+
"require": {
|
|
74
|
+
"types": "./dist/schema.d.cts",
|
|
75
|
+
"default": "./dist/schema.cjs"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"./package.json": "./package.json"
|
|
79
|
+
},
|
|
80
|
+
"main": "./dist/index.cjs",
|
|
81
|
+
"module": "./dist/index.mjs",
|
|
82
|
+
"types": "./dist/index.d.cts",
|
|
83
|
+
"files": [
|
|
84
|
+
"dist"
|
|
85
|
+
],
|
|
86
|
+
"engines": {
|
|
87
|
+
"node": ">=20.19.0"
|
|
88
|
+
},
|
|
89
|
+
"peerDependencies": {
|
|
90
|
+
"vite": ">=8.0.0",
|
|
91
|
+
"zod": "^4.0.0"
|
|
92
|
+
},
|
|
93
|
+
"dependencies": {
|
|
94
|
+
"jiti": "^2.6.1"
|
|
95
|
+
},
|
|
96
|
+
"devDependencies": {
|
|
97
|
+
"@types/node": "^25.5.2",
|
|
98
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
99
|
+
"tsdown": "^0.21.7",
|
|
100
|
+
"typescript": "^6.0.2",
|
|
101
|
+
"vite": "^8.0.3",
|
|
102
|
+
"vitest": "^4.1.2",
|
|
103
|
+
"zod": "^4.3.6"
|
|
104
|
+
},
|
|
105
|
+
"scripts": {
|
|
106
|
+
"build": "tsdown",
|
|
107
|
+
"dev": "tsdown --watch",
|
|
108
|
+
"test": "vitest run",
|
|
109
|
+
"typecheck": "tsc --noEmit"
|
|
110
|
+
}
|
|
111
|
+
}
|