void 0.10.8 → 0.10.11
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/AGENT_PROMPT.md +4 -0
- package/README.md +1 -1
- package/dist/{agents-Bmr5tFFb.mjs → agents-CtgBYqld.mjs} +1 -1
- package/dist/{auth-cmd-DlgNwByu.mjs → auth-cmd-BqsdZJp5.mjs} +3 -3
- package/dist/{better-auth-shared-BvnM9px6.d.mts → better-auth-shared-DealXecJ.d.mts} +1 -1
- package/dist/{build-cmd-Br8qL0rA.mjs → build-cmd-Bujrv5q-.mjs} +3 -3
- package/dist/{cache-wH-mP8UE.mjs → cache-C11V8Fxq.mjs} +3 -3
- package/dist/{cancel-deploy-BEBOEgtu.mjs → cancel-deploy-fwFYF04b.mjs} +2 -2
- package/dist/cli/cli.mjs +175 -43
- package/dist/cli/env-schema-probe.d.mts +96 -0
- package/dist/cli/env-schema-probe.mjs +272 -0
- package/dist/{client-Cj96iiBH.mjs → client-Gb71-XkG.mjs} +20 -2
- package/dist/{config-BdUctCZD.mjs → config-CutEMNGJ.mjs} +3 -3
- package/dist/{config-1twldYCW.mjs → config-E03l1C_h.mjs} +8 -2
- package/dist/{create-project-DD9n8Ho-.mjs → create-project-DsYvl3TB.mjs} +3 -3
- package/dist/{db-DjKE2-A-.mjs → db-PZBsLSGb.mjs} +27 -27
- package/dist/{delete-D2kr3Kmk.mjs → delete-mh6p-zkQ.mjs} +3 -3
- package/dist/deploy-DT8wsPZd.mjs +6990 -0
- package/dist/{discover-BuVVSAum.mjs → discover-CJHyvYfR.mjs} +2 -2
- package/dist/dist-DaKKDf8D.mjs +41 -0
- package/dist/{domain-_luIsM_B.mjs → domain-DiaNQbrl.mjs} +2 -2
- package/dist/entry-D7yy4xVH.mjs +100 -0
- package/dist/{env-CO5XAS9t.mjs → env-AAHU02L6.mjs} +5 -5
- package/dist/env-mask-Dd47NbR6.mjs +90 -0
- package/dist/env-public-BfiLcMBk.d.mts +140 -0
- package/dist/env-raw-Cx8ElDdj.mjs +58 -0
- package/dist/{env-types-D51bnR-c.mjs → env-types-QBj-ndax.mjs} +2 -2
- package/dist/env-validation-BdDlGhbN.mjs +1069 -0
- package/dist/{gen-Cf79J4aw.mjs → gen-oup1xBN0.mjs} +8 -8
- package/dist/{github-cmd-B6OX9c7d.mjs → github-cmd-BdNaOVNa.mjs} +102 -3
- package/dist/{handler-imD0UVDT.d.mts → handler-Cjh8uM3Y.d.mts} +1 -1
- package/dist/{headers-BwvFGhkx.mjs → headers-BQknpzkn.mjs} +2 -2
- package/dist/index.d.mts +14 -2
- package/dist/index.mjs +102 -55
- package/dist/{init-KirOzVDs.mjs → init-Dl2PKuQn.mjs} +13 -14
- package/dist/{link-CUmiosyb.mjs → link-CdGHSIy-.mjs} +4 -4
- package/dist/{list-3GEw7b6m.mjs → list-CPwFDZ_c.mjs} +3 -3
- package/dist/{login-DJReaT_Q.mjs → login-BT3H8PN3.mjs} +2 -2
- package/dist/{logs-D-rQ56Lq.mjs → logs-Bt313ax7.mjs} +3 -2
- package/dist/{mcp-D7yc0dXY.mjs → mcp-DoM3_nhd.mjs} +7 -2
- package/dist/{node-yFFk626c.mjs → node-BDx8pmhq.mjs} +5 -5
- package/dist/{package-json-B0NuUWGd.mjs → package-json-Cx1osYo6.mjs} +1 -1
- package/dist/pages/client.d.mts +1 -1
- package/dist/pages/index.d.mts +1 -23
- package/dist/pages/index.mjs +5 -5
- package/dist/pages/islands-plugin.mjs +2 -2
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/{plugin-inference-CJxi_fWI.mjs → plugin-inference-DMeavIJ6.mjs} +4 -98
- package/dist/{prepare-C_cVurhP.mjs → prepare-DOBTY0o4.mjs} +10 -10
- package/dist/preset-BGrvB4Bl.mjs +539 -0
- package/dist/{project-cmd-DnU7u9QF.mjs → project-cmd-D_w-4w5B.mjs} +13 -9
- package/dist/{project-paths-tpdR1mJR.mjs → project-paths-BQd7OmIo.mjs} +1 -1
- package/dist/project-paths-GpziKeQQ.d.mts +25 -0
- package/dist/{project-tsconfig-D9uSVVpA.mjs → project-tsconfig-B-QtXjLQ.mjs} +2 -2
- package/dist/{protocol-6hTJ04T1.d.mts → protocol-Bnb0LFp3.d.mts} +1 -1
- package/dist/provision-BLrCEBbI.mjs +2557 -0
- package/dist/requests-B8sZxaFM.mjs +50 -0
- package/dist/{resolve-project-D2HI3TrG.mjs → resolve-project-BBMtLLV9.mjs} +1 -1
- package/dist/{rollback-Yh7bCKob.mjs → rollback-CkvTFXx5.mjs} +2 -2
- package/dist/{route-types-CfKfhbIg.mjs → route-types-COI2DsZv.mjs} +2 -2
- package/dist/{runner-h272wcPj.mjs → runner-kapo9aPs.mjs} +3 -3
- package/dist/{runner-pg-waxJOnBb.mjs → runner-pg-CHM76xuC.mjs} +1 -1
- package/dist/runtime/ai.mjs +113 -15
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/env-public.d.mts +1 -139
- package/dist/runtime/env-public.mjs +10 -93
- package/dist/runtime/env.d.mts +14 -1
- package/dist/runtime/env.mjs +24 -10
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/isr-cache.d.mts +207 -0
- package/dist/runtime/isr-cache.mjs +523 -0
- package/dist/runtime/isr.d.mts +4 -3
- package/dist/runtime/isr.mjs +44 -5
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/live.mjs +1 -1
- package/dist/runtime/sandbox.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws.d.mts +2 -2
- package/dist/{scan-Dp_Gyzs3.mjs → scan-DEwlM_Xy.mjs} +2 -2
- package/dist/{scan-i7Yz54fv.mjs → scan-DYXkrasO.mjs} +4 -4
- package/dist/{secret-u7FRvg8d.mjs → secret-Dt32J6RI.mjs} +3 -3
- package/dist/{skills-DsdNDtX3.mjs → skills-CLjN0uUO.mjs} +2 -2
- package/dist/{subcommand-prompt-DtES-oP6.mjs → subcommand-prompt-BzV8iQZo.mjs} +1 -1
- package/dist/sveltekit.mjs +1 -1
- package/dist/{validate-DT7nFMlf.mjs → validate-Cw_RLeTj.mjs} +1 -1
- package/dist/{yarn-pnp-CW8LB6g_.mjs → yarn-pnp-DJn3SAHF.mjs} +1 -1
- package/getting-started-prompt.txt +3 -1
- package/package.json +6 -3
- package/schema.json +11 -0
- package/skills/void/SKILL.md +34 -33
- package/skills/void/docs/guide/auth.md +8 -0
- package/skills/void/docs/guide/deployment.md +1 -1
- package/skills/void/docs/guide/env-vars.md +14 -6
- package/skills/void/docs/guide/queues.md +4 -0
- package/skills/void/docs/integrations/cloudflare.md +171 -5
- package/skills/void/docs/node_modules/void/AGENT_PROMPT.md +4 -0
- package/skills/void/docs/node_modules/void/{AGENTS.md → CLAUDE.md} +14 -0
- package/skills/void/docs/node_modules/void/README.md +1 -1
- package/skills/void/docs/node_modules/void/node_modules/@types/proper-lockfile/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathslash/README.md +64 -0
- package/skills/void/docs/node_modules/void/node_modules/pathslash/README.md +64 -0
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/CHANGELOG.md +108 -0
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/README.md +183 -0
- package/skills/void/docs/node_modules/void/skills/void/SKILL.md +34 -33
- package/skills/void/docs/node_modules/void/test/e2e/README.md +85 -0
- package/skills/void/docs/reference/cli.md +97 -14
- package/dist/deploy-C4PbkFyE.mjs +0 -3705
- package/dist/dotenv-D_UbC_vc.mjs +0 -173
- package/dist/env-raw-CoS20LHP.mjs +0 -32
- package/dist/env-validation-CeC2FL66.mjs +0 -163
- package/dist/pathe.M-eThtNZ-CQzLbt4c.mjs +0 -150
- package/dist/preset-CVvwCeIy.mjs +0 -208
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathe/README.md +0 -73
- package/skills/void/docs/node_modules/void/node_modules/pathe/README.md +0 -73
package/dist/dotenv-D_UbC_vc.mjs
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
//#region src/shared/dotenv.ts
|
|
3
|
-
/**
|
|
4
|
-
* Shared dotenv parser + variable expander used by every CLI path that reads
|
|
5
|
-
* `.env*` files (`void env check`, `void deploy`, `void init` scaffold
|
|
6
|
-
* inference). A single source of truth avoids the drift we hit when two
|
|
7
|
-
* hand-rolled parsers diverged on quoting / expansion semantics.
|
|
8
|
-
*
|
|
9
|
-
* Expansion supports `${VAR}` and `$VAR`, a `\$VAR` literal-escape, and
|
|
10
|
-
* transitive references across earlier entries in the same record. Cycles
|
|
11
|
-
* are detected and fall through to the raw literal rather than looping.
|
|
12
|
-
*
|
|
13
|
-
* Security note: expansion is deliberately scoped to the in-file record.
|
|
14
|
-
* We do NOT consult `process.env` the way `dotenv-expand` does — a shell
|
|
15
|
-
* env leaking into an `.env.example` via expansion would silently reveal
|
|
16
|
-
* developer machine state in committed output, and `void env check` /
|
|
17
|
-
* `void deploy` would then pass with values that aren't present in CI.
|
|
18
|
-
*
|
|
19
|
-
* The runtime path (Vite's own `loadEnv`) DOES consult `process.env` for
|
|
20
|
-
* expansion. That's a deliberate Vite choice; `filterLoadedEnv` strips
|
|
21
|
-
* shell pollution from the final worker vars so the two sides agree on
|
|
22
|
-
* the observable surface even when expansion sources differ.
|
|
23
|
-
*
|
|
24
|
-
* This module is a leaf — it must not import from `../log` or any non-leaf
|
|
25
|
-
* module so that the prerender subprocess's worker bundle doesn't pick up
|
|
26
|
-
* unwanted transitive dependencies. Warnings are surfaced through the
|
|
27
|
-
* `onWarn` callback and left for the caller to route.
|
|
28
|
-
*/
|
|
29
|
-
/** Valid dotenv key — ASCII letter/underscore followed by letters/digits/underscore. */
|
|
30
|
-
const VALID_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
31
|
-
/**
|
|
32
|
-
* Parse a single `KEY=VALUE` line into `{ key, value }`, stripping matching
|
|
33
|
-
* single/double quotes around the value. Returns `null` for blanks, comments,
|
|
34
|
-
* and non-assignment lines.
|
|
35
|
-
*/
|
|
36
|
-
function parseDotenvLine(line) {
|
|
37
|
-
const trimmed = line.trim();
|
|
38
|
-
if (!trimmed || trimmed.startsWith("#")) return null;
|
|
39
|
-
const equalsIndex = trimmed.indexOf("=");
|
|
40
|
-
if (equalsIndex === -1) return null;
|
|
41
|
-
const key = trimmed.slice(0, equalsIndex).trim();
|
|
42
|
-
let value = trimmed.slice(equalsIndex + 1).trim();
|
|
43
|
-
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
44
|
-
return {
|
|
45
|
-
key,
|
|
46
|
-
value
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Parse the raw contents of a dotenv file into a record, optionally
|
|
51
|
-
* expanding `${VAR}` / `$VAR` references against earlier entries.
|
|
52
|
-
*/
|
|
53
|
-
function parseDotenv(content, options = {}) {
|
|
54
|
-
const { expand: shouldExpand = true, skipInvalidKeys = true, onWarn } = options;
|
|
55
|
-
const env = {};
|
|
56
|
-
for (const line of content.split("\n")) {
|
|
57
|
-
const parsed = parseDotenvLine(line);
|
|
58
|
-
if (!parsed) continue;
|
|
59
|
-
if (!VALID_KEY.test(parsed.key)) {
|
|
60
|
-
if (skipInvalidKeys) continue;
|
|
61
|
-
throw new Error(`dotenv: Invalid key '${parsed.key}'.`);
|
|
62
|
-
}
|
|
63
|
-
env[parsed.key] = parsed.value;
|
|
64
|
-
}
|
|
65
|
-
return shouldExpand ? expandDotenv(env, { onWarn }) : env;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Read and parse a dotenv file. Returns `{}` when the file is missing so
|
|
69
|
-
* callers can treat "no file" and "empty file" identically.
|
|
70
|
-
*/
|
|
71
|
-
function parseDotenvFile(filePath, options = {}) {
|
|
72
|
-
if (!existsSync(filePath)) return {};
|
|
73
|
-
return parseDotenv(readFileSync(filePath, "utf-8"), options);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Expand `${VAR}` / `$VAR` references in every value of a record against
|
|
77
|
-
* the other entries in that same record. Matches the surface of
|
|
78
|
-
* `dotenv-expand` minus the `process.env` fallback.
|
|
79
|
-
*
|
|
80
|
-
* Semantics:
|
|
81
|
-
* - `${VAR}` and `$VAR` both resolve (bare form stops at the first
|
|
82
|
-
* non-identifier character).
|
|
83
|
-
* - `\$VAR` stays literal; the backslash is consumed.
|
|
84
|
-
* - Nested refs resolve transitively — `A=${B}`, `B=${C}`, `C=v` → `A=v`.
|
|
85
|
-
* - Cycles are detected; the offending value keeps its raw literal and
|
|
86
|
-
* `onWarn` fires once per cycle seen.
|
|
87
|
-
* - Missing refs expand to the empty string, matching dotenv-expand.
|
|
88
|
-
*
|
|
89
|
-
* The input record is not mutated; a fresh object is returned.
|
|
90
|
-
*/
|
|
91
|
-
function expandDotenv(input, options = {}) {
|
|
92
|
-
const out = {};
|
|
93
|
-
const resolving = /* @__PURE__ */ new Set();
|
|
94
|
-
const warned = /* @__PURE__ */ new Set();
|
|
95
|
-
function resolveKey(key) {
|
|
96
|
-
if (!(key in input)) return "";
|
|
97
|
-
if (key in out) return out[key];
|
|
98
|
-
if (resolving.has(key)) {
|
|
99
|
-
if (!warned.has(key) && options.onWarn) {
|
|
100
|
-
warned.add(key);
|
|
101
|
-
options.onWarn(`dotenv expansion cycle detected at "${key}" — leaving raw value in place`);
|
|
102
|
-
}
|
|
103
|
-
return input[key];
|
|
104
|
-
}
|
|
105
|
-
resolving.add(key);
|
|
106
|
-
const expanded = expandValue(input[key], resolveKey);
|
|
107
|
-
resolving.delete(key);
|
|
108
|
-
out[key] = expanded;
|
|
109
|
-
return expanded;
|
|
110
|
-
}
|
|
111
|
-
for (const key of Object.keys(input)) resolveKey(key);
|
|
112
|
-
return out;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Expand a single value string. `resolve` returns the fully-expanded value
|
|
116
|
-
* for a referenced key (or `''` when missing). Backslash-escapes (`\$VAR`,
|
|
117
|
-
* `\${VAR}`) keep the `$...` literal and consume the backslash.
|
|
118
|
-
*/
|
|
119
|
-
function expandValue(value, resolve) {
|
|
120
|
-
let result = "";
|
|
121
|
-
let cursor = 0;
|
|
122
|
-
while (cursor < value.length) {
|
|
123
|
-
const character = value[cursor];
|
|
124
|
-
if (character === "\\" && cursor + 1 < value.length && value[cursor + 1] === "$") {
|
|
125
|
-
result += "$";
|
|
126
|
-
cursor += 2;
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (character !== "$") {
|
|
130
|
-
result += character;
|
|
131
|
-
cursor++;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
const next = value[cursor + 1];
|
|
135
|
-
if (next === "{") {
|
|
136
|
-
const endIndex = value.indexOf("}", cursor + 2);
|
|
137
|
-
if (endIndex === -1) {
|
|
138
|
-
result += character;
|
|
139
|
-
cursor++;
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
const key = value.slice(cursor + 2, endIndex);
|
|
143
|
-
if (VALID_KEY.test(key)) result += resolve(key);
|
|
144
|
-
else result += value.slice(cursor, endIndex + 1);
|
|
145
|
-
cursor = endIndex + 1;
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
if (next && /[A-Za-z_]/.test(next)) {
|
|
149
|
-
let keyEndIndex = cursor + 1;
|
|
150
|
-
while (keyEndIndex < value.length && /[A-Za-z0-9_]/.test(value[keyEndIndex])) keyEndIndex++;
|
|
151
|
-
const key = value.slice(cursor + 1, keyEndIndex);
|
|
152
|
-
result += resolve(key);
|
|
153
|
-
cursor = keyEndIndex;
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
result += character;
|
|
157
|
-
cursor++;
|
|
158
|
-
}
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Merge multiple parsed dotenv records with later-entries-win semantics,
|
|
163
|
-
* then expand across the combined set. This is the recommended path for
|
|
164
|
-
* callers reading multiple `.env*` files (Vite-style precedence), since
|
|
165
|
-
* expansion sees every earlier file's keys at once.
|
|
166
|
-
*/
|
|
167
|
-
function mergeAndExpand(records, options = {}) {
|
|
168
|
-
const merged = {};
|
|
169
|
-
for (const record of records) Object.assign(merged, record);
|
|
170
|
-
return expandDotenv(merged, options);
|
|
171
|
-
}
|
|
172
|
-
//#endregion
|
|
173
|
-
export { mergeAndExpand as n, parseDotenvFile as r, expandDotenv as t };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
//#region src/runtime/env-raw.ts
|
|
3
|
-
/**
|
|
4
|
-
* Raw runtime env resolution — framework-internal only.
|
|
5
|
-
*
|
|
6
|
-
* This module is NOT exported in package.json, so it cannot be imported
|
|
7
|
-
* via "void/..." subpaths. Only framework modules using relative imports
|
|
8
|
-
* (isr.ts, ai.ts, env.ts) can access it.
|
|
9
|
-
*/
|
|
10
|
-
/** Prefixes for platform-internal bindings that must be hidden from user code. */
|
|
11
|
-
const INTERNAL_BINDING_PREFIXES = ["__VOID_", "__PROJECT_"];
|
|
12
|
-
const envContext = new AsyncLocalStorage();
|
|
13
|
-
let cloudflareEnv;
|
|
14
|
-
if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") import("cloudflare:workers").then((mod) => {
|
|
15
|
-
cloudflareEnv = asEnv(mod.env) ?? void 0;
|
|
16
|
-
}).catch(() => {});
|
|
17
|
-
function asEnv(value) {
|
|
18
|
-
if (typeof value !== "object" || value === null) return null;
|
|
19
|
-
if ("then" in value && typeof value.then === "function") return null;
|
|
20
|
-
return value;
|
|
21
|
-
}
|
|
22
|
-
function getNuxtEnv() {
|
|
23
|
-
return asEnv(globalThis.__env__);
|
|
24
|
-
}
|
|
25
|
-
/** Resolve raw env from AsyncLocalStorage, Nuxt globals, or CF module env. */
|
|
26
|
-
function getRawRuntimeEnv() {
|
|
27
|
-
return envContext.getStore() ?? getNuxtEnv() ?? cloudflareEnv ?? (() => {
|
|
28
|
-
throw new Error("env: Cloudflare env is unavailable. Use void runtime bindings inside Nuxt/SvelteKit/Analog server request handlers or Worker handlers.");
|
|
29
|
-
})();
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { getRawRuntimeEnv as i, asEnv as n, envContext as r, INTERNAL_BINDING_PREFIXES as t };
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { a as join } from "./pathe.M-eThtNZ-CQzLbt4c.mjs";
|
|
2
|
-
import { i as voidWarn } from "./log-ChfPKsVd.mjs";
|
|
3
|
-
import { n as mergeAndExpand, r as parseDotenvFile } from "./dotenv-D_UbC_vc.mjs";
|
|
4
|
-
import { t as findEnvFile } from "./env-types-D51bnR-c.mjs";
|
|
5
|
-
import { pathToFileURL } from "node:url";
|
|
6
|
-
//#region src/host/load-user-env.ts
|
|
7
|
-
/**
|
|
8
|
-
* Loader for the user's `env.ts`.
|
|
9
|
-
*
|
|
10
|
-
* Uses Node's native `import()` (type-stripping is on by default in the
|
|
11
|
-
* supported Node version), so only relative imports and bare package
|
|
12
|
-
* specifiers resolve. tsconfig path aliases (`@/foo`, `~/foo`) are NOT
|
|
13
|
-
* supported — if the user writes one, we detect the resulting resolution
|
|
14
|
-
* error and re-throw with guidance pointing at the offending specifier.
|
|
15
|
-
*
|
|
16
|
-
* Used by:
|
|
17
|
-
* - `plugin-env-schema.ts` (dev plugin, HMR re-imports)
|
|
18
|
-
* - `cli/env-validation.ts` (deploy + `void env check`)
|
|
19
|
-
*
|
|
20
|
-
* Side-effect contract: loading the file evaluates the user's `defineEnv`
|
|
21
|
-
* call, which registers the schema in the singleton state in
|
|
22
|
-
* `runtime/env-public.ts`. Callers read the result from there.
|
|
23
|
-
*
|
|
24
|
-
* Node-only (lives under `host/`). Must not be imported from anything
|
|
25
|
-
* that ships in worker bundles.
|
|
26
|
-
*/
|
|
27
|
-
let loadCounter = 0;
|
|
28
|
-
/**
|
|
29
|
-
* Returns the specifier from a Node resolution error if the error looks
|
|
30
|
-
* like one — otherwise `null`. Both `ERR_MODULE_NOT_FOUND` and
|
|
31
|
-
* `ERR_UNSUPPORTED_DIR_IMPORT` have the specifier embedded in the message.
|
|
32
|
-
*/
|
|
33
|
-
function extractFailedSpecifier(err) {
|
|
34
|
-
if (!(err instanceof Error)) return null;
|
|
35
|
-
const code = err.code;
|
|
36
|
-
if (code !== "ERR_MODULE_NOT_FOUND" && code !== "ERR_PACKAGE_PATH_NOT_EXPORTED") return null;
|
|
37
|
-
const match = /Cannot find (?:package|module) '([^']+)'/.exec(err.message);
|
|
38
|
-
return match ? match[1] ?? null : null;
|
|
39
|
-
}
|
|
40
|
-
/** A specifier is alias-shaped if it isn't relative, absolute, a node: URL, or a valid bare package name. */
|
|
41
|
-
function looksLikeAlias(specifier) {
|
|
42
|
-
if (specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || specifier.startsWith("node:") || specifier.startsWith("file:")) return false;
|
|
43
|
-
if (specifier.startsWith("@")) return !/^@[^/]+\/[^/]+/.test(specifier);
|
|
44
|
-
return specifier.startsWith("~") || specifier.startsWith("#");
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Load the user's env.ts via native `import()`. The URL gets a cache-busting
|
|
48
|
-
* query param so HMR re-imports re-evaluate the file.
|
|
49
|
-
*
|
|
50
|
-
* On resolution failures, wraps the error with the source file path, and if
|
|
51
|
-
* the failed specifier looks like a tsconfig path alias, appends guidance
|
|
52
|
-
* explaining that env.ts doesn't resolve aliases.
|
|
53
|
-
*/
|
|
54
|
-
async function loadUserEnvFile(envFile) {
|
|
55
|
-
const url = pathToFileURL(envFile).href + `?t=${Date.now()}-${++loadCounter}`;
|
|
56
|
-
try {
|
|
57
|
-
await import(
|
|
58
|
-
/* @vite-ignore */
|
|
59
|
-
url
|
|
60
|
-
);
|
|
61
|
-
} catch (err) {
|
|
62
|
-
const specifier = extractFailedSpecifier(err);
|
|
63
|
-
const base = `env: Failed to load '${envFile}': '${err.message}'.`;
|
|
64
|
-
if (specifier && looksLikeAlias(specifier)) throw new Error(`${base}\n\nHint: '${specifier}' looks like a tsconfig path alias. env.ts is loaded directly by Node and does not resolve tsconfig "paths" — use a relative import (e.g. "./shared/...") instead.`);
|
|
65
|
-
throw new Error(base);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
//#endregion
|
|
69
|
-
//#region src/cli/env-validation.ts
|
|
70
|
-
/**
|
|
71
|
-
* Shared env-schema validation for CLI commands.
|
|
72
|
-
*
|
|
73
|
-
* Loads the user's `env.ts` (which calls `defineEnv` as a side effect),
|
|
74
|
-
* collects sources of env values (`.env*` files, remote secrets), and
|
|
75
|
-
* validates each declared key against the registered schema.
|
|
76
|
-
*
|
|
77
|
-
* Used by both `void deploy` (hard error on missing prod env) and
|
|
78
|
-
* `void env check` (CI/pre-push validation).
|
|
79
|
-
*/
|
|
80
|
-
/**
|
|
81
|
-
* After the user's env.ts has been imported (via `validateProdEnv` or
|
|
82
|
-
* `loadSchema`), read the registered schema's `.default(value)` entries.
|
|
83
|
-
* Returns `{}` if no schema was registered.
|
|
84
|
-
*/
|
|
85
|
-
async function getDeployEnvDefaults(root) {
|
|
86
|
-
const envFile = findEnvFile(root);
|
|
87
|
-
if (!envFile) return {};
|
|
88
|
-
const mod = await loadSchema(envFile);
|
|
89
|
-
if (!mod) return {};
|
|
90
|
-
return mod._getSchemaDefaults();
|
|
91
|
-
}
|
|
92
|
-
/** Load the registered schema by importing the user's env.ts. */
|
|
93
|
-
async function loadSchema(envFile) {
|
|
94
|
-
await loadUserEnvFile(envFile);
|
|
95
|
-
const mod = await import("./runtime/env-public.mjs");
|
|
96
|
-
if (!mod._hasRegisteredSchema()) return null;
|
|
97
|
-
return mod;
|
|
98
|
-
}
|
|
99
|
-
function emptyReport() {
|
|
100
|
-
return {
|
|
101
|
-
valid: true,
|
|
102
|
-
missing: [],
|
|
103
|
-
invalid: [],
|
|
104
|
-
values: /* @__PURE__ */ new Map()
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Validate the user's env schema against the union of .env files and
|
|
109
|
-
* remote secret names. Remote secrets are treated as "present" (we can't
|
|
110
|
-
* fetch their values), which is sufficient for the missing-key check.
|
|
111
|
-
*/
|
|
112
|
-
async function validateProdEnv(root, options) {
|
|
113
|
-
const envFile = findEnvFile(root);
|
|
114
|
-
if (!envFile) return {
|
|
115
|
-
hasSchema: false,
|
|
116
|
-
report: emptyReport()
|
|
117
|
-
};
|
|
118
|
-
const mod = await loadSchema(envFile);
|
|
119
|
-
if (!mod) return {
|
|
120
|
-
hasSchema: false,
|
|
121
|
-
report: emptyReport()
|
|
122
|
-
};
|
|
123
|
-
const merged = mergeAndExpand((options.productionOnly ? [".env", ".env.production"] : [
|
|
124
|
-
".env",
|
|
125
|
-
".env.local",
|
|
126
|
-
".env.production",
|
|
127
|
-
".env.production.local"
|
|
128
|
-
]).map((file) => parseDotenvFile(join(root, file), { expand: false })), { onWarn: (msg) => voidWarn(msg) });
|
|
129
|
-
const report = await mod.validateAllEnv(merged);
|
|
130
|
-
const remoteSet = new Set(options.remoteSecrets ?? []);
|
|
131
|
-
if (remoteSet.size > 0 && report.missing.length > 0) {
|
|
132
|
-
report.missing = report.missing.filter((key) => !remoteSet.has(key));
|
|
133
|
-
if (report.missing.length === 0 && report.invalid.length === 0) report.valid = true;
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
hasSchema: true,
|
|
137
|
-
report
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
/** Format an EnvValidationReport into a human-readable multi-line string. */
|
|
141
|
-
function formatEnvReport(report) {
|
|
142
|
-
const lines = [];
|
|
143
|
-
if (report.missing.length > 0) {
|
|
144
|
-
lines.push("Missing required env vars:");
|
|
145
|
-
for (const key of report.missing) lines.push(` • ${key}`);
|
|
146
|
-
}
|
|
147
|
-
if (report.invalid.length > 0) {
|
|
148
|
-
if (lines.length > 0) lines.push("");
|
|
149
|
-
lines.push("Invalid env vars:");
|
|
150
|
-
for (const { key, messages } of report.invalid) lines.push(` • ${key}: ${messages.join("; ")}`);
|
|
151
|
-
}
|
|
152
|
-
return lines.join("\n");
|
|
153
|
-
}
|
|
154
|
-
/** Convenience: fetch remote secret names from the platform. */
|
|
155
|
-
async function fetchRemoteSecretNames(client, projectId) {
|
|
156
|
-
try {
|
|
157
|
-
return (await client.listSecrets(projectId)).map((s) => s.name);
|
|
158
|
-
} catch {
|
|
159
|
-
return [];
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
//#endregion
|
|
163
|
-
export { loadUserEnvFile as a, validateProdEnv as i, formatEnvReport as n, getDeployEnvDefaults as r, fetchRemoteSecretNames as t };
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
|
|
2
|
-
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
3
|
-
function normalizeWindowsPath(input = "") {
|
|
4
|
-
if (!input) return input;
|
|
5
|
-
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
6
|
-
}
|
|
7
|
-
const _UNC_REGEX = /^[/\\]{2}/;
|
|
8
|
-
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
9
|
-
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
10
|
-
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
11
|
-
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
|
|
12
|
-
const normalize = function(path) {
|
|
13
|
-
if (path.length === 0) return ".";
|
|
14
|
-
path = normalizeWindowsPath(path);
|
|
15
|
-
const isUNCPath = path.match(_UNC_REGEX);
|
|
16
|
-
const isPathAbsolute = isAbsolute(path);
|
|
17
|
-
const trailingSeparator = path[path.length - 1] === "/";
|
|
18
|
-
path = normalizeString(path, !isPathAbsolute);
|
|
19
|
-
if (path.length === 0) {
|
|
20
|
-
if (isPathAbsolute) return "/";
|
|
21
|
-
return trailingSeparator ? "./" : ".";
|
|
22
|
-
}
|
|
23
|
-
if (trailingSeparator) path += "/";
|
|
24
|
-
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
25
|
-
if (isUNCPath) {
|
|
26
|
-
if (!isPathAbsolute) return `//./${path}`;
|
|
27
|
-
return `//${path}`;
|
|
28
|
-
}
|
|
29
|
-
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
30
|
-
};
|
|
31
|
-
const join = function(...segments) {
|
|
32
|
-
let path = "";
|
|
33
|
-
for (const seg of segments) {
|
|
34
|
-
if (!seg) continue;
|
|
35
|
-
if (path.length > 0) {
|
|
36
|
-
const pathTrailing = path[path.length - 1] === "/";
|
|
37
|
-
const segLeading = seg[0] === "/";
|
|
38
|
-
if (pathTrailing && segLeading) path += seg.slice(1);
|
|
39
|
-
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
40
|
-
} else path += seg;
|
|
41
|
-
}
|
|
42
|
-
return normalize(path);
|
|
43
|
-
};
|
|
44
|
-
function cwd() {
|
|
45
|
-
if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
|
|
46
|
-
return "/";
|
|
47
|
-
}
|
|
48
|
-
const resolve = function(...arguments_) {
|
|
49
|
-
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
50
|
-
let resolvedPath = "";
|
|
51
|
-
let resolvedAbsolute = false;
|
|
52
|
-
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
53
|
-
const path = index >= 0 ? arguments_[index] : cwd();
|
|
54
|
-
if (!path || path.length === 0) continue;
|
|
55
|
-
resolvedPath = `${path}/${resolvedPath}`;
|
|
56
|
-
resolvedAbsolute = isAbsolute(path);
|
|
57
|
-
}
|
|
58
|
-
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
59
|
-
if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
|
|
60
|
-
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
61
|
-
};
|
|
62
|
-
function normalizeString(path, allowAboveRoot) {
|
|
63
|
-
let res = "";
|
|
64
|
-
let lastSegmentLength = 0;
|
|
65
|
-
let lastSlash = -1;
|
|
66
|
-
let dots = 0;
|
|
67
|
-
let char = null;
|
|
68
|
-
for (let index = 0; index <= path.length; ++index) {
|
|
69
|
-
if (index < path.length) char = path[index];
|
|
70
|
-
else if (char === "/") break;
|
|
71
|
-
else char = "/";
|
|
72
|
-
if (char === "/") {
|
|
73
|
-
if (lastSlash === index - 1 || dots === 1);
|
|
74
|
-
else if (dots === 2) {
|
|
75
|
-
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
76
|
-
if (res.length > 2) {
|
|
77
|
-
const lastSlashIndex = res.lastIndexOf("/");
|
|
78
|
-
if (lastSlashIndex === -1) {
|
|
79
|
-
res = "";
|
|
80
|
-
lastSegmentLength = 0;
|
|
81
|
-
} else {
|
|
82
|
-
res = res.slice(0, lastSlashIndex);
|
|
83
|
-
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
84
|
-
}
|
|
85
|
-
lastSlash = index;
|
|
86
|
-
dots = 0;
|
|
87
|
-
continue;
|
|
88
|
-
} else if (res.length > 0) {
|
|
89
|
-
res = "";
|
|
90
|
-
lastSegmentLength = 0;
|
|
91
|
-
lastSlash = index;
|
|
92
|
-
dots = 0;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (allowAboveRoot) {
|
|
97
|
-
res += res.length > 0 ? "/.." : "..";
|
|
98
|
-
lastSegmentLength = 2;
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`;
|
|
102
|
-
else res = path.slice(lastSlash + 1, index);
|
|
103
|
-
lastSegmentLength = index - lastSlash - 1;
|
|
104
|
-
}
|
|
105
|
-
lastSlash = index;
|
|
106
|
-
dots = 0;
|
|
107
|
-
} else if (char === "." && dots !== -1) ++dots;
|
|
108
|
-
else dots = -1;
|
|
109
|
-
}
|
|
110
|
-
return res;
|
|
111
|
-
}
|
|
112
|
-
const isAbsolute = function(p) {
|
|
113
|
-
return _IS_ABSOLUTE_RE.test(p);
|
|
114
|
-
};
|
|
115
|
-
const extname = function(p) {
|
|
116
|
-
if (p === "..") return "";
|
|
117
|
-
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
|
|
118
|
-
return match && match[1] || "";
|
|
119
|
-
};
|
|
120
|
-
const relative = function(from, to) {
|
|
121
|
-
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
122
|
-
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
123
|
-
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) return _to.join("/");
|
|
124
|
-
const _fromCopy = [..._from];
|
|
125
|
-
for (const segment of _fromCopy) {
|
|
126
|
-
if (_to[0] !== segment) break;
|
|
127
|
-
_from.shift();
|
|
128
|
-
_to.shift();
|
|
129
|
-
}
|
|
130
|
-
return [..._from.map(() => ".."), ..._to].join("/");
|
|
131
|
-
};
|
|
132
|
-
const dirname = function(p) {
|
|
133
|
-
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
134
|
-
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
|
|
135
|
-
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
136
|
-
};
|
|
137
|
-
const basename = function(p, extension) {
|
|
138
|
-
const segments = normalizeWindowsPath(p).split("/");
|
|
139
|
-
let lastSegment = "";
|
|
140
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
141
|
-
const val = segments[i];
|
|
142
|
-
if (val) {
|
|
143
|
-
lastSegment = val;
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
148
|
-
};
|
|
149
|
-
//#endregion
|
|
150
|
-
export { join as a, resolve as c, isAbsolute as i, dirname as n, normalize as o, extname as r, relative as s, basename as t };
|