env-runner 0.1.14 → 0.1.16

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 CHANGED
@@ -73,9 +73,36 @@ await envServer.reload();
73
73
  // Use with any HTTP server
74
74
  const server = serve({
75
75
  fetch: (request) => envServer.fetch(request),
76
+ // Proxy WebSocket upgrades to the worker (see "WebSocket proxying" below)
77
+ plugins: [await envServer.wsSrvxPlugin()],
76
78
  });
77
79
  ```
78
80
 
81
+ #### WebSocket proxying
82
+
83
+ To proxy WebSocket upgrades to the worker, attach the plugin returned by
84
+ `wsSrvxPlugin()` (available on both `RunnerManager` and `EnvServer`) to your
85
+ [srvx](https://srvx.h3.dev) server:
86
+
87
+ ```ts
88
+ const server = serve({
89
+ fetch: (request) => envServer.fetch(request),
90
+ plugins: [await envServer.wsSrvxPlugin()],
91
+ });
92
+ ```
93
+
94
+ The plugin picks the proxy strategy by **host** runtime:
95
+
96
+ - **Node** — proxies the raw upgrade socket to the worker (transparent
97
+ passthrough; subprotocol/extension negotiation stays end-to-end).
98
+ - **Bun/Deno** — those runtimes serve natively and expose no Node upgrade
99
+ socket, so the client WebSocket is terminated with [crossws](https://crossws.h3.dev)
100
+ and bridged to the worker over a standard `WebSocket` client.
101
+
102
+ It reads the active runner lazily, so it keeps working across hot-reloads, and
103
+ waits for the worker to become ready before proxying. Your entry module should
104
+ expose WebSocket hooks via the `websocket` field (see [Workers](#workers)).
105
+
79
106
  ### Manager (`RunnerManager`)
80
107
 
81
108
  Proxy manager for hot-reload with message queueing and listener forwarding:
@@ -147,7 +174,8 @@ await using runner = new NodeProcessEnvRunner({
147
174
  // Relative URLs are resolved against a placeholder origin
148
175
  const response = await runner.fetch("/api");
149
176
 
150
- // Proxy WebSocket upgrades
177
+ // Proxy a raw WebSocket upgrade to the worker (Node host only — low-level;
178
+ // prefer `manager.wsSrvxPlugin()` for cross-runtime proxying)
151
179
  runner.upgrade?.({ node: { req, socket, head } });
152
180
 
153
181
  // Wait for runner to be ready
@@ -50,6 +50,7 @@ declare abstract class BaseEnvRunner implements EnvRunner, AsyncDisposable {
50
50
  data?: EnvRunnerData;
51
51
  });
52
52
  get ready(): boolean;
53
+ get address(): WorkerAddress | undefined;
53
54
  fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;
54
55
  upgrade(context: {
55
56
  node: {
@@ -23,13 +23,20 @@ var BaseEnvRunner = class {
23
23
  get ready() {
24
24
  return Boolean(!this.closed && this._address && this._hasRuntime());
25
25
  }
26
+ get address() {
27
+ return this._address;
28
+ }
26
29
  async fetch(input, init) {
27
30
  for (let i = 0; i < 5 && !this._address && !this.closed; i++) await new Promise((r) => setTimeout(r, 100 * Math.pow(2, i)));
28
31
  if (!this._address) return new Response(`${this._runtimeType()} env runner is unavailable`, { status: 503 });
29
32
  return proxyFetch(this._address, this._resolveFetchInput(input), init);
30
33
  }
31
34
  async upgrade(context) {
32
- if (!this.ready || !this._address) return;
35
+ if (!this.ready) await this.waitForReady().catch(() => {});
36
+ if (!this.ready || !this._address) {
37
+ context.node.socket.destroy();
38
+ return;
39
+ }
33
40
  try {
34
41
  await proxyUpgrade(this._address, context.node.req, context.node.socket, context.node.head);
35
42
  } catch {}
@@ -40,7 +47,7 @@ var BaseEnvRunner = class {
40
47
  offMessage(listener) {
41
48
  this._messageListeners.delete(listener);
42
49
  }
43
- waitForReady(timeout = 5e3) {
50
+ waitForReady(timeout = 15e3) {
44
51
  if (this.ready) return Promise.resolve();
45
52
  if (this.closed) return Promise.reject(/* @__PURE__ */ new Error("Runner closed before becoming ready"));
46
53
  return new Promise((resolve, reject) => {
@@ -6,8 +6,9 @@ async function registerVirtualModules(virtual) {
6
6
  if (!virtual || Object.keys(virtual).length === 0) return _noop;
7
7
  const { registerHooks, stripTypeScriptTypes } = await import("node:module");
8
8
  if (typeof registerHooks === "function") {
9
+ const isDeno = "Deno" in globalThis;
9
10
  let transformSource;
10
- if ("Deno" in globalThis) {
11
+ if (isDeno) {
11
12
  transformSource = (specifier, source) => _transformSourceForDeno(specifier, source, stripTypeScriptTypes);
12
13
  const transformed = {};
13
14
  for (const [specifier, source] of Object.entries(virtual)) transformed[specifier] = transformSource(specifier, source);
@@ -18,7 +19,7 @@ async function registerVirtualModules(virtual) {
18
19
  versions: /* @__PURE__ */ new Map(),
19
20
  transformSource
20
21
  };
21
- const hooks = registerHooks(createVirtualHooks(virtual, registration.versions));
22
+ const hooks = registerHooks(createVirtualHooks(virtual, registration.versions, void 0, isDeno));
22
23
  _hooksRegistrations.unshift(registration);
23
24
  return _once(() => {
24
25
  const index = _hooksRegistrations.indexOf(registration);
@@ -1,60 +1,60 @@
1
- var ImportType;
2
1
  (function(A) {
3
- A[A.Static = 1] = "Static", A[A.Dynamic = 2] = "Dynamic", A[A.ImportMeta = 3] = "ImportMeta", A[A.StaticSourcePhase = 4] = "StaticSourcePhase", A[A.DynamicSourcePhase = 5] = "DynamicSourcePhase", A[A.StaticDeferPhase = 6] = "StaticDeferPhase", A[A.DynamicDeferPhase = 7] = "DynamicDeferPhase";
4
- })(ImportType || (ImportType = {}));
2
+ return A[A.Static = 1] = "Static", A[A.Dynamic = 2] = "Dynamic", A[A.ImportMeta = 3] = "ImportMeta", A[A.StaticSourcePhase = 4] = "StaticSourcePhase", A[A.DynamicSourcePhase = 5] = "DynamicSourcePhase", A[A.StaticDeferPhase = 6] = "StaticDeferPhase", A[A.DynamicDeferPhase = 7] = "DynamicDeferPhase", A;
3
+ })({});
5
4
  const A = 1 === new Uint8Array(new Uint16Array([1]).buffer)[0];
6
5
  function parse(E, g = "@") {
7
- if (!C) return init.then((() => parse(E)));
8
- const I = E.length + 1, o = (C.__heap_base.value || C.__heap_base) + 4 * I - C.memory.buffer.byteLength;
9
- o > 0 && C.memory.grow(Math.ceil(o / 65536));
10
- const D = C.sa(I - 1);
11
- if ((A ? B : Q)(E, new Uint16Array(C.memory.buffer, D, I)), !C.parse()) throw Object.assign(/* @__PURE__ */ new Error(`Parse error ${g}:${E.slice(0, C.e()).split("\n").length}:${C.e() - E.lastIndexOf("\n", C.e() - 1)}`), { idx: C.e() });
12
- const K = [], k = [];
6
+ if (!C) return init.then(() => parse(E));
7
+ const I = E.length + 1, D = (C.__heap_base.value || C.__heap_base) + 4 * I - C.memory.buffer.byteLength;
8
+ D > 0 && C.memory.grow(Math.ceil(D / 65536));
9
+ const w = C.sa(I - 1);
10
+ if ((A ? B : Q)(E, new Uint16Array(C.memory.buffer, w, I)), !C.parse()) throw Object.assign(/* @__PURE__ */ new Error(`Parse error ${g}:${E.slice(0, C.e()).split("\n").length}:${C.e() - E.lastIndexOf("\n", C.e() - 1)}`), { idx: C.e() });
11
+ const i = [], G = [];
13
12
  for (; C.ri();) {
14
- const A = C.is(), Q = C.ie(), B = C.it(), g = C.ai(), I = C.id(), o = C.ss(), D = C.se();
15
- let k;
16
- C.ip() && (k = w(E.slice(-1 === I ? A - 1 : A, -1 === I ? Q + 1 : Q)));
17
- const i = [];
13
+ const A = C.is(), Q = C.ie(), B = C.it(), g = C.ai(), I = C.id(), D = C.ss(), w = C.se();
14
+ let G;
15
+ C.ip() && (G = o(E.slice(-1 === I ? A - 1 : A, -1 === I ? Q + 1 : Q)));
16
+ const R = [];
18
17
  for (C.rsa(); C.ra();) {
19
18
  const A = C.aks(), Q = C.ake(), B = C.avs(), g = C.ave();
20
- i.push([N(E.slice(A, Q)), N(E.slice(B, g))]);
19
+ R.push([s(E.slice(A, Q)), s(E.slice(B, g))]);
21
20
  }
22
- K.push({
23
- n: k,
21
+ i.push({
22
+ n: G,
24
23
  t: B,
25
24
  s: A,
26
25
  e: Q,
27
- ss: o,
28
- se: D,
26
+ ss: D,
27
+ se: w,
29
28
  d: I,
30
29
  a: g,
31
- at: i.length > 0 ? i : null
30
+ at: R.length > 0 ? R : null
32
31
  });
33
32
  }
34
33
  for (; C.re();) {
35
- const A = C.es(), Q = C.ee(), B = C.els(), g = C.ele(), I = N(E.slice(A, Q)), o = B < 0 ? void 0 : N(E.slice(B, g));
36
- k.push({
34
+ const A = C.es(), Q = C.ee(), B = C.els(), g = C.ele(), I = C.ess(), D = s(E.slice(A, Q)), w = B < 0 ? void 0 : s(E.slice(B, g));
35
+ G.push({
37
36
  s: A,
38
37
  e: Q,
39
38
  ls: B,
40
39
  le: g,
41
- n: I,
42
- ln: o
40
+ ss: I,
41
+ n: D,
42
+ ln: w
43
43
  });
44
44
  }
45
- function w(A) {
45
+ function o(A) {
46
46
  try {
47
47
  return (0, eval)(A);
48
48
  } catch (A) {}
49
49
  }
50
- function N(A) {
50
+ function s(A) {
51
51
  if (!A) return A;
52
52
  const Q = A[0];
53
- return ("\"" === Q || "'" === Q) && w(A) || A;
53
+ return ("\"" === Q || "'" === Q) && o(A) || A;
54
54
  }
55
55
  return [
56
- K,
57
- k,
56
+ i,
57
+ G,
58
58
  !!C.f(),
59
59
  !!C.ms()
60
60
  ];
@@ -74,10 +74,10 @@ function B(A, Q) {
74
74
  }
75
75
  let C;
76
76
  const E = () => {
77
- return A = "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", "undefined" != typeof Buffer ? Buffer.from(A, "base64") : Uint8Array.from(atob(A), ((A) => A.charCodeAt(0)));
77
+ return A = "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", "undefined" != typeof Buffer ? Buffer.from(A, "base64") : Uint8Array.from(atob(A), (A) => A.charCodeAt(0));
78
78
  var A;
79
79
  };
80
- const init = WebAssembly.compile(E()).then(WebAssembly.instantiate).then((({ exports: A }) => {
80
+ const init = WebAssembly.compile(E()).then(WebAssembly.instantiate).then(({ exports: A }) => {
81
81
  C = A;
82
- }));
82
+ });
83
83
  export { init, parse };
@@ -180,13 +180,16 @@ export default {
180
180
  };
181
181
  `;
182
182
  }
183
+ function importWrangler() {
184
+ return import("wrangler");
185
+ }
183
186
  let _warnedNoWrangler = false;
184
187
  const WRANGLER_CONFIG_FILENAMES = [
185
188
  "wrangler.json",
186
189
  "wrangler.jsonc",
187
190
  "wrangler.toml"
188
191
  ];
189
- const WRANGLER_OPTION_DENYLIST = new Set([
192
+ const WRANGLER_OPTION_DENYLIST = /* @__PURE__ */ new Set([
190
193
  "name",
191
194
  "script",
192
195
  "scriptPath",
@@ -223,7 +226,7 @@ async function loadWranglerConfig(opt, env, entryPath) {
223
226
  } else configPath = findWranglerConfig(entryPath);
224
227
  let wrangler;
225
228
  try {
226
- wrangler = await import("wrangler");
229
+ wrangler = await importWrangler();
227
230
  } catch {
228
231
  if (!_warnedNoWrangler) {
229
232
  _warnedNoWrangler = true;
@@ -248,7 +251,7 @@ function mergeWranglerMiniflareOptions(base, override) {
248
251
  const out = { ...base };
249
252
  for (const [key, value] of Object.entries(override)) {
250
253
  const prev = out[key];
251
- if (Array.isArray(value) && Array.isArray(prev)) out[key] = [...new Set([...prev, ...value])];
254
+ if (Array.isArray(value) && Array.isArray(prev)) out[key] = [.../* @__PURE__ */ new Set([...prev, ...value])];
252
255
  else if (isPlainObject(value) && isPlainObject(prev)) out[key] = {
253
256
  ...prev,
254
257
  ...value
@@ -527,7 +530,7 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
527
530
  modules: true,
528
531
  ...wranglerOptions,
529
532
  ...this.#miniflareOptions,
530
- compatibilityFlags: [...new Set([
533
+ compatibilityFlags: [.../* @__PURE__ */ new Set([
531
534
  "nodejs_compat",
532
535
  ...wranglerFlags,
533
536
  ...userFlags
@@ -1,4 +1,34 @@
1
1
  import { watch } from "node:fs";
2
+ async function createRunnerWSProxyPlugin(getRunner) {
3
+ const isBun = "Bun" in globalThis;
4
+ const isDeno = "Deno" in globalThis;
5
+ if (!isBun && !isDeno) return (server) => {
6
+ server.ready().then(() => {
7
+ (server.node?.server)?.on("upgrade", (req, socket, head) => {
8
+ getRunner()?.upgrade?.({ node: {
9
+ req,
10
+ socket,
11
+ head
12
+ } });
13
+ });
14
+ }).catch(() => {});
15
+ };
16
+ const { createWebSocketProxy } = await import("crossws");
17
+ const { plugin } = isBun ? await import("crossws/server/bun") : await import("crossws/server/deno");
18
+ const proxy = createWebSocketProxy({ target: async (peer) => {
19
+ await getRunner()?.waitForReady?.().catch(() => {});
20
+ return resolveWSProxyTarget(getRunner()?.address, peer.request.url);
21
+ } });
22
+ return plugin({ resolve: () => proxy });
23
+ }
24
+ function resolveWSProxyTarget(address, requestUrl) {
25
+ if (!address) throw new Error("env runner worker is not ready");
26
+ const { pathname, search } = new URL(requestUrl);
27
+ if (address.socketPath) return `ws+unix://${address.socketPath}:${pathname}${search}`;
28
+ if (!address.port) throw new Error("env runner worker is not ready");
29
+ const host = address.host || "127.0.0.1";
30
+ return `ws://${host.includes(":") && !host.startsWith("[") ? `[${host}]` : host}:${address.port}${pathname}${search}`;
31
+ }
2
32
  var RunnerManager = class {
3
33
  _runner;
4
34
  _messageQueue = [];
@@ -9,6 +39,7 @@ var RunnerManager = class {
9
39
  _pendingModuleReload;
10
40
  _closeListeners = /* @__PURE__ */ new Set();
11
41
  _readyListeners = /* @__PURE__ */ new Set();
42
+ _readyRejectors = /* @__PURE__ */ new Set();
12
43
  constructor(runner) {
13
44
  if (runner) this._attach(runner);
14
45
  }
@@ -18,6 +49,9 @@ var RunnerManager = class {
18
49
  get closed() {
19
50
  return this._closed;
20
51
  }
52
+ get address() {
53
+ return this._runner?.address;
54
+ }
21
55
  async reload(runner) {
22
56
  this._reloading = true;
23
57
  try {
@@ -49,9 +83,17 @@ var RunnerManager = class {
49
83
  });
50
84
  return this._pendingModuleReload;
51
85
  }
52
- upgrade = (context) => {
53
- this._runner?.upgrade?.(context);
86
+ upgrade = async (context) => {
87
+ const runner = await this._waitForRunner();
88
+ if (!runner?.upgrade) {
89
+ context.node.socket.destroy();
90
+ return;
91
+ }
92
+ await runner.upgrade(context);
54
93
  };
94
+ wsSrvxPlugin() {
95
+ return createRunnerWSProxyPlugin(() => this);
96
+ }
55
97
  sendMessage(message) {
56
98
  if (!this._runner || !this._runner.ready) {
57
99
  this._messageQueue.push(message);
@@ -67,21 +109,31 @@ var RunnerManager = class {
67
109
  this._messageListeners.delete(listener);
68
110
  this._runner?.offMessage(listener);
69
111
  }
70
- waitForReady(timeout = 5e3) {
112
+ waitForReady(timeout = 15e3) {
71
113
  if (this.ready) return Promise.resolve();
114
+ if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("Runner closed before becoming ready"));
72
115
  return new Promise((resolve, reject) => {
116
+ const cleanup = () => {
117
+ clearTimeout(timer);
118
+ this.offMessage(listener);
119
+ this._readyRejectors.delete(onClose);
120
+ };
73
121
  const timer = setTimeout(() => {
74
- this._messageListeners.delete(listener);
122
+ cleanup();
75
123
  reject(/* @__PURE__ */ new Error("Runner did not become ready in time"));
76
124
  }, timeout);
77
125
  const listener = (message) => {
78
126
  if (message?.address || this.ready) {
79
- clearTimeout(timer);
80
- this._messageListeners.delete(listener);
127
+ cleanup();
81
128
  resolve();
82
129
  }
83
130
  };
84
- this._messageListeners.add(listener);
131
+ const onClose = () => {
132
+ cleanup();
133
+ reject(/* @__PURE__ */ new Error("Runner closed before becoming ready"));
134
+ };
135
+ this.onMessage(listener);
136
+ this._readyRejectors.add(onClose);
85
137
  });
86
138
  }
87
139
  rpc(name, data, opts) {
@@ -124,6 +176,8 @@ var RunnerManager = class {
124
176
  async close() {
125
177
  this._closed = true;
126
178
  this._messageQueue.length = 0;
179
+ for (const rejectReady of this._readyRejectors) rejectReady();
180
+ this._readyRejectors.clear();
127
181
  const runner = this._runner;
128
182
  this._detach();
129
183
  if (runner) await runner.close();
@@ -62,6 +62,8 @@ interface EnvRunner extends RunnerRPCHooks, AsyncDisposable {
62
62
  readonly ready: boolean;
63
63
  /** Whether the runner has been closed. */
64
64
  readonly closed: boolean;
65
+ /** Address the worker is listening at, once ready (`undefined` before then). */
66
+ readonly address?: WorkerAddress;
65
67
  /** Proxy an HTTP request to the worker. */
66
68
  fetch: FetchHandler;
67
69
  /** Proxy a WebSocket upgrade request to the worker. */
@@ -44,7 +44,9 @@ function _checkVercelOidcToken(token = process.env.VERCEL_OIDC_TOKEN) {
44
44
  let _defaultEntry;
45
45
  const _podId = Math.random().toString(32).slice(-5);
46
46
  function generateVercelId() {
47
- return `dev1::${_podId}-${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`;
47
+ const timestamp = Date.now().toString(36);
48
+ const random = randomBytes(6).toString("hex");
49
+ return `dev1::${_podId}-${timestamp}-${random}`;
48
50
  }
49
51
  var VercelEnvRunner = class extends NodeWorkerEnvRunner {
50
52
  constructor(opts) {
@@ -4,7 +4,7 @@ async function resolveVirtualModules(virtual) {
4
4
  return Object.fromEntries(entries);
5
5
  }
6
6
  const VIRTUAL_SCHEME = "virtual:";
7
- function createVirtualHooks(virtual, versions, parentURL = _defaultParentURL()) {
7
+ function createVirtualHooks(virtual, versions, parentURL = _defaultParentURL(), forcePlainModule = false) {
8
8
  const resolve = (specifier, context, nextResolve) => {
9
9
  const key = _stripQuery(specifier);
10
10
  if (Object.hasOwn(virtual, key)) {
@@ -24,7 +24,7 @@ function createVirtualHooks(virtual, versions, parentURL = _defaultParentURL())
24
24
  if (url.startsWith(VIRTUAL_SCHEME)) {
25
25
  const key = _stripQuery(decodeURIComponent(url.slice(8)));
26
26
  if (Object.hasOwn(virtual, key)) return {
27
- format: virtualModuleFormat(key),
27
+ format: forcePlainModule ? "module" : virtualModuleFormat(key),
28
28
  source: virtual[key],
29
29
  shortCircuit: true
30
30
  };
package/dist/cli.mjs CHANGED
@@ -50,16 +50,10 @@ const server = serve({
50
50
  port: values.port,
51
51
  hostname: values.host,
52
52
  gracefulShutdown: false,
53
- fetch: (request) => envServer.fetch(request)
53
+ fetch: (request) => envServer.fetch(request),
54
+ plugins: [await envServer.wsSrvxPlugin()]
54
55
  });
55
56
  await server.ready();
56
- server.node?.server?.on("upgrade", (req, socket, head) => {
57
- envServer.upgrade({ node: {
58
- req,
59
- socket,
60
- head
61
- } });
62
- });
63
57
  for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, async () => {
64
58
  console.log(`\n\x1B[2mShutting down...\x1B[0m`);
65
59
  await envServer.close();
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ import { DenoProcessEnvRunner } from "./_chunks/deno-process-runner.mjs";
4
4
  import { MiniflareEnvRunner, MiniflareEnvRunnerOptions, MiniflareExportInfo, TransformResult } from "./_chunks/miniflare-runner.mjs";
5
5
  import { VercelEnvRunner } from "./_chunks/vercel-runner.mjs";
6
6
  import { NetlifyEnvRunner } from "./_chunks/netlify-runner.mjs";
7
- import { ServerOptions } from "srvx";
7
+ import { ServerOptions, ServerPlugin } from "srvx";
8
8
  import { Hooks } from "crossws";
9
9
  /**
10
10
  * Manages an active `EnvRunner` instance, proxying all calls to it.
@@ -20,9 +20,11 @@ declare class RunnerManager implements EnvRunner, AsyncDisposable {
20
20
  private _pendingModuleReload;
21
21
  private _closeListeners;
22
22
  private _readyListeners;
23
+ private _readyRejectors;
23
24
  constructor(runner?: EnvRunner);
24
25
  get ready(): boolean;
25
26
  get closed(): boolean;
27
+ get address(): WorkerAddress | undefined;
26
28
  /**
27
29
  * Replace the active runner with a new one. Closes the previous runner.
28
30
  *
@@ -41,6 +43,14 @@ declare class RunnerManager implements EnvRunner, AsyncDisposable {
41
43
  */
42
44
  private _flushInvalidation;
43
45
  upgrade: UpgradeHandler;
46
+ /**
47
+ * Create a runtime-native WebSocket reverse-proxy plugin for the public srvx
48
+ * server. Attach it via `serve({ plugins: [await manager.wsSrvxPlugin()] })`:
49
+ * on Node it proxies the raw upgrade socket to the worker, and on Bun/Deno it
50
+ * bridges the WebSocket with crossws. The plugin reads the active runner
51
+ * lazily, so it keeps working across hot-reloads.
52
+ */
53
+ wsSrvxPlugin(): Promise<ServerPlugin>;
44
54
  sendMessage(message: unknown): void;
45
55
  onMessage(listener: RunnerMessageListener): void;
46
56
  offMessage(listener: RunnerMessageListener): void;
@@ -1,6 +1,6 @@
1
1
  import { handleInvalidateModule, isVirtualSpecifier, parseServerAddress, registerVirtualModules, reloadEntryModule, resolveEntry } from "../../_chunks/common-worker-utils.mjs";
2
2
  import { serve } from "srvx";
3
- import { plugin } from "crossws/server/node";
3
+ import { plugin } from "crossws/server";
4
4
  process.on("disconnect", () => process.exit(0));
5
5
  const data = JSON.parse(process.env.ENV_RUNNER_DATA || "{}");
6
6
  const sendMessage = (message) => process.send(message);
@@ -1,7 +1,7 @@
1
1
  import { handleInvalidateModule, isVirtualSpecifier, parseServerAddress, registerVirtualModules, reloadEntryModule, resolveEntry } from "../../_chunks/common-worker-utils.mjs";
2
2
  import { parentPort, workerData } from "node:worker_threads";
3
3
  import { serve } from "srvx";
4
- import { plugin } from "crossws/server/node";
4
+ import { plugin } from "crossws/server";
5
5
  const data = workerData || {};
6
6
  const sendMessage = (message) => parentPort?.postMessage(message);
7
7
  const virtualEntry = isVirtualSpecifier(data.entry, data.virtual);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "env-runner",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Generic environment runner for JavaScript runtimes.",
5
5
  "license": "MIT",
6
6
  "repository": "unjs/env-runner",
@@ -43,33 +43,33 @@
43
43
  "typecheck": "tsgo --noEmit --skipLibCheck"
44
44
  },
45
45
  "dependencies": {
46
- "crossws": "^0.4.5",
47
- "exsolve": "^1.0.8",
48
- "httpxy": "^0.5.3",
49
- "srvx": "^0.11.16"
46
+ "crossws": "^0.4.8",
47
+ "exsolve": "^1.1.0",
48
+ "httpxy": "^0.5.4",
49
+ "srvx": "^0.11.19"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@netlify/runtime": "^4.1.25",
53
- "@types/node": "^25.9.2",
54
- "@typescript/native-preview": "7.0.0-dev.20260521.1",
55
- "@vercel/queue": "^0.2.1",
56
- "@vitest/coverage-v8": "^4.1.8",
53
+ "@types/node": "^26.0.1",
54
+ "@typescript/native-preview": "7.0.0-dev.20260629.1",
55
+ "@vercel/queue": "^0.3.1",
56
+ "@vitest/coverage-v8": "^4.1.9",
57
57
  "automd": "^0.4.3",
58
58
  "changelogen": "^0.6.2",
59
59
  "cjs-module-lexer": "^2.2.0",
60
60
  "env-runner-fixture": "link:",
61
- "es-module-lexer": "^2.1.0",
62
- "miniflare": "^4.20260603.0",
63
- "obuild": "^0.4.36",
64
- "oxfmt": "^0.51.0",
65
- "oxlint": "^1.69.0",
61
+ "es-module-lexer": "^2.2.0",
62
+ "miniflare": "^4.20260625.0",
63
+ "obuild": "^0.4.37",
64
+ "oxfmt": "^0.56.0",
65
+ "oxlint": "^1.71.0",
66
66
  "typescript": "^6.0.3",
67
- "vitest": "^4.1.8",
68
- "wrangler": "^4.99.0"
67
+ "vitest": "^4.1.9",
68
+ "wrangler": "^4.105.0"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@netlify/runtime": "^4.1.23",
72
- "@vercel/queue": "^0.2.0",
72
+ "@vercel/queue": ">=0.2.0",
73
73
  "miniflare": "^4.20260515.0",
74
74
  "wrangler": "^4.0.0"
75
75
  },
@@ -87,5 +87,5 @@
87
87
  "optional": true
88
88
  }
89
89
  },
90
- "packageManager": "pnpm@11.5.2"
90
+ "packageManager": "pnpm@11.9.0"
91
91
  }