env-runner 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -9
- package/dist/_chunks/common-base-runner.d.mts +16 -47
- package/dist/_chunks/common-base-runner.mjs +4 -1
- package/dist/_chunks/common-runtime-deps.d.mts +7 -30
- package/dist/_chunks/deno-process-runner.mjs +14 -36
- package/dist/_chunks/miniflare-runner.d.mts +45 -105
- package/dist/_chunks/miniflare-runner.mjs +571 -61
- package/dist/_chunks/netlify-runner.d.mts +3 -21
- package/dist/_chunks/types.d.mts +2 -11
- package/dist/_chunks/vercel-runner.mjs +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +17 -68
- package/dist/runners/deno-process/worker.mjs +9 -31
- package/dist/runners/vercel/queue-dev.d.mts +9 -45
- package/dist/vite.d.mts +2 -12
- package/package.json +6 -6
|
@@ -7,14 +7,17 @@ import { init as init$1, parse as parse$1 } from "./libs/es-module-lexer.mjs";
|
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { proxyUpgrade } from "httpxy";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
-
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
10
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
12
12
|
import { resolveModulePath } from "exsolve";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
|
+
import { parseEnv } from "node:util";
|
|
14
15
|
const IPC_PATH = "/__env_runner_ipc";
|
|
15
16
|
const IPC_BINDING = "__ENV_RUNNER_IPC";
|
|
16
17
|
const UNSAFE_EVAL_BINDING = "__ENV_RUNNER_UNSAFE_EVAL__";
|
|
17
18
|
function generateWrapper(entryPath, opts) {
|
|
19
|
+
const processShim = opts?.nodeCompat === false ? "" : `import __process from "node:process";
|
|
20
|
+
if (!globalThis.process) { globalThis.process = __process; }`;
|
|
18
21
|
const staticReExport = opts?.dynamicOnly ? "" : `export * from ${JSON.stringify(entryPath)};`;
|
|
19
22
|
const explicitExports = opts?.dynamicOnly && opts.exports?.length ? opts.exports.map((name) => `export { ${name} } from ${JSON.stringify(entryPath)};`).join("\n") : "";
|
|
20
23
|
const fetchBody = opts?.captureErrors ?? true ? `try {
|
|
@@ -31,8 +34,7 @@ function generateWrapper(entryPath, opts) {
|
|
|
31
34
|
headers: { "Content-Type": "application/json", "X-Env-Runner-Error": "1" },
|
|
32
35
|
});
|
|
33
36
|
}` : `return __server.fetch(request, env, ctx);`;
|
|
34
|
-
return
|
|
35
|
-
if (!globalThis.process) { globalThis.process = __process; }
|
|
37
|
+
return `${processShim}
|
|
36
38
|
${staticReExport}
|
|
37
39
|
${explicitExports}
|
|
38
40
|
|
|
@@ -257,6 +259,67 @@ export default {
|
|
|
257
259
|
};
|
|
258
260
|
`;
|
|
259
261
|
}
|
|
262
|
+
function expandDotenv(parsed, processEnv) {
|
|
263
|
+
const running = {};
|
|
264
|
+
for (const [key, raw] of Object.entries(parsed)) running[key] = processEnv[key] = (processEnv[key] && processEnv[key] !== raw ? processEnv[key] : expandDotenvValue(raw, processEnv, running)).replace(/\\\$/g, "$");
|
|
265
|
+
return processEnv;
|
|
266
|
+
}
|
|
267
|
+
function expandDotenvValue(value, processEnv, running) {
|
|
268
|
+
const env = {
|
|
269
|
+
...running,
|
|
270
|
+
...processEnv
|
|
271
|
+
};
|
|
272
|
+
const regex = /(?<!\\)\$\{([^{}]+)\}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
273
|
+
const seen = /* @__PURE__ */ new Set();
|
|
274
|
+
let result = value;
|
|
275
|
+
let match;
|
|
276
|
+
while ((match = regex.exec(result)) !== null) {
|
|
277
|
+
seen.add(result);
|
|
278
|
+
const [template, braced, unbraced] = match;
|
|
279
|
+
const expression = braced || unbraced;
|
|
280
|
+
const splitter = expression.match(/(:\+|\+|:-|-)/)?.[0];
|
|
281
|
+
const parts = splitter ? expression.split(splitter) : [expression];
|
|
282
|
+
const key = parts.shift();
|
|
283
|
+
let replacement;
|
|
284
|
+
if (splitter === ":+" || splitter === "+") replacement = env[key] ? parts.join(splitter) : "";
|
|
285
|
+
else {
|
|
286
|
+
const found = env[key];
|
|
287
|
+
replacement = found && !seen.has(found) ? found : parts.join(splitter ?? "");
|
|
288
|
+
}
|
|
289
|
+
result = result.replace(template, replacement);
|
|
290
|
+
if (result === running[key]) break;
|
|
291
|
+
regex.lastIndex = 0;
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
function readDotenvFile(path) {
|
|
296
|
+
return existsSync(path) ? parseEnv(readFileSync(path, "utf8")) : void 0;
|
|
297
|
+
}
|
|
298
|
+
function booleanEnv(name, defaultValue) {
|
|
299
|
+
const value = process.env[name]?.toLowerCase();
|
|
300
|
+
return value === "true" ? true : value === "false" ? false : defaultValue;
|
|
301
|
+
}
|
|
302
|
+
function loadDevVars(opts) {
|
|
303
|
+
const { configDir, env, envFiles } = opts;
|
|
304
|
+
if (!envFiles?.length) {
|
|
305
|
+
const devVars = resolve(configDir, ".dev.vars");
|
|
306
|
+
const loaded = env !== void 0 && readDotenvFile(`${devVars}.${env}`) || readDotenvFile(devVars);
|
|
307
|
+
if (loaded) return loaded;
|
|
308
|
+
}
|
|
309
|
+
if (!booleanEnv("CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV", true)) return;
|
|
310
|
+
const files = envFiles ?? [
|
|
311
|
+
".env",
|
|
312
|
+
".env.local",
|
|
313
|
+
...env ? [`.env.${env}`, `.env.${env}.local`] : []
|
|
314
|
+
];
|
|
315
|
+
const parsed = {};
|
|
316
|
+
for (const file of files) Object.assign(parsed, readDotenvFile(resolve(configDir, file)));
|
|
317
|
+
const processEnv = {};
|
|
318
|
+
if (opts.hasSecrets || booleanEnv("CLOUDFLARE_INCLUDE_PROCESS_ENV", false)) {
|
|
319
|
+
for (const [key, value] of Object.entries(process.env)) if (typeof value === "string") processEnv[key] = value;
|
|
320
|
+
}
|
|
321
|
+
return expandDotenv(parsed, processEnv);
|
|
322
|
+
}
|
|
260
323
|
const WRANGLER_CONFIG_FILENAMES = [
|
|
261
324
|
"wrangler.json",
|
|
262
325
|
"wrangler.jsonc",
|
|
@@ -274,45 +337,143 @@ const WRANGLER_OPTION_DENYLIST = /* @__PURE__ */ new Set([
|
|
|
274
337
|
"unsafeModuleFallbackService",
|
|
275
338
|
"unsafeUseModuleFallbackService"
|
|
276
339
|
]);
|
|
340
|
+
const WRANGLER_OPTION_DROPLIST = /* @__PURE__ */ new Set([
|
|
341
|
+
"assets",
|
|
342
|
+
"serviceBindings",
|
|
343
|
+
"workflows",
|
|
344
|
+
"queueConsumers",
|
|
345
|
+
"tails",
|
|
346
|
+
"streamingTails"
|
|
347
|
+
]);
|
|
348
|
+
const WRANGLER_DROPPED_OPTION_NAMES = {
|
|
349
|
+
assets: "assets",
|
|
350
|
+
serviceBindings: "services",
|
|
351
|
+
workflows: "workflows",
|
|
352
|
+
queueConsumers: "queues.consumers",
|
|
353
|
+
tails: "tail_consumers",
|
|
354
|
+
streamingTails: "streaming_tail_consumers",
|
|
355
|
+
durableObjects: "durable_objects"
|
|
356
|
+
};
|
|
357
|
+
function addDropped(dropped, name, details) {
|
|
358
|
+
let set = dropped.get(name);
|
|
359
|
+
if (!set) {
|
|
360
|
+
set = /* @__PURE__ */ new Set();
|
|
361
|
+
dropped.set(name, set);
|
|
362
|
+
}
|
|
363
|
+
for (const detail of details) set.add(detail);
|
|
364
|
+
}
|
|
365
|
+
function warnDroppedWranglerOptions(dropped) {
|
|
366
|
+
if (dropped.size === 0) return;
|
|
367
|
+
const list = [...dropped].map(([name, details]) => details.size > 0 ? `${name} (${[...details].join(", ")})` : name).join(", ");
|
|
368
|
+
console.warn(`[env-runner] wrangler config options not supported by the miniflare dev runner were ignored: ${list}; pass them via miniflareOptions to opt in.`);
|
|
369
|
+
}
|
|
277
370
|
function isPlainObject(value) {
|
|
278
371
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
279
372
|
}
|
|
280
373
|
function isInlineWranglerConfig(opt) {
|
|
281
374
|
return isPlainObject(opt);
|
|
282
375
|
}
|
|
283
|
-
async function loadWranglerConfig(
|
|
284
|
-
|
|
376
|
+
async function loadWranglerConfig(opts) {
|
|
377
|
+
const { wrangler: opt, env, entryPath, wranglerModule, envFiles } = opts;
|
|
378
|
+
if (!opt) return {};
|
|
285
379
|
const inline = isInlineWranglerConfig(opt) ? opt : void 0;
|
|
286
380
|
let configPath;
|
|
287
|
-
|
|
288
|
-
|
|
381
|
+
const explicitPath = typeof opt === "string" ? opt : opts.configPath;
|
|
382
|
+
if (explicitPath) {
|
|
383
|
+
configPath = resolve(explicitPath);
|
|
289
384
|
if (!existsSync(configPath)) {
|
|
290
385
|
console.warn(`[env-runner] wrangler config requested but not found at "${configPath}"`);
|
|
291
|
-
return;
|
|
386
|
+
if (!inline) return {};
|
|
387
|
+
configPath = void 0;
|
|
292
388
|
}
|
|
293
|
-
} else
|
|
389
|
+
} else {
|
|
294
390
|
configPath = findWranglerConfig(entryPath);
|
|
295
|
-
if (!configPath) {
|
|
296
|
-
console.warn("[env-runner] wrangler config requested but none found
|
|
297
|
-
return;
|
|
391
|
+
if (!configPath && !inline) {
|
|
392
|
+
console.warn("[env-runner] wrangler config requested but none found (searched the entry's directory, then from the cwd up to the filesystem root)");
|
|
393
|
+
return {};
|
|
298
394
|
}
|
|
299
|
-
}
|
|
395
|
+
}
|
|
300
396
|
const wrangler = await resolveRuntimeDep({
|
|
301
397
|
name: "wrangler",
|
|
302
398
|
option: "wranglerModule",
|
|
303
399
|
value: wranglerModule
|
|
304
400
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
401
|
+
const dropped = /* @__PURE__ */ new Map();
|
|
402
|
+
if (!wrangler?.unstable_readConfig || !wrangler.unstable_getMiniflareWorkerOptions) {
|
|
403
|
+
const unsupported = /* @__PURE__ */ new Map();
|
|
404
|
+
const file = configPath ? readWranglerConfigMinimal(configPath, env) : void 0;
|
|
405
|
+
const inlineConfig = inline ? applyWranglerEnv(inline, env) : void 0;
|
|
406
|
+
let options = mergeWranglerMiniflareOptions(file && (mapWranglerConfigToMiniflare(file.config, dropped, unsupported) ?? {}), inlineConfig && mapWranglerConfigToMiniflare(inlineConfig, dropped, unsupported));
|
|
407
|
+
if (file || inlineConfig) options = applyMinimalDevVars(options, [file?.config, inlineConfig], {
|
|
408
|
+
configDir: configPath ? dirname(configPath) : process.cwd(),
|
|
409
|
+
env,
|
|
410
|
+
envFiles
|
|
411
|
+
});
|
|
412
|
+
filterLocalDurableObjects(options, dropped, (inline && wranglerWorkerName(inline, env)) ?? file?.workerName);
|
|
413
|
+
warnDroppedWranglerOptions(dropped);
|
|
414
|
+
warnUnsupportedMinimalBindings(unsupported);
|
|
415
|
+
return {
|
|
416
|
+
options,
|
|
417
|
+
configFile: file ? configPath : void 0
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
let fileLoaded = false;
|
|
421
|
+
let fileOptions;
|
|
422
|
+
let fileSecrets;
|
|
423
|
+
let fileWorkerName;
|
|
424
|
+
if (configPath) try {
|
|
425
|
+
const config = wrangler.unstable_readConfig({
|
|
308
426
|
config: configPath,
|
|
309
427
|
env
|
|
310
|
-
}, { hideWarnings:
|
|
428
|
+
}, { hideWarnings: !claimWranglerWarnings(configPath, env) });
|
|
429
|
+
fileOptions = pickWranglerMiniflareOptions(wrangler.unstable_getMiniflareWorkerOptions(config, env, { envFiles }).workerOptions, dropped);
|
|
430
|
+
fileWorkerName = config?.name;
|
|
431
|
+
fileSecrets = config?.secrets;
|
|
432
|
+
fileLoaded = true;
|
|
311
433
|
} catch (error) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
434
|
+
warnWranglerLoadError(`"${configPath}"`, error);
|
|
435
|
+
}
|
|
436
|
+
let inlineOptions;
|
|
437
|
+
if (inline) try {
|
|
438
|
+
const inlineEnv = env && isPlainObject(inline.env) && inline.env[env] ? env : void 0;
|
|
439
|
+
const { env: _env, ...inlineTopLevel } = inline;
|
|
440
|
+
const inlineConfig = readInlineWranglerConfig(wrangler, inlineEnv ? inline : inlineTopLevel, inlineEnv);
|
|
441
|
+
inlineConfig.userConfigPath = configPath;
|
|
442
|
+
if (fileLoaded && inlineConfig.secrets === void 0) inlineConfig.secrets = fileSecrets;
|
|
443
|
+
inlineOptions = pickWranglerMiniflareOptions(wrangler.unstable_getMiniflareWorkerOptions(inlineConfig, env, { envFiles }).workerOptions, dropped);
|
|
444
|
+
if (inlineOptions) {
|
|
445
|
+
delete inlineOptions.rootPath;
|
|
446
|
+
if (fileLoaded) filterInlineDevVarBindings(inlineOptions, fileOptions, inlineConfig);
|
|
447
|
+
}
|
|
448
|
+
} catch (error) {
|
|
449
|
+
warnWranglerLoadError("(inline)", error);
|
|
315
450
|
}
|
|
451
|
+
const options = mergeWranglerMiniflareOptions(fileOptions, inlineOptions);
|
|
452
|
+
filterLocalDurableObjects(options, dropped, (inline && wranglerWorkerName(inline, env)) ?? fileWorkerName);
|
|
453
|
+
warnDroppedWranglerOptions(dropped);
|
|
454
|
+
return {
|
|
455
|
+
options,
|
|
456
|
+
configFile: fileLoaded ? configPath : void 0
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
const _shownWranglerWarnings = /* @__PURE__ */ new Set();
|
|
460
|
+
function claimWranglerWarnings(configPath, env) {
|
|
461
|
+
let version = "";
|
|
462
|
+
try {
|
|
463
|
+
const stat = statSync(configPath);
|
|
464
|
+
version = `${stat.mtimeMs}:${stat.size}`;
|
|
465
|
+
} catch {}
|
|
466
|
+
const key = JSON.stringify([
|
|
467
|
+
resolve(configPath),
|
|
468
|
+
env ?? null,
|
|
469
|
+
version
|
|
470
|
+
]);
|
|
471
|
+
if (_shownWranglerWarnings.has(key)) return false;
|
|
472
|
+
_shownWranglerWarnings.add(key);
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
function warnWranglerLoadError(desc, error) {
|
|
476
|
+
console.warn(`[env-runner] failed to load wrangler config ${desc}: ${error.message}`);
|
|
316
477
|
}
|
|
317
478
|
function mergeWranglerMiniflareOptions(base, override) {
|
|
318
479
|
if (!base) return override;
|
|
@@ -329,6 +490,12 @@ function mergeWranglerMiniflareOptions(base, override) {
|
|
|
329
490
|
}
|
|
330
491
|
return out;
|
|
331
492
|
}
|
|
493
|
+
function filterInlineDevVarBindings(inlineOptions, fileOptions, inlineConfig) {
|
|
494
|
+
if (!isPlainObject(inlineOptions.bindings)) return;
|
|
495
|
+
const fileBindings = isPlainObject(fileOptions?.bindings) ? fileOptions.bindings : {};
|
|
496
|
+
const declared = /* @__PURE__ */ new Set([...Object.keys(inlineConfig.vars ?? {}), ...inlineConfig.secrets?.required ?? []]);
|
|
497
|
+
inlineOptions.bindings = Object.fromEntries(Object.entries(inlineOptions.bindings).filter(([key]) => declared.has(key) || Object.hasOwn(fileBindings, key)));
|
|
498
|
+
}
|
|
332
499
|
function readInlineWranglerConfig(wrangler, inline, env) {
|
|
333
500
|
const dir = mkdtempSync(join(tmpdir(), "env-runner-wrangler-"));
|
|
334
501
|
const file = join(dir, "wrangler.json");
|
|
@@ -345,29 +512,173 @@ function readInlineWranglerConfig(wrangler, inline, env) {
|
|
|
345
512
|
});
|
|
346
513
|
}
|
|
347
514
|
}
|
|
515
|
+
const _announcedWranglerConfigs = /* @__PURE__ */ new Set();
|
|
348
516
|
function findWranglerConfig(entryPath) {
|
|
349
|
-
const
|
|
517
|
+
const cwd = process.cwd();
|
|
518
|
+
let start = cwd;
|
|
350
519
|
if (entryPath) {
|
|
351
|
-
const
|
|
352
|
-
|
|
520
|
+
const entryDir = dirname(resolve(entryPath));
|
|
521
|
+
const rel = relative(cwd, entryDir);
|
|
522
|
+
if (rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel)) start = entryDir;
|
|
523
|
+
else {
|
|
524
|
+
const local = findWranglerConfigInDir(entryDir);
|
|
525
|
+
if (local) return local;
|
|
526
|
+
}
|
|
353
527
|
}
|
|
354
|
-
|
|
355
|
-
|
|
528
|
+
for (let dir = start;; dir = dirname(dir)) {
|
|
529
|
+
const found = findWranglerConfigInDir(dir);
|
|
530
|
+
if (found) {
|
|
531
|
+
if (dir !== cwd && dir !== start && !_announcedWranglerConfigs.has(found)) {
|
|
532
|
+
_announcedWranglerConfigs.add(found);
|
|
533
|
+
console.info(`[env-runner] using wrangler config from a parent directory: ${found}`);
|
|
534
|
+
}
|
|
535
|
+
return found;
|
|
536
|
+
}
|
|
537
|
+
if (dirname(dir) === dir) return;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function findWranglerConfigInDir(dir) {
|
|
541
|
+
for (const name of WRANGLER_CONFIG_FILENAMES) {
|
|
356
542
|
const candidate = join(dir, name);
|
|
357
543
|
if (existsSync(candidate)) return candidate;
|
|
358
544
|
}
|
|
359
545
|
}
|
|
360
|
-
function pickWranglerMiniflareOptions(workerOptions) {
|
|
546
|
+
function pickWranglerMiniflareOptions(workerOptions, dropped) {
|
|
361
547
|
const out = {};
|
|
362
548
|
for (const [key, value] of Object.entries(workerOptions)) {
|
|
363
549
|
if (value === void 0 || WRANGLER_OPTION_DENYLIST.has(key)) continue;
|
|
550
|
+
if (WRANGLER_OPTION_DROPLIST.has(key)) {
|
|
551
|
+
if (!isEmptyOption(value)) addDropped(dropped, WRANGLER_DROPPED_OPTION_NAMES[key], describeDroppedOption(value));
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (isEmptyPickedOption(key, value)) continue;
|
|
364
555
|
out[key] = value;
|
|
365
556
|
}
|
|
366
557
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
367
558
|
}
|
|
559
|
+
function isEmptyPickedOption(key, value) {
|
|
560
|
+
const isEmptyArray = (v) => Array.isArray(v) && v.length === 0;
|
|
561
|
+
if (isEmptyArray(value) || isPlainObject(value) && Object.keys(value).length === 0) return true;
|
|
562
|
+
return key !== "bindings" && isPlainObject(value) && Object.values(value).every(isEmptyArray);
|
|
563
|
+
}
|
|
564
|
+
function isEmptyOption(value) {
|
|
565
|
+
return !value || Array.isArray(value) && value.length === 0 || isPlainObject(value) && Object.keys(value).length === 0;
|
|
566
|
+
}
|
|
567
|
+
function describeDroppedOption(value) {
|
|
568
|
+
if (Array.isArray(value)) return value.map((entry) => entry?.name).filter((name) => typeof name === "string");
|
|
569
|
+
if (isPlainObject(value)) {
|
|
570
|
+
if ("directory" in value) return typeof value.binding === "string" ? [value.binding] : [];
|
|
571
|
+
return Object.keys(value);
|
|
572
|
+
}
|
|
573
|
+
return [];
|
|
574
|
+
}
|
|
575
|
+
function filterLocalDurableObjects(options, dropped, workerName) {
|
|
576
|
+
const value = options?.durableObjects;
|
|
577
|
+
if (!options || !isPlainObject(value)) return;
|
|
578
|
+
const out = {};
|
|
579
|
+
for (const [name, binding] of Object.entries(value)) if (typeof binding === "string" || isPlainObject(binding) && !binding.scriptName) out[name] = binding;
|
|
580
|
+
else if (isPlainObject(binding) && workerName && binding.scriptName === workerName) {
|
|
581
|
+
const { scriptName: _scriptName, ...local } = binding;
|
|
582
|
+
out[name] = local;
|
|
583
|
+
} else {
|
|
584
|
+
const scriptName = isPlainObject(binding) ? binding.scriptName : void 0;
|
|
585
|
+
addDropped(dropped, "durable_objects", [`${name} → script "${String(scriptName)}"`]);
|
|
586
|
+
}
|
|
587
|
+
if (Object.keys(out).length > 0) options.durableObjects = out;
|
|
588
|
+
else delete options.durableObjects;
|
|
589
|
+
}
|
|
590
|
+
const WRANGLER_NON_INHERITABLE_KEYS = /* @__PURE__ */ new Set([
|
|
591
|
+
"vars",
|
|
592
|
+
"secrets",
|
|
593
|
+
"define",
|
|
594
|
+
"durable_objects",
|
|
595
|
+
"workflows",
|
|
596
|
+
"kv_namespaces",
|
|
597
|
+
"cloudchamber",
|
|
598
|
+
"containers",
|
|
599
|
+
"send_email",
|
|
600
|
+
"queues",
|
|
601
|
+
"connect",
|
|
602
|
+
"r2_buckets",
|
|
603
|
+
"d1_databases",
|
|
604
|
+
"vectorize",
|
|
605
|
+
"ai_search_namespaces",
|
|
606
|
+
"ai_search",
|
|
607
|
+
"websearch",
|
|
608
|
+
"agent_memory",
|
|
609
|
+
"hyperdrive",
|
|
610
|
+
"services",
|
|
611
|
+
"analytics_engine_datasets",
|
|
612
|
+
"dispatch_namespaces",
|
|
613
|
+
"mtls_certificates",
|
|
614
|
+
"tail_consumers",
|
|
615
|
+
"streaming_tail_consumers",
|
|
616
|
+
"unsafe",
|
|
617
|
+
"browser",
|
|
618
|
+
"ai",
|
|
619
|
+
"images",
|
|
620
|
+
"stream",
|
|
621
|
+
"media",
|
|
622
|
+
"pipelines",
|
|
623
|
+
"secrets_store_secrets",
|
|
624
|
+
"artifacts",
|
|
625
|
+
"unsafe_hello_world",
|
|
626
|
+
"flagship",
|
|
627
|
+
"worker_loaders",
|
|
628
|
+
"ratelimits",
|
|
629
|
+
"vpc_services",
|
|
630
|
+
"vpc_networks",
|
|
631
|
+
"version_metadata"
|
|
632
|
+
]);
|
|
633
|
+
const MINIMAL_UNSUPPORTED_BINDING_KEYS = [
|
|
634
|
+
"hyperdrive",
|
|
635
|
+
"analytics_engine_datasets",
|
|
636
|
+
"ai",
|
|
637
|
+
"ai_search_namespaces",
|
|
638
|
+
"ai_search",
|
|
639
|
+
"websearch",
|
|
640
|
+
"agent_memory",
|
|
641
|
+
"version_metadata",
|
|
642
|
+
"ratelimits",
|
|
643
|
+
"send_email",
|
|
644
|
+
"secrets_store_secrets",
|
|
645
|
+
"vectorize",
|
|
646
|
+
"browser",
|
|
647
|
+
"images",
|
|
648
|
+
"stream",
|
|
649
|
+
"media",
|
|
650
|
+
"pipelines",
|
|
651
|
+
"dispatch_namespaces",
|
|
652
|
+
"mtls_certificates",
|
|
653
|
+
"worker_loaders",
|
|
654
|
+
"vpc_services",
|
|
655
|
+
"vpc_networks",
|
|
656
|
+
"artifacts",
|
|
657
|
+
"flagship",
|
|
658
|
+
"containers",
|
|
659
|
+
"unsafe",
|
|
660
|
+
"unsafe_hello_world",
|
|
661
|
+
"logfwdr",
|
|
662
|
+
"wasm_modules",
|
|
663
|
+
"text_blobs",
|
|
664
|
+
"data_blobs"
|
|
665
|
+
];
|
|
666
|
+
const MINIMAL_BINDING_OPTIONS = [
|
|
667
|
+
"kvNamespaces",
|
|
668
|
+
"r2Buckets",
|
|
669
|
+
"d1Databases",
|
|
670
|
+
"queueProducers",
|
|
671
|
+
"durableObjects"
|
|
672
|
+
];
|
|
673
|
+
function warnUnsupportedMinimalBindings(unsupported) {
|
|
674
|
+
if (unsupported.size === 0) return;
|
|
675
|
+
const list = [...unsupported].map(([name, details]) => details.size > 0 ? `${name} (${[...details].join(", ")})` : name).join(", ");
|
|
676
|
+
console.warn(`[env-runner] wrangler config bindings not supported by the built-in minimal wrangler config reader were ignored: ${list}; install 'wrangler' (or pass it as \`wranglerModule\`) to use them.`);
|
|
677
|
+
}
|
|
368
678
|
function readWranglerConfigMinimal(configPath, env) {
|
|
369
|
-
|
|
370
|
-
|
|
679
|
+
const ext = extname(configPath).toLowerCase();
|
|
680
|
+
if (ext !== ".json" && ext !== ".jsonc") {
|
|
681
|
+
console.warn(`[env-runner] reading "${basename(configPath)}" requires the 'wrangler' package; the built-in reader supports JSON/JSONC only (install 'wrangler' for TOML).`);
|
|
371
682
|
return;
|
|
372
683
|
}
|
|
373
684
|
let raw;
|
|
@@ -378,45 +689,203 @@ function readWranglerConfigMinimal(configPath, env) {
|
|
|
378
689
|
}
|
|
379
690
|
let config;
|
|
380
691
|
try {
|
|
381
|
-
config =
|
|
692
|
+
config = parseJSONC(raw);
|
|
382
693
|
} catch (error) {
|
|
383
694
|
console.warn(`[env-runner] failed to parse wrangler config "${configPath}": ${error.message}`);
|
|
384
695
|
return;
|
|
385
696
|
}
|
|
386
|
-
|
|
697
|
+
if (!isPlainObject(config)) {
|
|
698
|
+
warnWranglerLoadError(`"${configPath}"`, /* @__PURE__ */ new Error("config must be an object"));
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
let envConfig;
|
|
702
|
+
try {
|
|
703
|
+
envConfig = applyWranglerEnv(config, env, configPath);
|
|
704
|
+
} catch (error) {
|
|
705
|
+
warnWranglerLoadError(`"${configPath}"`, error);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
return {
|
|
709
|
+
config: envConfig,
|
|
710
|
+
workerName: wranglerWorkerName(config, env)
|
|
711
|
+
};
|
|
387
712
|
}
|
|
388
|
-
function applyWranglerEnv(config, env) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
713
|
+
function applyWranglerEnv(config, env, configPath) {
|
|
714
|
+
const { env: envs, ...topLevel } = config;
|
|
715
|
+
if (!env) return topLevel;
|
|
716
|
+
const rawEnv = isPlainObject(envs) ? envs[env] : void 0;
|
|
717
|
+
const warnings = [];
|
|
718
|
+
let out;
|
|
719
|
+
if (isPlainObject(rawEnv)) {
|
|
720
|
+
out = {};
|
|
721
|
+
for (const [key, value] of Object.entries(topLevel)) if (!WRANGLER_NON_INHERITABLE_KEYS.has(key)) out[key] = value;
|
|
722
|
+
else if (rawEnv[key] === void 0) warnings.push(`"${key}" exists at the top level, but is not inherited by "env.${env}"`);
|
|
723
|
+
Object.assign(out, rawEnv);
|
|
724
|
+
} else {
|
|
725
|
+
if (configPath && isPlainObject(envs)) throw new Error(`No environment found in configuration with name "${env}". The available configured environment names are: ${JSON.stringify(Object.keys(envs))}`);
|
|
726
|
+
warnings.push(`No environment found in configuration with name "${env}"`);
|
|
727
|
+
out = topLevel;
|
|
728
|
+
}
|
|
729
|
+
if (configPath && warnings.length > 0 && claimWranglerWarnings(configPath, env)) console.warn(`[env-runner] wrangler config "${configPath}": ${warnings.join("; ")}.`);
|
|
730
|
+
return out;
|
|
731
|
+
}
|
|
732
|
+
function wranglerWorkerName(config, env) {
|
|
733
|
+
const envName = env ? config.env?.[env]?.name : void 0;
|
|
734
|
+
if (typeof envName === "string") return envName;
|
|
735
|
+
if (typeof config.name !== "string" || !config.name) return void 0;
|
|
736
|
+
return env ? `${config.name}-${env}` : config.name;
|
|
393
737
|
}
|
|
394
|
-
function mapWranglerConfigToMiniflare(config) {
|
|
738
|
+
function mapWranglerConfigToMiniflare(config, dropped, unsupported) {
|
|
395
739
|
const out = {};
|
|
740
|
+
for (const [name, value, field] of [
|
|
741
|
+
[
|
|
742
|
+
"services",
|
|
743
|
+
config.services,
|
|
744
|
+
"binding"
|
|
745
|
+
],
|
|
746
|
+
[
|
|
747
|
+
"assets",
|
|
748
|
+
config.assets,
|
|
749
|
+
"binding"
|
|
750
|
+
],
|
|
751
|
+
[
|
|
752
|
+
"queues.consumers",
|
|
753
|
+
config.queues?.consumers,
|
|
754
|
+
"queue"
|
|
755
|
+
],
|
|
756
|
+
[
|
|
757
|
+
"workflows",
|
|
758
|
+
config.workflows,
|
|
759
|
+
"binding"
|
|
760
|
+
],
|
|
761
|
+
[
|
|
762
|
+
"tail_consumers",
|
|
763
|
+
config.tail_consumers,
|
|
764
|
+
"service"
|
|
765
|
+
],
|
|
766
|
+
[
|
|
767
|
+
"streaming_tail_consumers",
|
|
768
|
+
config.streaming_tail_consumers,
|
|
769
|
+
"service"
|
|
770
|
+
]
|
|
771
|
+
]) if (!isEmptyOption(value)) addDropped(dropped, name, (Array.isArray(value) ? value : [value]).map((e) => e?.[field]).filter((d) => typeof d === "string"));
|
|
772
|
+
for (const key of MINIMAL_UNSUPPORTED_BINDING_KEYS) {
|
|
773
|
+
const value = config[key];
|
|
774
|
+
const bindings = isPlainObject(value) && Array.isArray(value.bindings) ? value.bindings : value;
|
|
775
|
+
if (!isEmptyOption(bindings)) addDropped(unsupported, key, describeBindingNames(bindings));
|
|
776
|
+
}
|
|
396
777
|
if (typeof config.compatibility_date === "string") out.compatibilityDate = config.compatibility_date;
|
|
397
778
|
if (Array.isArray(config.compatibility_flags)) out.compatibilityFlags = config.compatibility_flags;
|
|
398
779
|
if (config.vars && typeof config.vars === "object") out.bindings = { ...config.vars };
|
|
399
|
-
const kv = mapBindingArray(config.kv_namespaces, "binding", (n) => n.id
|
|
780
|
+
const kv = mapBindingArray(config.kv_namespaces, "binding", (n) => firstString(n.preview_id, n.id, n.binding));
|
|
400
781
|
if (kv) out.kvNamespaces = kv;
|
|
401
|
-
const r2 = mapBindingArray(config.r2_buckets, "binding", (n) => n.bucket_name
|
|
782
|
+
const r2 = mapBindingArray(config.r2_buckets, "binding", (n) => firstString(n.preview_bucket_name, n.bucket_name, n.binding));
|
|
402
783
|
if (r2) out.r2Buckets = r2;
|
|
403
|
-
const d1 = mapBindingArray(config.d1_databases, "binding", (n) => n.
|
|
784
|
+
const d1 = mapBindingArray(config.d1_databases, "binding", (n) => firstString(n.preview_database_id, n.database_id, n.binding));
|
|
404
785
|
if (d1) out.d1Databases = d1;
|
|
405
786
|
const queues = mapBindingArray(config.queues?.producers, "binding", (n) => n.queue);
|
|
406
787
|
if (queues) out.queueProducers = queues;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
788
|
+
const useSQLite = durableObjectClassStorage(config);
|
|
789
|
+
const doBindings = Array.isArray(config.durable_objects?.bindings) ? config.durable_objects.bindings : [];
|
|
790
|
+
const dos = {};
|
|
791
|
+
for (const b of doBindings) {
|
|
792
|
+
if (!b?.name || !b?.class_name) continue;
|
|
793
|
+
dos[b.name] = {
|
|
794
|
+
className: b.class_name,
|
|
795
|
+
...b.script_name ? { scriptName: b.script_name } : {},
|
|
796
|
+
...useSQLite.has(b.class_name) ? { useSQLite: useSQLite.get(b.class_name) } : {}
|
|
797
|
+
};
|
|
417
798
|
}
|
|
799
|
+
if (Object.keys(dos).length > 0) out.durableObjects = dos;
|
|
800
|
+
const unbound = [...useSQLite].filter(([className]) => !doBindings.some((b) => b?.class_name === className)).map(([className, sqlite]) => ({
|
|
801
|
+
className,
|
|
802
|
+
useSQLite: sqlite
|
|
803
|
+
}));
|
|
804
|
+
if (unbound.length > 0) out.additionalUnboundDurableObjects = unbound;
|
|
418
805
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
419
806
|
}
|
|
807
|
+
function durableObjectClassStorage(config) {
|
|
808
|
+
const classes = /* @__PURE__ */ new Map();
|
|
809
|
+
for (const migration of Array.isArray(config.migrations) ? config.migrations : []) {
|
|
810
|
+
for (const name of migration?.deleted_classes ?? []) classes.delete(name);
|
|
811
|
+
for (const { from, to } of migration?.renamed_classes ?? []) {
|
|
812
|
+
const sqlite = classes.get(from);
|
|
813
|
+
if (sqlite !== void 0) {
|
|
814
|
+
classes.delete(from);
|
|
815
|
+
classes.set(to, sqlite);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
for (const name of migration?.new_classes ?? []) classes.set(name, false);
|
|
819
|
+
for (const name of migration?.new_sqlite_classes ?? []) classes.set(name, true);
|
|
820
|
+
}
|
|
821
|
+
if (isPlainObject(config.exports)) for (const [name, entry] of Object.entries(config.exports)) {
|
|
822
|
+
const state = entry?.state;
|
|
823
|
+
if (entry?.type === "durable-object" && (state === void 0 || state === "created" || state === "expecting-transfer")) classes.set(name, entry.storage === "sqlite");
|
|
824
|
+
}
|
|
825
|
+
return classes;
|
|
826
|
+
}
|
|
827
|
+
function describeBindingNames(value) {
|
|
828
|
+
if (isPlainObject(value) && typeof value.binding !== "string") return Object.keys(value);
|
|
829
|
+
return (Array.isArray(value) ? value : [value]).map((e) => e?.binding ?? e?.name ?? e?.class_name).filter((name) => typeof name === "string");
|
|
830
|
+
}
|
|
831
|
+
function applyMinimalDevVars(options, configs, opts) {
|
|
832
|
+
const secrets = configs.map((c) => c?.secrets).filter(isPlainObject);
|
|
833
|
+
const loaded = loadDevVars({
|
|
834
|
+
...opts,
|
|
835
|
+
hasSecrets: secrets.length > 0
|
|
836
|
+
});
|
|
837
|
+
if (!loaded) return options;
|
|
838
|
+
const out = { ...options };
|
|
839
|
+
const bindings = isPlainObject(out.bindings) ? { ...out.bindings } : {};
|
|
840
|
+
const taken = new Set(MINIMAL_BINDING_OPTIONS.flatMap((key) => isPlainObject(out[key]) ? Object.keys(out[key]) : []));
|
|
841
|
+
const required = new Set(secrets.flatMap((s) => Array.isArray(s.required) ? s.required : []));
|
|
842
|
+
let changed = false;
|
|
843
|
+
for (const [key, value] of Object.entries(loaded)) {
|
|
844
|
+
if (taken.has(key) || secrets.length > 0 && !Object.hasOwn(bindings, key) && !required.has(key)) continue;
|
|
845
|
+
bindings[key] = value;
|
|
846
|
+
changed = true;
|
|
847
|
+
}
|
|
848
|
+
const missing = [...required].filter((key) => !Object.hasOwn(loaded, key));
|
|
849
|
+
if (missing.length > 0) console.warn(`[env-runner] missing required wrangler secrets: ${missing.join(", ")}. Add them to .dev.vars, .env, or set as environment variables.`);
|
|
850
|
+
if (!changed) return options;
|
|
851
|
+
out.bindings = bindings;
|
|
852
|
+
return out;
|
|
853
|
+
}
|
|
854
|
+
function firstString(...values) {
|
|
855
|
+
return values.find((value) => typeof value === "string");
|
|
856
|
+
}
|
|
857
|
+
function parseJSONC(text) {
|
|
858
|
+
let out = "";
|
|
859
|
+
let comma = -1;
|
|
860
|
+
const src = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
861
|
+
for (let i = 0; i < src.length; i++) {
|
|
862
|
+
const ch = src[i];
|
|
863
|
+
if (ch === "/" && (src[i + 1] === "/" || src[i + 1] === "*")) {
|
|
864
|
+
const line = src[i + 1] === "/";
|
|
865
|
+
let end = line ? src.indexOf("\n", i) : src.indexOf("*/", i + 2);
|
|
866
|
+
end = end === -1 ? src.length : line ? end : end + 2;
|
|
867
|
+
out += src.slice(i, end).replace(/[^\n]/g, " ");
|
|
868
|
+
i = end - 1;
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
if (/\s/.test(ch)) {
|
|
872
|
+
out += ch;
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
if ((ch === "}" || ch === "]") && comma !== -1) out = `${out.slice(0, comma)} ${out.slice(comma + 1)}`;
|
|
876
|
+
comma = -1;
|
|
877
|
+
if (ch === "\"") {
|
|
878
|
+
let end = i + 1;
|
|
879
|
+
while (end < src.length && src[end] !== "\"") end += src[end] === "\\" ? 2 : 1;
|
|
880
|
+
out += src.slice(i, end + 1);
|
|
881
|
+
i = end;
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
if (ch === ",") comma = out.length;
|
|
885
|
+
out += ch;
|
|
886
|
+
}
|
|
887
|
+
return JSON.parse(out);
|
|
888
|
+
}
|
|
420
889
|
function mapBindingArray(arr, keyField, value) {
|
|
421
890
|
if (!Array.isArray(arr)) return;
|
|
422
891
|
const out = {};
|
|
@@ -443,6 +912,9 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
443
912
|
#exportConditions;
|
|
444
913
|
#wrangler;
|
|
445
914
|
#wranglerEnv;
|
|
915
|
+
#wranglerConfigPath;
|
|
916
|
+
#wranglerEnvFiles;
|
|
917
|
+
#compatibilityDate;
|
|
446
918
|
#wranglerModule;
|
|
447
919
|
#miniflareModule;
|
|
448
920
|
constructor(opts) {
|
|
@@ -460,6 +932,9 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
460
932
|
this.#wrangler = opts.wrangler ?? false;
|
|
461
933
|
this.#wranglerEnv = opts.wranglerEnv ?? process.env.CLOUDFLARE_ENV;
|
|
462
934
|
this.#wranglerModule = opts.wranglerModule;
|
|
935
|
+
this.#wranglerConfigPath = opts.wranglerConfigPath;
|
|
936
|
+
this.#wranglerEnvFiles = opts.wranglerEnvFiles;
|
|
937
|
+
this.#compatibilityDate = opts.compatibilityDate;
|
|
463
938
|
this._initWithVirtualData(() => this.#init());
|
|
464
939
|
}
|
|
465
940
|
static async disposeAll() {
|
|
@@ -609,20 +1084,28 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
609
1084
|
const entryPath = this._data?.entry;
|
|
610
1085
|
const virtual = await this.#prepareVirtualModules();
|
|
611
1086
|
this.#virtual = virtual;
|
|
612
|
-
const wranglerOptions = await loadWranglerConfig(
|
|
1087
|
+
const { options: wranglerOptions, configFile: wranglerConfigFile } = await loadWranglerConfig({
|
|
1088
|
+
wrangler: this.#wrangler,
|
|
1089
|
+
env: this.#wranglerEnv,
|
|
1090
|
+
entryPath,
|
|
1091
|
+
configPath: this.#wranglerConfigPath,
|
|
1092
|
+
wranglerModule: this.#wranglerModule,
|
|
1093
|
+
envFiles: this.#wranglerEnvFiles
|
|
1094
|
+
});
|
|
613
1095
|
const userFlags = this.#miniflareOptions.compatibilityFlags || [];
|
|
614
1096
|
const wranglerFlags = wranglerOptions?.compatibilityFlags || [];
|
|
615
1097
|
const userDirectSockets = this.#miniflareOptions.unsafeDirectSockets || [];
|
|
616
1098
|
const options = {
|
|
617
|
-
compatibilityDate: supportedCompatibilityDate,
|
|
618
1099
|
modules: true,
|
|
1100
|
+
...this.#wrangler && !hasUserPersistOptions(this.#miniflareOptions) ? { defaultPersistRoot: wranglerPersistRoot(wranglerConfigFile, typeof this.#wrangler === "string" ? this.#wrangler : this.#wranglerConfigPath) } : void 0,
|
|
619
1101
|
...wranglerOptions,
|
|
620
1102
|
...this.#miniflareOptions,
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
])
|
|
1103
|
+
compatibilityDate: resolveCompatibilityDate([
|
|
1104
|
+
this.#miniflareOptions.compatibilityDate,
|
|
1105
|
+
this.#compatibilityDate === "latest" ? supportedCompatibilityDate : this.#compatibilityDate,
|
|
1106
|
+
wranglerOptions?.compatibilityDate
|
|
1107
|
+
], supportedCompatibilityDate),
|
|
1108
|
+
compatibilityFlags: resolveCompatibilityFlags(wranglerFlags, userFlags),
|
|
626
1109
|
unsafeDirectSockets: [{
|
|
627
1110
|
host: "127.0.0.1",
|
|
628
1111
|
port: 0
|
|
@@ -643,18 +1126,21 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
643
1126
|
const entrySource = entryIsVirtual ? virtual[entryPath] : _tryReadFile(resolvedEntry);
|
|
644
1127
|
const detectedExports = this.#exports === false || this.#exports === void 0 ? [] : detectExportedClasses(entrySource, typeof this.#exports === "object" ? this.#exports : {});
|
|
645
1128
|
if (entryIsVirtual && detectedExports.length > 0) throw new Error(`[env-runner] named exports (${detectedExports.join(", ")}) are not supported with a virtual entry on the miniflare runner; pass \`exports: false\` or use a real entry file.`);
|
|
646
|
-
if (detectedExports.length > 0
|
|
647
|
-
const
|
|
1129
|
+
if (detectedExports.length > 0) {
|
|
1130
|
+
const existingDOs = isPlainObject(options.durableObjects) ? options.durableObjects : {};
|
|
1131
|
+
const boundClasses = new Set(Object.values(existingDOs).map((b) => typeof b === "string" ? b : isPlainObject(b) && !b.scriptName ? b.className : void 0));
|
|
1132
|
+
const autoDOs = { ...existingDOs };
|
|
648
1133
|
for (const name of detectedExports) {
|
|
649
1134
|
const bindingName = toScreamingSnakeCase(name);
|
|
650
|
-
if (!autoDOs[bindingName]) autoDOs[bindingName] = name;
|
|
1135
|
+
if (!autoDOs[bindingName] && !boundClasses.has(name)) autoDOs[bindingName] = name;
|
|
651
1136
|
}
|
|
652
1137
|
options.durableObjects = autoDOs;
|
|
653
1138
|
}
|
|
654
1139
|
options.script = generateWrapper(resolvedEntry, {
|
|
655
1140
|
dynamicOnly: true,
|
|
656
1141
|
captureErrors: this.#captureErrors,
|
|
657
|
-
exports: detectedExports
|
|
1142
|
+
exports: detectedExports,
|
|
1143
|
+
nodeCompat: !options.compatibilityFlags.includes("no_nodejs_compat")
|
|
658
1144
|
});
|
|
659
1145
|
options.scriptPath = entryDir + "/__env_runner_wrapper.mjs";
|
|
660
1146
|
if (!options.modulesRoot) options.modulesRoot = "/";
|
|
@@ -853,6 +1339,30 @@ function detectExportedClasses(entrySource, explicit) {
|
|
|
853
1339
|
}
|
|
854
1340
|
return [...names];
|
|
855
1341
|
}
|
|
1342
|
+
function resolveCompatibilityDate(candidates, supported) {
|
|
1343
|
+
const date = candidates.find((d) => typeof d === "string" && d) ?? supported;
|
|
1344
|
+
if (date && supported && _isDateString(date) && _isDateString(supported) && date > supported) {
|
|
1345
|
+
console.warn(`[env-runner] compatibility date "${date}" is newer than the installed workerd supports; falling back to "${supported}".`);
|
|
1346
|
+
return supported;
|
|
1347
|
+
}
|
|
1348
|
+
return date;
|
|
1349
|
+
}
|
|
1350
|
+
function resolveCompatibilityFlags(wranglerFlags, userFlags) {
|
|
1351
|
+
const opposite = (flag) => flag === "nodejs_compat" ? "no_nodejs_compat" : flag === "no_nodejs_compat" ? "nodejs_compat" : void 0;
|
|
1352
|
+
const flags = [...wranglerFlags.filter((flag) => !userFlags.includes(opposite(flag))), ...userFlags];
|
|
1353
|
+
const defaults = flags.includes("no_nodejs_compat") ? [] : ["nodejs_compat"];
|
|
1354
|
+
return [.../* @__PURE__ */ new Set([...defaults, ...flags])];
|
|
1355
|
+
}
|
|
1356
|
+
function _isDateString(value) {
|
|
1357
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(value);
|
|
1358
|
+
}
|
|
1359
|
+
function hasUserPersistOptions(options) {
|
|
1360
|
+
return Object.keys(options).some((key) => key === "defaultPersistRoot" || key.endsWith("Persist"));
|
|
1361
|
+
}
|
|
1362
|
+
function wranglerPersistRoot(configFile, explicitPath) {
|
|
1363
|
+
const file = configFile ?? (explicitPath ? resolve(explicitPath) : void 0);
|
|
1364
|
+
return join(file ? dirname(file) : process.cwd(), ".wrangler/state/v3");
|
|
1365
|
+
}
|
|
856
1366
|
function _tryReadFile(path) {
|
|
857
1367
|
try {
|
|
858
1368
|
return readFileSync(path, "utf8");
|