env-runner 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,37 @@
1
- import { createVirtualHooks, expandVirtualInvalidation, stripVirtualTypeScript, virtualModuleFormat } from "./virtual-loader.mjs";
2
- import { pathToFileURL } from "node:url";
3
- import { existsSync, readFileSync } from "node:fs";
4
- import { isAbsolute } from "node:path";
5
- async function registerVirtualModules(virtual) {
6
- if (!virtual || Object.keys(virtual).length === 0) return _noop;
7
- const { registerHooks, stripTypeScriptTypes } = await import("node:module");
1
+ import { createVirtualHooks, decodeVirtualModules, expandVirtualInvalidation, findVirtualPathKey, stripVirtualTypeScript, unsupportedVirtualJSXError, virtualKeyURL, virtualModuleCacheId, virtualModuleCode, virtualModuleFormat } from "./virtual-loader.mjs";
2
+ import { basename, dirname, isAbsolute, resolve, sep } from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ async function registerVirtualModules(wire) {
5
+ if (!wire || Object.keys(wire).length === 0) return _once(() => {
6
+ for (const unregister of _lazyUnregisters.splice(0)) unregister();
7
+ });
8
+ let virtual = decodeVirtualModules(wire);
9
+ const { registerHooks, stripTypeScriptTypes, createRequire } = await import("node:module");
8
10
  if (typeof registerHooks === "function") {
9
11
  const isDeno = "Deno" in globalThis;
10
- let transformSource;
11
- if (isDeno) {
12
- transformSource = (specifier, source) => _transformSourceForDeno(specifier, source, stripTypeScriptTypes);
13
- const transformed = {};
14
- for (const [specifier, source] of Object.entries(virtual)) transformed[specifier] = transformSource(specifier, source);
15
- virtual = transformed;
16
- }
12
+ const prepare = isDeno ? (key, module) => _prepareForDeno(key, module, stripTypeScriptTypes) : _prepareForNode;
13
+ virtual = await _prepareVirtualModules(virtual, prepare);
14
+ const versions = /* @__PURE__ */ new Map();
15
+ const importers = /* @__PURE__ */ new Map();
16
+ const { resolve, load, updateKeys } = createVirtualHooks(virtual, {
17
+ versions,
18
+ importers,
19
+ forcePlainModule: isDeno,
20
+ opaquePathURL: isDeno ? (url) => url.endsWith(".cjs") || url.endsWith(".cts") : void 0
21
+ });
22
+ const hooks = registerHooks({
23
+ resolve,
24
+ load
25
+ });
17
26
  const registration = {
18
27
  virtual,
19
- versions: /* @__PURE__ */ new Map(),
20
- transformSource
28
+ versions,
29
+ version: 0,
30
+ importers,
31
+ prepare,
32
+ updateKeys,
33
+ cache: createRequire(import.meta.url).cache
21
34
  };
22
- const hooks = registerHooks(createVirtualHooks(virtual, registration.versions, void 0, isDeno));
23
35
  _hooksRegistrations.unshift(registration);
24
36
  return _once(() => {
25
37
  const index = _hooksRegistrations.indexOf(registration);
@@ -28,74 +40,429 @@ async function registerVirtualModules(virtual) {
28
40
  });
29
41
  }
30
42
  if (typeof globalThis.Bun?.plugin === "function") {
31
- _bunVirtual = virtual;
32
- _registerBunModules(Object.keys(virtual));
43
+ virtual = await _prepareVirtualModules(virtual, _prepareForBun);
44
+ const registration = _createBunRegistration(virtual, createRequire(import.meta.url).cache);
45
+ globalThis.Bun.plugin({
46
+ name: "env-runner-virtual",
47
+ setup: (build) => _setupBunPlugin(build, registration)
48
+ });
49
+ _bunRegistrations.unshift(registration);
33
50
  return _once(() => {
34
- if (_bunVirtual === virtual) _bunVirtual = void 0;
51
+ const index = _bunRegistrations.indexOf(registration);
52
+ if (index !== -1) _bunRegistrations.splice(index, 1);
53
+ for (const path of [...registration.paths.keys(), ...registration.removed.keys()]) _bunReleasedPaths.add(path);
35
54
  });
36
55
  }
37
- console.warn("[env-runner] virtual modules require `module.registerHooks` (Node.js >= 22.15 / Deno >= 2.x) or `Bun.plugin`; skipping registration.");
56
+ console.warn("[env-runner] virtual modules require `module.registerHooks` (Node.js >= 22.15 / Deno >= 2.8) or `Bun.plugin`; skipping registration.");
38
57
  return _noop;
39
58
  }
40
59
  function refreshVirtualModule(specifier) {
41
- if (_bunVirtual?.[specifier] === void 0) return false;
42
- _registerBunModules([specifier]);
43
- return true;
44
- }
45
- function invalidateVirtualModule(specifier, source) {
46
- for (const registration of _hooksRegistrations) {
47
- if (!Object.hasOwn(registration.virtual, specifier)) continue;
48
- const { virtual, versions, transformSource } = registration;
49
- if (source !== void 0) virtual[specifier] = transformSource ? transformSource(specifier, source) : source;
50
- for (const key of expandVirtualInvalidation(virtual, specifier)) versions.set(key, (versions.get(key) ?? 0) + 1);
51
- return true;
52
- }
53
- if (_bunVirtual && Object.hasOwn(_bunVirtual, specifier)) {
54
- if (source !== void 0) _bunVirtual[specifier] = source;
55
- _registerBunModules(expandVirtualInvalidation(_bunVirtual, specifier));
60
+ for (const registration of _bunRegistrations) if (Object.hasOwn(registration.virtual, specifier)) {
61
+ _bustBunModules(registration, [specifier]);
56
62
  return true;
57
63
  }
58
64
  return false;
59
65
  }
60
- function handleInvalidateModule(message, sendMessage) {
61
- const ok = invalidateVirtualModule(message.specifier, message.source);
62
- sendMessage({
63
- event: "module-invalidated",
64
- specifier: message.specifier,
65
- error: ok ? void 0 : `Cannot invalidate "${message.specifier}" (not a registered virtual module)`
66
+ async function updateVirtualModules(wire) {
67
+ const changes = decodeVirtualModules(wire);
68
+ if (_hooksRegistrations.length === 0 && _bunRegistrations.length === 0) {
69
+ const added = Object.fromEntries(Object.entries(changes).filter((entry) => entry[1] !== null));
70
+ if (Object.keys(added).length === 0) return;
71
+ const unregister = await registerVirtualModules(added);
72
+ if (_hooksRegistrations.length === 0 && _bunRegistrations.length === 0) throw new Error("Cannot update virtual modules: this runtime can't serve them");
73
+ _lazyUnregisters.push(unregister);
74
+ }
75
+ const registrations = _hooksRegistrations.length > 0 ? _hooksRegistrations : _bunRegistrations;
76
+ const groups = /* @__PURE__ */ new Map();
77
+ for (const [key, module] of Object.entries(changes)) {
78
+ const owner = registrations.find((registration) => Object.hasOwn(registration.virtual, key)) ?? (module === null ? void 0 : registrations[0]);
79
+ if (owner) {
80
+ let group = groups.get(owner);
81
+ if (!group) groups.set(owner, group = {});
82
+ group[key] = module;
83
+ }
84
+ }
85
+ const prepared = [];
86
+ for (const [registration, group] of groups) {
87
+ const prepare = "prepare" in registration ? registration.prepare : _prepareForBun;
88
+ prepared.push([registration, await _prepareVirtualModules(group, prepare)]);
89
+ }
90
+ for (const [registration, sources] of prepared) if ("updateKeys" in registration) _updateHooksRegistration(registration, sources);
91
+ else _updateBunRegistration(registration, sources);
92
+ }
93
+ function handleUpdateVirtualModules(message, sendMessage) {
94
+ _pendingUpdate = _pendingUpdate.then(() => updateVirtualModules(message.changes ?? {})).then(() => sendMessage({
95
+ event: "virtual-modules-updated",
96
+ id: message.id
97
+ }), (error) => sendMessage({
98
+ event: "virtual-modules-updated",
99
+ id: message.id,
100
+ error: error?.message || String(error)
101
+ })).catch(() => {});
102
+ return _pendingUpdate;
103
+ }
104
+ function registeredVirtualModules() {
105
+ const merged = {};
106
+ for (const registration of [..._hooksRegistrations, ..._bunRegistrations].reverse()) Object.assign(merged, registration.virtual);
107
+ return merged;
108
+ }
109
+ let _pendingUpdate = Promise.resolve();
110
+ const _lazyUnregisters = [];
111
+ function _updateHooksRegistration(registration, changes) {
112
+ const { virtual, versions, importers } = registration;
113
+ const added = [];
114
+ const removed = [];
115
+ for (const [key, module] of Object.entries(changes)) {
116
+ if (module === null) {
117
+ removed.push(key);
118
+ continue;
119
+ }
120
+ if (!Object.hasOwn(virtual, key)) added.push(key);
121
+ virtual[key] = module;
122
+ }
123
+ registration.updateKeys(added);
124
+ const targets = Object.keys(changes).flatMap((key) => {
125
+ const url = virtualKeyURL(key);
126
+ return url && url !== key ? [key, url] : [key];
66
127
  });
128
+ for (const node of expandVirtualInvalidation(virtual, targets, importers)) {
129
+ versions.set(node, ++registration.version);
130
+ if (Object.hasOwn(virtual, node)) delete registration.cache[virtualModuleCacheId(node)];
131
+ }
132
+ for (const key of removed) delete virtual[key];
133
+ registration.updateKeys(removed);
67
134
  }
68
135
  const _hooksRegistrations = [];
69
- let _bunVirtual;
70
- function _registerBunModules(specifiers) {
71
- globalThis.Bun.plugin({
72
- name: "env-runner-virtual",
73
- setup(build) {
74
- for (const specifier of specifiers) build.module(specifier, () => {
75
- const source = _bunVirtual?.[specifier];
76
- if (source === void 0) throw new Error(`Cannot find virtual module "${specifier}" (unregistered)`);
77
- const format = virtualModuleFormat(specifier);
78
- if (format === "json") return {
79
- exports: { default: JSON.parse(source) },
80
- loader: "object"
81
- };
82
- return {
83
- contents: source,
84
- loader: format === "module-typescript" ? "ts" : "js"
85
- };
86
- });
136
+ const _bunRegistrations = [];
137
+ const BUN_NAMESPACE = "env-runner-virtual";
138
+ const BUN_VIRTUAL_MARKER = "__env_runner_virtual";
139
+ const BUN_DISK_MARKER = "__env_runner_disk";
140
+ let _bunNamespaceLoader = false;
141
+ let _bunDynamicCallbacks = false;
142
+ const _bunDynamicNames = /* @__PURE__ */ new Set();
143
+ const _bunReleasedPaths = /* @__PURE__ */ new Set();
144
+ function _createBunRegistration(virtual, cache) {
145
+ const registration = {
146
+ virtual,
147
+ paths: /* @__PURE__ */ new Map(),
148
+ namespaced: /* @__PURE__ */ new Set(),
149
+ modules: /* @__PURE__ */ new Set(),
150
+ dynamic: /* @__PURE__ */ new Set(),
151
+ removed: /* @__PURE__ */ new Map(),
152
+ versions: /* @__PURE__ */ new Map(),
153
+ version: 0,
154
+ importers: /* @__PURE__ */ new Map(),
155
+ served: /* @__PURE__ */ new Map(),
156
+ cache
157
+ };
158
+ for (const key of Object.keys(virtual)) _addBunKey(registration, key);
159
+ return registration;
160
+ }
161
+ function _addBunKey(registration, key) {
162
+ const path = _keyPath(key);
163
+ if (path === void 0) {
164
+ (!key.includes(":") && _bunResolvable(key) ? registration.namespaced : registration.modules).add(key);
165
+ return false;
166
+ }
167
+ if (_bunResolvable(basename(path))) {
168
+ registration.paths.set(path, key);
169
+ registration.removed.delete(path);
170
+ return true;
171
+ }
172
+ registration.modules.add(key);
173
+ return false;
174
+ }
175
+ function _setupBunPlugin(build, registration) {
176
+ registration.build = build;
177
+ const query = String.raw`(?:\?.*)?$`;
178
+ const resolveFilters = [...[...registration.namespaced].map((key) => `^${_escapeRegExp(key)}${query}`), ...[...registration.paths.keys()].map((path) => String.raw`(?:^|[\\/])${_escapeRegExp(basename(path))}${query}`)];
179
+ if (resolveFilters.length > 0) build.onResolve({ filter: new RegExp(resolveFilters.join("|")) }, _resolveBunModule);
180
+ if (registration.paths.size > 0) {
181
+ const paths = [...registration.paths.keys()].map(_escapeRegExp).join("|");
182
+ const loadQuery = String.raw`(?:\?(?!${BUN_DISK_MARKER}(?:&|$)).*)?$`;
183
+ build.onLoad({ filter: new RegExp(`^(?:${paths})${loadQuery}`) }, _loadBunPath);
184
+ }
185
+ if (registration.namespaced.size > 0 && !_bunNamespaceLoader) {
186
+ _bunNamespaceLoader = true;
187
+ build.onLoad({
188
+ filter: /.*/,
189
+ namespace: BUN_NAMESPACE
190
+ }, _loadBunNamespaced);
191
+ }
192
+ for (const key of registration.modules) build.module(key, () => _loadBunModule(key));
193
+ }
194
+ function _installBunDynamicCallbacks(build) {
195
+ if (!_bunDynamicCallbacks) {
196
+ _bunDynamicCallbacks = true;
197
+ build.onResolve({ filter: /.*/ }, _resolveBunDynamic);
198
+ const marker = new RegExp(String.raw`\?${BUN_VIRTUAL_MARKER}(?:&|$)`);
199
+ build.onLoad({ filter: marker }, _loadBunPath);
200
+ }
201
+ if (!_bunNamespaceLoader) {
202
+ _bunNamespaceLoader = true;
203
+ build.onLoad({
204
+ filter: /.*/,
205
+ namespace: BUN_NAMESPACE
206
+ }, _loadBunNamespaced);
207
+ }
208
+ }
209
+ function _updateBunRegistration(registration, changes) {
210
+ const { virtual } = registration;
211
+ const removed = [];
212
+ let dynamic = false;
213
+ for (const [key, source] of Object.entries(changes)) {
214
+ if (source === null) {
215
+ removed.push(key);
216
+ continue;
87
217
  }
88
- });
218
+ if (!Object.hasOwn(virtual, key)) {
219
+ const path = _keyPath(key);
220
+ if (_addBunKey(registration, key)) {
221
+ registration.dynamic.add(path);
222
+ _bunDynamicNames.add(_bunSpecifierName(path));
223
+ } else if (registration.namespaced.has(key)) _bunDynamicNames.add(_bunSpecifierName(key));
224
+ dynamic ||= !registration.modules.has(key);
225
+ }
226
+ virtual[key] = source;
227
+ }
228
+ if (dynamic) _installBunDynamicCallbacks(registration.build);
229
+ _bustBunModules(registration, expandVirtualInvalidation(virtual, Object.keys(changes), registration.importers));
230
+ for (const key of removed) _removeBunKey(registration, key);
231
+ }
232
+ function _removeBunKey(registration, key) {
233
+ const { virtual, paths } = registration;
234
+ delete virtual[key];
235
+ registration.namespaced.delete(key);
236
+ registration.modules.delete(key);
237
+ const path = _keyPath(key);
238
+ if (path === void 0 || paths.get(path) !== key) return;
239
+ paths.delete(path);
240
+ registration.dynamic.delete(path);
241
+ registration.removed.set(path, key);
242
+ for (const other of Object.keys(virtual)) if (_keyPath(other) === path) {
243
+ paths.set(path, other);
244
+ registration.removed.delete(path);
245
+ }
246
+ }
247
+ function _resolveBunModule(args) {
248
+ const specifier = _stripQuery(args.path);
249
+ const query = _stripBunMarker(args.path.slice(specifier.length));
250
+ let path;
251
+ if (isAbsolute(specifier)) path = resolve(specifier);
252
+ else if (/^\.\.?[\\/]/.test(specifier)) path = resolve(_bunImporterDir(args.importer), specifier);
253
+ for (const registration of _bunRegistrations) {
254
+ const namespaced = registration.namespaced.has(specifier);
255
+ const key = namespaced ? specifier : path && registration.paths.get(path);
256
+ if (!key) continue;
257
+ _addBunImporter(registration, key, args.importer);
258
+ const marker = !namespaced && registration.dynamic.has(path) ? BUN_VIRTUAL_MARKER : void 0;
259
+ const served = _bunVersioned((namespaced ? specifier : path) + _withBunMarker(query, marker), registration.versions.get(key));
260
+ _addToSetMap(registration.served, key, namespaced ? `${BUN_NAMESPACE}:${served}` : served);
261
+ return namespaced ? {
262
+ path: served,
263
+ namespace: BUN_NAMESPACE
264
+ } : { path: served };
265
+ }
266
+ for (const registration of _bunRegistrations) {
267
+ const key = path && registration.removed.get(path);
268
+ if (!key) continue;
269
+ _addBunImporter(registration, key, args.importer);
270
+ const served = _bunVersioned(path + _withBunMarker(query, BUN_DISK_MARKER), registration.versions.get(key));
271
+ _addToSetMap(registration.served, key, served);
272
+ return { path: served };
273
+ }
274
+ if (path && _bunReleasedPaths.has(path)) return { path: path + _withBunMarker(query, BUN_DISK_MARKER) };
275
+ }
276
+ function _resolveBunDynamic(args) {
277
+ const name = _bunSpecifierName(_stripQuery(args.path));
278
+ return _bunDynamicNames.has(name) ? _resolveBunModule(args) : void 0;
279
+ }
280
+ function _bunSpecifierName(specifier) {
281
+ return specifier.slice(Math.max(specifier.lastIndexOf("/"), specifier.lastIndexOf("\\")) + 1);
282
+ }
283
+ function _addBunImporter(registration, key, importerId) {
284
+ const importer = _bunKeyOf(registration, importerId);
285
+ if (importer !== void 0 && importer !== key) _addToSetMap(registration.importers, key, importer);
286
+ }
287
+ function _withBunMarker(query, marker) {
288
+ if (!marker) return query;
289
+ return `?${marker}` + (query ? `&${query.slice(1)}` : "");
290
+ }
291
+ function _stripBunMarker(query) {
292
+ for (const marker of [BUN_VIRTUAL_MARKER, BUN_DISK_MARKER]) {
293
+ if (query === `?${marker}`) return "";
294
+ if (query.startsWith(`?${marker}&`)) return `?${query.slice(marker.length + 2)}`;
295
+ }
296
+ return query;
297
+ }
298
+ function _loadBunPath(args) {
299
+ const path = _stripQuery(args.path);
300
+ for (const registration of _bunRegistrations) {
301
+ const key = registration.paths.get(path);
302
+ if (key !== void 0) return _serveBunModule(key, registration.virtual[key]);
303
+ }
304
+ }
305
+ function _loadBunNamespaced(args) {
306
+ const key = _stripQuery(args.path);
307
+ return _serveBunModule(key, _bunRegistrations.find((r) => r.namespaced.has(key))?.virtual[key]);
308
+ }
309
+ function _loadBunModule(key) {
310
+ return _serveBunModule(key, _bunRegistrations.find((r) => r.modules.has(key))?.virtual[key]);
311
+ }
312
+ function _serveBunModule(key, module) {
313
+ if (module === void 0) throw new Error(`Cannot find virtual module "${key}" (unregistered)`);
314
+ const format = virtualModuleFormat(key, module);
315
+ const source = typeof module === "string" ? module : module.source;
316
+ switch (format) {
317
+ case "json": return {
318
+ exports: { default: _parseBunJSON(key, source) },
319
+ loader: "object"
320
+ };
321
+ case "text": return {
322
+ exports: { default: source },
323
+ loader: "object"
324
+ };
325
+ case "bytes": return {
326
+ exports: { default: source.slice() },
327
+ loader: "object"
328
+ };
329
+ case "wasm": return {
330
+ exports: { default: new WebAssembly.Module(source) },
331
+ loader: "object"
332
+ };
333
+ }
334
+ return {
335
+ contents: source,
336
+ loader: format === "module-typescript" ? "ts" : format === "module" ? "js" : format
337
+ };
338
+ }
339
+ function _parseBunJSON(key, source) {
340
+ try {
341
+ return JSON.parse(source);
342
+ } catch (error) {
343
+ const message = `[env-runner] invalid JSON in virtual module "${key}": ${error?.message}`;
344
+ throw new SyntaxError(message, { cause: error });
345
+ }
346
+ }
347
+ function _bustBunModules(registration, keys) {
348
+ for (const key of keys) {
349
+ if (registration.modules.has(key)) {
350
+ registration.build.module(key, () => _loadBunModule(key));
351
+ continue;
352
+ }
353
+ registration.versions.set(key, ++registration.version);
354
+ for (const id of registration.served.get(key) ?? []) delete registration.cache[id];
355
+ registration.served.delete(key);
356
+ }
357
+ }
358
+ function _bunVersioned(id, version) {
359
+ const param = `v=${version}`;
360
+ if (!version || id.endsWith(`?${param}`) || id.endsWith(`&${param}`)) return id;
361
+ return id + (id.includes("?") ? "&" : "?") + param;
362
+ }
363
+ function _keyPath(key) {
364
+ if (key.startsWith("file:")) try {
365
+ return fileURLToPath(key);
366
+ } catch {
367
+ return;
368
+ }
369
+ return isAbsolute(key) ? resolve(key) : void 0;
370
+ }
371
+ function _bunKeyOf(registration, importer) {
372
+ const prefix = `${BUN_NAMESPACE}:`;
373
+ const id = _stripQuery(importer.startsWith(prefix) ? importer.slice(prefix.length) : importer);
374
+ return registration.paths.get(id) ?? (Object.hasOwn(registration.virtual, id) ? id : void 0);
89
375
  }
90
- function _transformSourceForDeno(specifier, source, stripTypeScriptTypes) {
91
- const format = virtualModuleFormat(specifier);
92
- if (format === "module-typescript") return stripVirtualTypeScript(specifier, source, stripTypeScriptTypes, {
376
+ function _bunImporterDir(importer) {
377
+ const path = _stripQuery(importer);
378
+ return isAbsolute(path) ? dirname(path) : process.cwd();
379
+ }
380
+ function _bunResolvable(specifier) {
381
+ const dot = specifier.lastIndexOf(".");
382
+ const code = dot === -1 ? 0 : specifier.charCodeAt(dot + 1);
383
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code > 127;
384
+ }
385
+ function _stripQuery(specifier) {
386
+ const qIndex = specifier.indexOf("?");
387
+ return qIndex === -1 ? specifier : specifier.slice(0, qIndex);
388
+ }
389
+ function _addToSetMap(map, key, value) {
390
+ let set = map.get(key);
391
+ if (!set) map.set(key, set = /* @__PURE__ */ new Set());
392
+ set.add(value);
393
+ }
394
+ function _escapeRegExp(value) {
395
+ return value.replace(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`);
396
+ }
397
+ async function _prepareVirtualModules(virtual, prepare) {
398
+ if (prepare !== _prepareForNode && !_cjsLexer) {
399
+ if (Object.entries(virtual).some(([key, module]) => module !== null && virtualModuleFormat(key, module).startsWith("commonjs"))) {
400
+ const lexer = await import("./lexer.mjs");
401
+ await lexer.init();
402
+ _cjsLexer = lexer;
403
+ }
404
+ }
405
+ const out = {};
406
+ for (const [key, module] of Object.entries(virtual)) out[key] = module === null ? module : prepare(key, module);
407
+ return out;
408
+ }
409
+ let _cjsLexer;
410
+ function _prepareForNode(key, module) {
411
+ const format = virtualModuleFormat(key, module);
412
+ if (format === "jsx" || format === "tsx") throw unsupportedVirtualJSXError(key, format, "Node.js");
413
+ return module;
414
+ }
415
+ function _prepareForBun(key, module) {
416
+ const format = virtualModuleFormat(key, module);
417
+ if (format !== "commonjs" && format !== "commonjs-typescript") return module;
418
+ return {
419
+ source: _commonJSToESM(key, typeof module === "string" ? module : module.source),
420
+ format: format === "commonjs" ? "module" : "module-typescript"
421
+ };
422
+ }
423
+ function _prepareForDeno(key, module, stripTypeScriptTypes) {
424
+ const format = virtualModuleFormat(key, module);
425
+ const source = typeof module === "string" ? module : module.source;
426
+ const strip = () => stripVirtualTypeScript(key, source, stripTypeScriptTypes, {
93
427
  requirement: "(custom load hooks bypass Deno's native type stripping)",
94
428
  remedy: "upgrade Deno"
95
429
  });
96
- if (format === "json") return `export default JSON.parse(${JSON.stringify(source)});`;
430
+ switch (format) {
431
+ case "module-typescript": return strip();
432
+ case "commonjs": return _commonJSToESM(key, source);
433
+ case "commonjs-typescript": return _commonJSToESM(key, strip());
434
+ case "json": return `export default JSON.parse(${JSON.stringify(source)});`;
435
+ case "text":
436
+ case "bytes":
437
+ case "wasm": return virtualModuleCode(format, source);
438
+ case "jsx":
439
+ case "tsx": throw unsupportedVirtualJSXError(key, format, "Deno");
440
+ }
97
441
  return source;
98
442
  }
443
+ function _commonJSToESM(key, source) {
444
+ const path = _keyPath(key);
445
+ const filename = JSON.stringify(path ?? key);
446
+ const dir = JSON.stringify(path ? dirname(path) : process.cwd());
447
+ const base = JSON.stringify(path ?? process.cwd() + sep);
448
+ let names = [];
449
+ try {
450
+ names = _cjsLexer.parse(source).exports;
451
+ } catch {}
452
+ const p = "__envRunner";
453
+ const lines = [
454
+ `import { createRequire as ${p}CreateRequire } from "node:module"; const ${p}Module = { exports: {} }; (function (exports, require, module, __filename, __dirname) {${source}`,
455
+ `}).call(${p}Module.exports, ${p}Module.exports, ${p}CreateRequire(${base}), ${p}Module, ${filename}, ${dir});`,
456
+ `const ${p}Exports = ${p}Module.exports;`,
457
+ `export { ${p}Exports as default, ${p}Exports as "module.exports" };`
458
+ ];
459
+ let index = 0;
460
+ for (const name of new Set(names)) if (name !== "default" && name !== "module.exports") {
461
+ const local = `${p}Export${index++}`;
462
+ lines.push(`const ${local} = ${p}Exports?.[${JSON.stringify(name)}];`, `export { ${local} as ${JSON.stringify(name)} };`);
463
+ }
464
+ return lines.join("\n") + "\n";
465
+ }
99
466
  const _noop = () => {};
100
467
  function _once(fn) {
101
468
  let done = false;
@@ -155,8 +522,13 @@ function toServerOptions(entry) {
155
522
  gracefulShutdown: false
156
523
  };
157
524
  }
158
- function isVirtualSpecifier(specifier, virtual) {
159
- return Boolean(specifier && virtual && Object.hasOwn(virtual, specifier));
525
+ function isVirtualSpecifier(specifier, virtual, matchPaths = false) {
526
+ if (!specifier || !virtual) return false;
527
+ return Object.hasOwn(virtual, specifier) || matchPaths && findVirtualPathKey(virtual, specifier) !== void 0;
528
+ }
529
+ function isVirtualEntry(entry, virtual = registeredVirtualModules()) {
530
+ const registerHooks = process.getBuiltinModule?.("node:module")?.registerHooks;
531
+ return isVirtualSpecifier(entry, virtual, typeof registerHooks === "function");
160
532
  }
161
533
  async function resolveEntry(entryPath, virtual) {
162
534
  const mod = await (virtual ? import(entryPath) : import(_toImportPath(entryPath)));
@@ -164,6 +536,19 @@ async function resolveEntry(entryPath, virtual) {
164
536
  if (typeof entry.fetch !== "function") throw new Error(`[env-runner] Entry module "${entryPath}" must export a \`fetch\` handler (export default { fetch(req) { ... } }).`);
165
537
  return entry;
166
538
  }
539
+ function formatInitError(error) {
540
+ const message = error?.message || String(error);
541
+ if (message.startsWith("[env-runner]") || /:\d+:\d+/.test(message)) return message;
542
+ const location = _errorLocation(error);
543
+ return location ? `${message} (at ${location})` : message;
544
+ }
545
+ function _errorLocation(error) {
546
+ const position = error?.position;
547
+ if (position?.file) return `${position.file}:${position.line}:${position.column}`;
548
+ const stack = typeof error?.stack === "string" ? error.stack : "";
549
+ const location = stack.startsWith(String(error?.name)) ? /\n\s+at (?:async )?(?:.* \()?([^\n()]+:\d+:\d+)\)?/.exec(stack)?.[1] : /^([^\n]+:\d+)\n/.exec(stack)?.[1];
550
+ return location && !/^(?:node|ext|native):/.test(location) ? location : void 0;
551
+ }
167
552
  function parseServerAddress(server) {
168
553
  const url = new URL(server.url);
169
554
  return {
@@ -184,18 +569,24 @@ function _toImportPath(entryPath) {
184
569
  if (isAbsolute(filePath)) return pathToFileURL(filePath).href + query;
185
570
  return entryPath;
186
571
  }
572
+ function _toReloadPath(entryPath) {
573
+ if (!("Bun" in globalThis)) return _toImportPath(entryPath);
574
+ if (!entryPath.startsWith("file:")) return entryPath;
575
+ const qIndex = entryPath.indexOf("?");
576
+ return qIndex === -1 ? fileURLToPath(entryPath) : fileURLToPath(entryPath.slice(0, qIndex)) + entryPath.slice(qIndex);
577
+ }
187
578
  let _reloadCounter = 0;
188
579
  async function _importFresh(entryPath, virtual) {
189
580
  const qIndex = entryPath.indexOf("?");
190
581
  const filePath = qIndex === -1 ? entryPath : entryPath.slice(0, qIndex);
191
582
  let mod;
192
- if (!virtual && existsSync(filePath)) {
193
- const code = readFileSync(filePath, "utf8");
194
- mod = await import("data:text/javascript;base64," + Buffer.from(code).toString("base64"));
195
- } else if (virtual && refreshVirtualModule(filePath)) mod = await import(filePath);
196
- else mod = await import(entryPath + (qIndex === -1 ? "?" : "&") + "__envRunnerReload=" + _reloadCounter++);
583
+ if (virtual && refreshVirtualModule(filePath)) mod = await import(filePath);
584
+ else {
585
+ const importPath = virtual ? entryPath : _toReloadPath(entryPath);
586
+ mod = await import(importPath + (importPath.includes("?") ? "&" : "?") + "__envRunnerReload=" + _reloadCounter++);
587
+ }
197
588
  const entry = mod.default || mod;
198
589
  if (typeof entry.fetch !== "function") throw new Error(`[env-runner] Entry module "${entryPath}" must export a \`fetch\` handler (export default { fetch(req) { ... } }).`);
199
590
  return entry;
200
591
  }
201
- export { RESERVED_RUNTIME_OPTIONS, RESERVED_SERVER_OPTIONS, handleInvalidateModule, isVirtualSpecifier, parseServerAddress, registerVirtualModules, reloadEntryModule, resolveEntry, toServerOptions };
592
+ export { RESERVED_RUNTIME_OPTIONS, RESERVED_SERVER_OPTIONS, formatInitError, handleUpdateVirtualModules, isVirtualEntry, parseServerAddress, registerVirtualModules, reloadEntryModule, resolveEntry, toServerOptions };
@@ -1,5 +1,4 @@
1
1
  import { BaseEnvRunner } from "./common-base-runner.mjs";
2
- import { hostEnv } from "./common-host-env.mjs";
3
2
  import { fileURLToPath } from "node:url";
4
3
  import { existsSync } from "node:fs";
5
4
  import { spawn } from "node:child_process";
@@ -45,10 +44,7 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
45
44
  ...execArgv || [],
46
45
  this._workerEntry
47
46
  ], {
48
- env: hostEnv({
49
- ENV_RUNNER_NAME: this._name,
50
- ENV_RUNNER_DATA: JSON.stringify(this._data || {})
51
- }),
47
+ env: this._processEnv(),
52
48
  stdio: [
53
49
  "pipe",
54
50
  "pipe",
@@ -68,7 +64,7 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
68
64
  }
69
65
  });
70
66
  child.on("message", (message) => {
71
- this._handleMessage(message);
67
+ this._handleProcessMessage(message);
72
68
  });
73
69
  child.stdout?.pipe(process.stdout);
74
70
  child.stderr?.pipe(process.stderr);
@@ -0,0 +1,2 @@
1
+ import { init, initSync, parse } from "./libs/cjs-module-lexer.mjs";
2
+ export { init, initSync, parse };
@@ -142,4 +142,9 @@ function init() {
142
142
  A = Q;
143
143
  })());
144
144
  }
145
- export { init, parse };
145
+ function initSync() {
146
+ if (A) return;
147
+ const B = new WebAssembly.Module(w()), { exports: Q } = new WebAssembly.Instance(B);
148
+ A = Q;
149
+ }
150
+ export { init, initSync, parse };