env-runner 0.1.6 → 0.1.7
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 +39 -9
- package/dist/_chunks/runner.mjs +17 -6
- package/dist/_chunks/runner2.d.mts +8 -0
- package/dist/_chunks/runner2.mjs +14 -2
- package/dist/_chunks/runner3.d.mts +19 -0
- package/dist/_chunks/runner3.mjs +62 -0
- package/dist/_chunks/runner4.d.mts +17 -0
- package/dist/_chunks/runner4.mjs +42 -0
- package/dist/_chunks/runner5.d.mts +17 -0
- package/dist/_chunks/runner5.mjs +47 -0
- package/dist/_chunks/server.mjs +3 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +3 -2
- package/dist/runners/deno-process/runner.mjs +0 -1
- package/dist/runners/deno-process/worker.mjs +31 -8
- package/dist/runners/miniflare/runner.mjs +0 -2
- package/dist/runners/netlify/runner.d.mts +3 -0
- package/dist/runners/netlify/runner.mjs +2 -0
- package/dist/runners/netlify/worker.d.mts +1 -0
- package/dist/runners/netlify/worker.mjs +43 -0
- package/dist/runners/node-worker/runner.d.mts +3 -19
- package/dist/runners/node-worker/runner.mjs +1 -61
- package/dist/runners/vercel/runner.d.mts +3 -0
- package/dist/runners/vercel/runner.mjs +2 -0
- package/dist/runners/vercel/worker.d.mts +1 -0
- package/dist/runners/vercel/worker.mjs +50 -0
- package/package.json +27 -17
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<!-- /automd -->
|
|
9
9
|
|
|
10
|
-
Generic environment runner for JavaScript runtimes. Run your server apps across Node.js worker threads, child processes, Bun, Deno, Cloudflare Workers (via miniflare), or in-process — with hot-reload, WebSocket proxying, and bidirectional messaging.
|
|
10
|
+
Generic environment runner for JavaScript runtimes. Run your server apps across Node.js worker threads, child processes, Bun, Deno, Cloudflare Workers (via miniflare), Vercel, Netlify, or in-process — with hot-reload, WebSocket proxying, and bidirectional messaging.
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
@@ -120,6 +120,8 @@ import { BunProcessEnvRunner } from "env-runner/runners/bun-process";
|
|
|
120
120
|
import { DenoProcessEnvRunner } from "env-runner/runners/deno-process";
|
|
121
121
|
import { SelfEnvRunner } from "env-runner/runners/self";
|
|
122
122
|
import { MiniflareEnvRunner } from "env-runner/runners/miniflare";
|
|
123
|
+
import { VercelEnvRunner } from "env-runner/runners/vercel";
|
|
124
|
+
import { NetlifyEnvRunner } from "env-runner/runners/netlify";
|
|
123
125
|
```
|
|
124
126
|
|
|
125
127
|
All runners implement the [`EnvRunner`](./src/types.ts) interface:
|
|
@@ -160,14 +162,16 @@ await runner.close();
|
|
|
160
162
|
|
|
161
163
|
**Available runners:**
|
|
162
164
|
|
|
163
|
-
| Runner | Isolation
|
|
164
|
-
| ---------------------- |
|
|
165
|
-
| `NodeWorkerEnvRunner` | Worker thread
|
|
166
|
-
| `NodeProcessEnvRunner` | Child process (`fork`)
|
|
167
|
-
| `BunProcessEnvRunner` | Bun or Node.js process
|
|
168
|
-
| `DenoProcessEnvRunner` | Deno process
|
|
169
|
-
| `SelfEnvRunner` | In-process
|
|
170
|
-
| `MiniflareEnvRunner` | Cloudflare Workers (miniflare)
|
|
165
|
+
| Runner | Isolation | IPC mechanism |
|
|
166
|
+
| ---------------------- | ------------------------------- | ---------------------------------- |
|
|
167
|
+
| `NodeWorkerEnvRunner` | Worker thread | `workerData` / `parentPort` |
|
|
168
|
+
| `NodeProcessEnvRunner` | Child process (`fork`) | `ENV_RUNNER_DATA` / `process.send` |
|
|
169
|
+
| `BunProcessEnvRunner` | Bun or Node.js process | `Bun.spawn` IPC or `fork()` |
|
|
170
|
+
| `DenoProcessEnvRunner` | Deno process | `deno run` with IPC channel |
|
|
171
|
+
| `SelfEnvRunner` | In-process | In-memory channel |
|
|
172
|
+
| `MiniflareEnvRunner` | Cloudflare Workers (miniflare) | WebSocket pair via `dispatchFetch` |
|
|
173
|
+
| `VercelEnvRunner` | Worker thread (Vercel context) | `workerData` / `parentPort` |
|
|
174
|
+
| `NetlifyEnvRunner` | Worker thread (Netlify context) | `workerData` / `parentPort` |
|
|
171
175
|
|
|
172
176
|
#### Miniflare Runner
|
|
173
177
|
|
|
@@ -289,6 +293,32 @@ const runner2 = new MiniflareEnvRunner({
|
|
|
289
293
|
// Fully destroy: runner.dispose() or MiniflareEnvRunner.disposeAll()
|
|
290
294
|
```
|
|
291
295
|
|
|
296
|
+
#### Vercel Runner
|
|
297
|
+
|
|
298
|
+
Simulates a Vercel deployment environment with automatic header injection (`x-vercel-deployment-url`, `x-vercel-forwarded-for`, forwarding headers) and global context.
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
import { VercelEnvRunner } from "env-runner/runners/vercel";
|
|
302
|
+
|
|
303
|
+
const runner = new VercelEnvRunner({
|
|
304
|
+
name: "my-app",
|
|
305
|
+
data: { entry: "./app.ts" },
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
#### Netlify Runner
|
|
310
|
+
|
|
311
|
+
Simulates a Netlify deployment environment with automatic header injection (`x-nf-client-connection-ip`, `x-nf-account-id`, `x-nf-site-id`, `x-nf-deploy-id`, `x-nf-deploy-context`, `x-nf-geo`, `x-nf-request-id`, forwarding headers) and `globalThis.Netlify` setup:
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
import { NetlifyEnvRunner } from "env-runner/runners/netlify";
|
|
315
|
+
|
|
316
|
+
const runner = new NetlifyEnvRunner({
|
|
317
|
+
name: "my-app",
|
|
318
|
+
data: { entry: "./app.ts" },
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
292
322
|
### Vite Environment API
|
|
293
323
|
|
|
294
324
|
env-runner provides helpers for integrating with Vite's [Environment API](https://vite.dev/guide/api-environment-runtimes.html):
|
package/dist/_chunks/runner.mjs
CHANGED
|
@@ -44,8 +44,9 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
|
|
|
44
44
|
};
|
|
45
45
|
const child = spawn("deno", [
|
|
46
46
|
"run",
|
|
47
|
-
"
|
|
47
|
+
"-A",
|
|
48
48
|
"--node-modules-dir=auto",
|
|
49
|
+
"--no-lock",
|
|
49
50
|
...execArgv || [],
|
|
50
51
|
this._workerEntry
|
|
51
52
|
], {
|
|
@@ -53,8 +54,7 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
|
|
|
53
54
|
stdio: [
|
|
54
55
|
"pipe",
|
|
55
56
|
"pipe",
|
|
56
|
-
"pipe"
|
|
57
|
-
"ipc"
|
|
57
|
+
"pipe"
|
|
58
58
|
]
|
|
59
59
|
});
|
|
60
60
|
const exited = new Promise((resolve) => {
|
|
@@ -63,7 +63,9 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
|
|
|
63
63
|
const handle = {
|
|
64
64
|
pid: child.pid,
|
|
65
65
|
kill: () => child.kill(),
|
|
66
|
-
send: (message) =>
|
|
66
|
+
send: (message) => {
|
|
67
|
+
child.stdin.write(JSON.stringify(message) + "\n");
|
|
68
|
+
},
|
|
67
69
|
exited,
|
|
68
70
|
_exitCode: void 0,
|
|
69
71
|
removeAllListeners: () => child.removeAllListeners()
|
|
@@ -78,8 +80,17 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner {
|
|
|
78
80
|
this.close(error);
|
|
79
81
|
}
|
|
80
82
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
let buffer = "";
|
|
84
|
+
child.stdout.on("data", (chunk) => {
|
|
85
|
+
buffer += chunk.toString();
|
|
86
|
+
let newlineIdx;
|
|
87
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
88
|
+
const line = buffer.slice(0, newlineIdx);
|
|
89
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
90
|
+
if (line.startsWith("{")) try {
|
|
91
|
+
this._handleMessage(JSON.parse(line));
|
|
92
|
+
} catch {}
|
|
93
|
+
}
|
|
83
94
|
});
|
|
84
95
|
this.#process = handle;
|
|
85
96
|
}
|
|
@@ -46,6 +46,14 @@ interface MiniflareEnvRunnerOptions {
|
|
|
46
46
|
persistent?: boolean;
|
|
47
47
|
/** Wrap the user's `fetch` in a try/catch that returns structured JSON error responses. Default: `true`. */
|
|
48
48
|
captureErrors?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Export conditions for bare-specifier module resolution in the module
|
|
51
|
+
* fallback service. Ensures packages with conditional exports (e.g.
|
|
52
|
+
* `"workerd"`) resolve to the correct entry instead of the Node.js one.
|
|
53
|
+
*
|
|
54
|
+
* Defaults to `["workerd", "worker"]`.
|
|
55
|
+
*/
|
|
56
|
+
exportConditions?: string[];
|
|
49
57
|
}
|
|
50
58
|
declare class MiniflareEnvRunner extends BaseEnvRunner {
|
|
51
59
|
#private;
|
package/dist/_chunks/runner2.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { proxyUpgrade } from "httpxy";
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { basename, dirname, resolve } from "node:path";
|
|
8
|
+
import { resolveModulePath } from "exsolve";
|
|
8
9
|
//#region src/runners/miniflare/wrapper.ts
|
|
9
10
|
const IPC_PATH$1 = "/__env_runner_ipc";
|
|
10
11
|
/** Service binding name used for cross-request IPC (worker → runner). */
|
|
@@ -207,6 +208,7 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
207
208
|
#cacheKey;
|
|
208
209
|
#exports;
|
|
209
210
|
#captureErrors;
|
|
211
|
+
#exportConditions;
|
|
210
212
|
constructor(opts) {
|
|
211
213
|
super({
|
|
212
214
|
...opts,
|
|
@@ -217,6 +219,7 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
217
219
|
this.#persistent = opts.persistent ?? false;
|
|
218
220
|
this.#exports = opts.exports ?? {};
|
|
219
221
|
this.#captureErrors = opts.captureErrors ?? true;
|
|
222
|
+
this.#exportConditions = opts.exportConditions ?? ["workerd", "worker"];
|
|
220
223
|
this.#init();
|
|
221
224
|
}
|
|
222
225
|
/** Dispose all persistent Miniflare instances from the cache. */
|
|
@@ -399,6 +402,7 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
399
402
|
if (!options.unsafeModuleFallbackService) {
|
|
400
403
|
const _require = createRequire(resolvedEntry);
|
|
401
404
|
const _transformRequest = this.#transformRequest;
|
|
405
|
+
const _exportConditions = this.#exportConditions;
|
|
402
406
|
options.unsafeUseModuleFallbackService = true;
|
|
403
407
|
const modulePathMap = /* @__PURE__ */ new Map();
|
|
404
408
|
const _cjsLexerReady = ensureCjsLexer();
|
|
@@ -422,6 +426,7 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
422
426
|
const referrerKey = referrer.startsWith("/") ? referrer.slice(1) : referrer;
|
|
423
427
|
const referrerReal = modulePathMap.get(referrerKey);
|
|
424
428
|
const contextRequire = referrerReal ? createRequire(referrerReal) : _require;
|
|
429
|
+
if (cleanRaw.startsWith("cloudflare:")) return new Response(null, { status: 404 });
|
|
425
430
|
if (cleanRaw.startsWith("node:")) {
|
|
426
431
|
const nodeName = cleanRaw.slice(5);
|
|
427
432
|
try {
|
|
@@ -430,7 +435,11 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
430
435
|
return new Response(null, { status: 404 });
|
|
431
436
|
}
|
|
432
437
|
} else try {
|
|
433
|
-
resolvedPath =
|
|
438
|
+
resolvedPath = resolveModulePath(cleanRaw, {
|
|
439
|
+
from: referrerReal || resolvedEntry,
|
|
440
|
+
conditions: _exportConditions,
|
|
441
|
+
try: true
|
|
442
|
+
}) || contextRequire.resolve(cleanRaw);
|
|
434
443
|
} catch {
|
|
435
444
|
const name = cleanSpecifier.startsWith("/") ? cleanSpecifier.slice(1) : cleanSpecifier;
|
|
436
445
|
return Response.json({
|
|
@@ -486,7 +495,10 @@ var MiniflareEnvRunner = class extends BaseEnvRunner {
|
|
|
486
495
|
}
|
|
487
496
|
}
|
|
488
497
|
if (this.#persistent && entryPath) {
|
|
489
|
-
this.#cacheKey = computeCacheKey(entryPath,
|
|
498
|
+
this.#cacheKey = computeCacheKey(entryPath, {
|
|
499
|
+
...this.#miniflareOptions,
|
|
500
|
+
_exportConditions: this.#exportConditions
|
|
501
|
+
});
|
|
490
502
|
const cached = _miniflareCache.get(this.#cacheKey);
|
|
491
503
|
if (cached) {
|
|
492
504
|
this.#miniflare = cached.mf;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { u as WorkerHooks } from "./types.mjs";
|
|
2
|
+
import { n as EnvRunnerData, t as BaseEnvRunner } from "./base-runner.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/runners/node-worker/runner.d.ts
|
|
5
|
+
declare class NodeWorkerEnvRunner extends BaseEnvRunner {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(opts: {
|
|
8
|
+
name: string;
|
|
9
|
+
workerEntry?: string;
|
|
10
|
+
hooks?: WorkerHooks;
|
|
11
|
+
data?: EnvRunnerData;
|
|
12
|
+
});
|
|
13
|
+
sendMessage(message: unknown): void;
|
|
14
|
+
protected _hasRuntime(): boolean;
|
|
15
|
+
protected _runtimeType(): string;
|
|
16
|
+
protected _closeRuntime(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { NodeWorkerEnvRunner as t };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { t as BaseEnvRunner } from "./base-runner.mjs";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { Worker } from "node:worker_threads";
|
|
5
|
+
//#region src/runners/node-worker/runner.ts
|
|
6
|
+
let _defaultEntry;
|
|
7
|
+
var NodeWorkerEnvRunner = class extends BaseEnvRunner {
|
|
8
|
+
#worker;
|
|
9
|
+
constructor(opts) {
|
|
10
|
+
_defaultEntry ||= fileURLToPath(import.meta.resolve("env-runner/runners/node-worker/worker"));
|
|
11
|
+
super({
|
|
12
|
+
...opts,
|
|
13
|
+
workerEntry: opts.workerEntry || _defaultEntry
|
|
14
|
+
});
|
|
15
|
+
this.#initWorker();
|
|
16
|
+
}
|
|
17
|
+
sendMessage(message) {
|
|
18
|
+
if (!this.#worker) throw new Error("Worker thread should be initialized before sending messages.");
|
|
19
|
+
this.#worker.postMessage(message);
|
|
20
|
+
}
|
|
21
|
+
_hasRuntime() {
|
|
22
|
+
return Boolean(this.#worker);
|
|
23
|
+
}
|
|
24
|
+
_runtimeType() {
|
|
25
|
+
return "worker";
|
|
26
|
+
}
|
|
27
|
+
async _closeRuntime() {
|
|
28
|
+
if (!this.#worker) return;
|
|
29
|
+
this.#worker.removeAllListeners();
|
|
30
|
+
await this.#worker.terminate().catch((error) => {
|
|
31
|
+
console.error(error);
|
|
32
|
+
});
|
|
33
|
+
this.#worker = void 0;
|
|
34
|
+
}
|
|
35
|
+
#initWorker() {
|
|
36
|
+
if (!existsSync(this._workerEntry)) {
|
|
37
|
+
this.close(`worker entry not found in "${this._workerEntry}".`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const worker = new Worker(this._workerEntry, {
|
|
41
|
+
env: { ...process.env },
|
|
42
|
+
workerData: {
|
|
43
|
+
name: this._name,
|
|
44
|
+
...this._data
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
worker.once("exit", (code) => {
|
|
48
|
+
worker._exitCode = code;
|
|
49
|
+
this.close(`worker exited with code ${code}`);
|
|
50
|
+
});
|
|
51
|
+
worker.once("error", (error) => {
|
|
52
|
+
console.error(`Worker error:`, error);
|
|
53
|
+
this.close(error);
|
|
54
|
+
});
|
|
55
|
+
worker.on("message", (message) => {
|
|
56
|
+
this._handleMessage(message);
|
|
57
|
+
});
|
|
58
|
+
this.#worker = worker;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
export { NodeWorkerEnvRunner as t };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { u as WorkerHooks } from "./types.mjs";
|
|
2
|
+
import { n as EnvRunnerData } from "./base-runner.mjs";
|
|
3
|
+
import { t as NodeWorkerEnvRunner } from "./runner3.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/runners/vercel/runner.d.ts
|
|
6
|
+
declare class VercelEnvRunner extends NodeWorkerEnvRunner {
|
|
7
|
+
constructor(opts: {
|
|
8
|
+
name: string;
|
|
9
|
+
workerEntry?: string;
|
|
10
|
+
hooks?: WorkerHooks;
|
|
11
|
+
data?: EnvRunnerData;
|
|
12
|
+
});
|
|
13
|
+
fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;
|
|
14
|
+
protected _runtimeType(): string;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { VercelEnvRunner as t };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { t as NodeWorkerEnvRunner } from "./runner3.mjs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
//#region src/runners/vercel/runner.ts
|
|
4
|
+
let _defaultEntry;
|
|
5
|
+
var VercelEnvRunner = class extends NodeWorkerEnvRunner {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
_defaultEntry ||= fileURLToPath(import.meta.resolve("env-runner/runners/vercel/worker"));
|
|
8
|
+
super({
|
|
9
|
+
...opts,
|
|
10
|
+
workerEntry: opts.workerEntry || _defaultEntry
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async fetch(input, init) {
|
|
14
|
+
const headers = new Headers(input instanceof Request ? input.headers : init?.headers);
|
|
15
|
+
if (this._address && this._address.port != null && !headers.has("x-vercel-deployment-url")) {
|
|
16
|
+
const host = this._address.host || "127.0.0.1";
|
|
17
|
+
headers.set("x-vercel-deployment-url", `http://${host}:${this._address.port}`);
|
|
18
|
+
}
|
|
19
|
+
const clientIp = headers.get("x-forwarded-for")?.split(",")[0]?.trim() || headers.get("x-real-ip") || "127.0.0.1";
|
|
20
|
+
if (!headers.has("x-vercel-forwarded-for")) headers.set("x-vercel-forwarded-for", clientIp);
|
|
21
|
+
if (!headers.has("x-forwarded-for")) headers.set("x-forwarded-for", clientIp);
|
|
22
|
+
if (!headers.has("x-real-ip")) headers.set("x-real-ip", clientIp);
|
|
23
|
+
try {
|
|
24
|
+
const url = new URL(input instanceof Request ? input.url : input.toString());
|
|
25
|
+
if (!headers.has("x-forwarded-proto")) headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
|
|
26
|
+
if (!headers.has("x-forwarded-host")) headers.set("x-forwarded-host", headers.get("host") || url.host);
|
|
27
|
+
} catch {}
|
|
28
|
+
if (input instanceof Request) return super.fetch(new Request(input, {
|
|
29
|
+
...init,
|
|
30
|
+
headers
|
|
31
|
+
}));
|
|
32
|
+
return super.fetch(input, {
|
|
33
|
+
...init,
|
|
34
|
+
headers
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
_runtimeType() {
|
|
38
|
+
return "vercel";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { VercelEnvRunner as t };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { u as WorkerHooks } from "./types.mjs";
|
|
2
|
+
import { n as EnvRunnerData } from "./base-runner.mjs";
|
|
3
|
+
import { t as NodeWorkerEnvRunner } from "./runner3.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/runners/netlify/runner.d.ts
|
|
6
|
+
declare class NetlifyEnvRunner extends NodeWorkerEnvRunner {
|
|
7
|
+
constructor(opts: {
|
|
8
|
+
name: string;
|
|
9
|
+
workerEntry?: string;
|
|
10
|
+
hooks?: WorkerHooks;
|
|
11
|
+
data?: EnvRunnerData;
|
|
12
|
+
});
|
|
13
|
+
fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;
|
|
14
|
+
protected _runtimeType(): string;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { NetlifyEnvRunner as t };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { t as NodeWorkerEnvRunner } from "./runner3.mjs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
//#region src/runners/netlify/runner.ts
|
|
4
|
+
let _defaultEntry;
|
|
5
|
+
var NetlifyEnvRunner = class extends NodeWorkerEnvRunner {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
_defaultEntry ||= fileURLToPath(import.meta.resolve("env-runner/runners/netlify/worker"));
|
|
8
|
+
super({
|
|
9
|
+
...opts,
|
|
10
|
+
workerEntry: opts.workerEntry || _defaultEntry
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async fetch(input, init) {
|
|
14
|
+
const headers = new Headers(input instanceof Request ? input.headers : init?.headers);
|
|
15
|
+
const clientIp = headers.get("x-forwarded-for")?.split(",")[0]?.trim() || headers.get("x-real-ip") || "127.0.0.1";
|
|
16
|
+
if (!headers.has("x-nf-client-connection-ip")) headers.set("x-nf-client-connection-ip", clientIp);
|
|
17
|
+
if (!headers.has("x-nf-account-id")) headers.set("x-nf-account-id", "0");
|
|
18
|
+
if (!headers.has("x-nf-site-id")) headers.set("x-nf-site-id", "0");
|
|
19
|
+
if (!headers.has("x-nf-deploy-id")) headers.set("x-nf-deploy-id", "0");
|
|
20
|
+
if (!headers.has("x-nf-deploy-context")) headers.set("x-nf-deploy-context", "dev");
|
|
21
|
+
if (!headers.has("x-nf-geo")) headers.set("x-nf-geo", btoa(JSON.stringify({
|
|
22
|
+
city: "localhost",
|
|
23
|
+
country: { code: "dev" }
|
|
24
|
+
})));
|
|
25
|
+
if (!headers.has("x-nf-request-id")) headers.set("x-nf-request-id", crypto.randomUUID());
|
|
26
|
+
if (!headers.has("x-forwarded-for")) headers.set("x-forwarded-for", clientIp);
|
|
27
|
+
if (!headers.has("x-real-ip")) headers.set("x-real-ip", clientIp);
|
|
28
|
+
try {
|
|
29
|
+
const url = new URL(input instanceof Request ? input.url : input.toString());
|
|
30
|
+
if (!headers.has("x-forwarded-proto")) headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
|
|
31
|
+
if (!headers.has("x-forwarded-host")) headers.set("x-forwarded-host", headers.get("host") || url.host);
|
|
32
|
+
} catch {}
|
|
33
|
+
if (input instanceof Request) return super.fetch(new Request(input, {
|
|
34
|
+
...init,
|
|
35
|
+
headers
|
|
36
|
+
}));
|
|
37
|
+
return super.fetch(input, {
|
|
38
|
+
...init,
|
|
39
|
+
headers
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
_runtimeType() {
|
|
43
|
+
return "netlify";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { NetlifyEnvRunner as t };
|
package/dist/_chunks/server.mjs
CHANGED
|
@@ -175,7 +175,9 @@ const loaders = {
|
|
|
175
175
|
"bun-process": () => import("env-runner/runners/bun-process").then((m) => m.BunProcessEnvRunner),
|
|
176
176
|
"deno-process": () => import("env-runner/runners/deno-process").then((m) => m.DenoProcessEnvRunner),
|
|
177
177
|
self: () => import("env-runner/runners/self").then((m) => m.SelfEnvRunner),
|
|
178
|
-
miniflare: () => import("env-runner/runners/miniflare").then((m) => m.MiniflareEnvRunner)
|
|
178
|
+
miniflare: () => import("env-runner/runners/miniflare").then((m) => m.MiniflareEnvRunner),
|
|
179
|
+
vercel: () => import("env-runner/runners/vercel").then((m) => m.VercelEnvRunner),
|
|
180
|
+
netlify: () => import("env-runner/runners/netlify").then((m) => m.NetlifyEnvRunner)
|
|
179
181
|
};
|
|
180
182
|
async function loadRunner(runner, opts) {
|
|
181
183
|
return new (await (loaders[runner]()))(opts);
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,8 @@ import { a as RunnerMessageListener, c as UpgradeHandler, i as RPCOptions, l as
|
|
|
2
2
|
import { n as EnvRunnerData, t as BaseEnvRunner } from "./_chunks/base-runner.mjs";
|
|
3
3
|
import { t as DenoProcessEnvRunner } from "./_chunks/runner.mjs";
|
|
4
4
|
import { i as TransformResult, n as MiniflareEnvRunnerOptions, r as MiniflareExportInfo, t as MiniflareEnvRunner } from "./_chunks/runner2.mjs";
|
|
5
|
+
import { t as VercelEnvRunner } from "./_chunks/runner4.mjs";
|
|
6
|
+
import { t as NetlifyEnvRunner } from "./_chunks/runner5.mjs";
|
|
5
7
|
import { ServerOptions } from "srvx";
|
|
6
8
|
import { Hooks } from "crossws";
|
|
7
9
|
|
|
@@ -46,13 +48,15 @@ declare class RunnerManager implements EnvRunner {
|
|
|
46
48
|
}
|
|
47
49
|
//#endregion
|
|
48
50
|
//#region src/loader.d.ts
|
|
49
|
-
type RunnerName = "node-worker" | "node-process" | "bun-process" | "deno-process" | "self" | "miniflare";
|
|
51
|
+
type RunnerName = "node-worker" | "node-process" | "bun-process" | "deno-process" | "self" | "miniflare" | "vercel" | "netlify";
|
|
50
52
|
interface LoadRunnerOptions {
|
|
51
53
|
name: string;
|
|
52
54
|
workerEntry?: string;
|
|
53
55
|
hooks?: WorkerHooks;
|
|
54
56
|
data?: EnvRunnerData;
|
|
55
57
|
execArgv?: string[];
|
|
58
|
+
/** Additional runner-specific options (passed through to the runner constructor). */
|
|
59
|
+
[key: string]: unknown;
|
|
56
60
|
}
|
|
57
61
|
declare function loadRunner(runner: RunnerName, opts: LoadRunnerOptions): Promise<EnvRunner>;
|
|
58
62
|
//#endregion
|
|
@@ -113,4 +117,4 @@ interface AppEntry {
|
|
|
113
117
|
ipc?: AppEntryIPC;
|
|
114
118
|
}
|
|
115
119
|
//#endregion
|
|
116
|
-
export { type AppEntry, type AppEntryIPC, type AppEntryIPCContext, BaseEnvRunner, DenoProcessEnvRunner, type EnvRunnerData as DenoProcessEnvRunnerData, type EnvRunnerData, type EnvRunner, EnvServer, type EnvServerOptions, type FetchHandler, type LoadRunnerOptions, MiniflareEnvRunner, type MiniflareEnvRunnerOptions, type MiniflareExportInfo, type NodeUpgradeContext, type RPCOptions, RunnerManager, type RunnerMessageListener, type RunnerName, type RunnerRPCHooks, type TransformResult, type UpgradeContext, type UpgradeHandler, type WorkerAddress, type WorkerHooks, loadRunner };
|
|
120
|
+
export { type AppEntry, type AppEntryIPC, type AppEntryIPCContext, BaseEnvRunner, DenoProcessEnvRunner, type EnvRunnerData as DenoProcessEnvRunnerData, type EnvRunnerData, type EnvRunner, EnvServer, type EnvServerOptions, type FetchHandler, type LoadRunnerOptions, MiniflareEnvRunner, type MiniflareEnvRunnerOptions, type MiniflareExportInfo, NetlifyEnvRunner, type NodeUpgradeContext, type RPCOptions, RunnerManager, type RunnerMessageListener, type RunnerName, type RunnerRPCHooks, type TransformResult, type UpgradeContext, type UpgradeHandler, VercelEnvRunner, type WorkerAddress, type WorkerHooks, loadRunner };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as BaseEnvRunner } from "./_chunks/base-runner.mjs";
|
|
2
2
|
import { n as loadRunner, r as RunnerManager, t as EnvServer } from "./_chunks/server.mjs";
|
|
3
3
|
import { t as DenoProcessEnvRunner } from "./_chunks/runner.mjs";
|
|
4
|
-
import "./_chunks/libs/cjs-module-lexer.mjs";
|
|
5
4
|
import { t as MiniflareEnvRunner } from "./_chunks/runner2.mjs";
|
|
6
|
-
|
|
5
|
+
import { t as VercelEnvRunner } from "./_chunks/runner4.mjs";
|
|
6
|
+
import { t as NetlifyEnvRunner } from "./_chunks/runner5.mjs";
|
|
7
|
+
export { BaseEnvRunner, DenoProcessEnvRunner, EnvServer, MiniflareEnvRunner, NetlifyEnvRunner, RunnerManager, VercelEnvRunner, loadRunner };
|
|
@@ -4,7 +4,9 @@ import { plugin } from "crossws/server";
|
|
|
4
4
|
//#region src/runners/deno-process/worker.ts
|
|
5
5
|
const data = JSON.parse(process.env.ENV_RUNNER_DATA || "{}");
|
|
6
6
|
let entry = await resolveEntry(data.entry);
|
|
7
|
-
const
|
|
7
|
+
const _stdout = globalThis.Deno?.stdout ? { write: (s) => globalThis.Deno.stdout.writeSync(new TextEncoder().encode(s)) } : process.stdout;
|
|
8
|
+
const sendMessage = (message) => _stdout.write(JSON.stringify(message) + "\n");
|
|
9
|
+
const _stdin = globalThis.Deno?.stdin?.readable || process.stdin;
|
|
8
10
|
const server = serve({
|
|
9
11
|
port: 0,
|
|
10
12
|
hostname: "127.0.0.1",
|
|
@@ -23,20 +25,40 @@ if (entry.upgrade) server.node?.server?.on("upgrade", (req, socket, head) => {
|
|
|
23
25
|
} });
|
|
24
26
|
});
|
|
25
27
|
if (entry.ipc) await entry.ipc.onOpen?.({ sendMessage });
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
sendMessage({ address: parseServerAddress(server) });
|
|
29
|
+
async function readMessages() {
|
|
30
|
+
const decoder = new TextDecoder();
|
|
31
|
+
let buffer = "";
|
|
32
|
+
for await (const chunk of _stdin) {
|
|
33
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
34
|
+
let newlineIdx;
|
|
35
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
36
|
+
const line = buffer.slice(0, newlineIdx);
|
|
37
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
38
|
+
if (!line) continue;
|
|
39
|
+
let message;
|
|
40
|
+
try {
|
|
41
|
+
message = JSON.parse(line);
|
|
42
|
+
} catch {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
await handleMessage(message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function handleMessage(message) {
|
|
28
50
|
if (message?.event === "shutdown") {
|
|
29
51
|
Promise.resolve(entry.ipc?.onClose?.()).then(() => server.close()).then(() => {
|
|
30
|
-
|
|
52
|
+
sendMessage({ event: "exit" });
|
|
31
53
|
});
|
|
32
54
|
return;
|
|
33
55
|
}
|
|
34
56
|
if (message?.event === "reload-module") {
|
|
35
57
|
try {
|
|
36
58
|
entry = await reloadEntryModule(data.entry, entry, sendMessage);
|
|
37
|
-
|
|
59
|
+
sendMessage({ event: "module-reloaded" });
|
|
38
60
|
} catch (error) {
|
|
39
|
-
|
|
61
|
+
sendMessage({
|
|
40
62
|
event: "module-reloaded",
|
|
41
63
|
error: error?.message || String(error)
|
|
42
64
|
});
|
|
@@ -44,13 +66,14 @@ process.on("message", async (message) => {
|
|
|
44
66
|
return;
|
|
45
67
|
}
|
|
46
68
|
if (message?.type === "ping") {
|
|
47
|
-
|
|
69
|
+
sendMessage({
|
|
48
70
|
type: "pong",
|
|
49
71
|
data: message.data
|
|
50
72
|
});
|
|
51
73
|
return;
|
|
52
74
|
}
|
|
53
75
|
entry.ipc?.onMessage?.(message);
|
|
54
|
-
}
|
|
76
|
+
}
|
|
77
|
+
readMessages().catch(() => {});
|
|
55
78
|
//#endregion
|
|
56
79
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/runners/netlify/worker.ts
|
|
2
|
+
try {
|
|
3
|
+
const { startRuntime } = await import("@netlify/runtime");
|
|
4
|
+
startRuntime({
|
|
5
|
+
deployID: "0",
|
|
6
|
+
siteID: "0",
|
|
7
|
+
env: {
|
|
8
|
+
get: (key) => process.env[key],
|
|
9
|
+
has: (key) => key in process.env,
|
|
10
|
+
set: (key, value) => {
|
|
11
|
+
process.env[key] = value;
|
|
12
|
+
},
|
|
13
|
+
delete: (key) => {
|
|
14
|
+
delete process.env[key];
|
|
15
|
+
},
|
|
16
|
+
toObject: () => ({ ...process.env })
|
|
17
|
+
},
|
|
18
|
+
getRequestContext: () => null,
|
|
19
|
+
cache: { getCacheAPIContext: () => null }
|
|
20
|
+
});
|
|
21
|
+
} catch {
|
|
22
|
+
if (!process.env.__ENV_RUNNER_NETLIFY_WARNED) {
|
|
23
|
+
process.env.__ENV_RUNNER_NETLIFY_WARNED = "1";
|
|
24
|
+
console.warn("@netlify/runtime is not installed. Install it for full Netlify runtime emulation: npx nypm i -D @netlify/runtime");
|
|
25
|
+
}
|
|
26
|
+
globalThis.Netlify = {
|
|
27
|
+
context: null,
|
|
28
|
+
env: {
|
|
29
|
+
get: (key) => process.env[key],
|
|
30
|
+
has: (key) => key in process.env,
|
|
31
|
+
set: (key, value) => {
|
|
32
|
+
process.env[key] = value;
|
|
33
|
+
},
|
|
34
|
+
delete: (key) => {
|
|
35
|
+
delete process.env[key];
|
|
36
|
+
},
|
|
37
|
+
toObject: () => ({ ...process.env })
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
await import("../node-worker/worker.mjs");
|
|
42
|
+
//#endregion
|
|
43
|
+
export {};
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
//#region src/runners/node-worker/runner.d.ts
|
|
5
|
-
declare class NodeWorkerEnvRunner extends BaseEnvRunner {
|
|
6
|
-
#private;
|
|
7
|
-
constructor(opts: {
|
|
8
|
-
name: string;
|
|
9
|
-
workerEntry?: string;
|
|
10
|
-
hooks?: WorkerHooks;
|
|
11
|
-
data?: EnvRunnerData;
|
|
12
|
-
});
|
|
13
|
-
sendMessage(message: unknown): void;
|
|
14
|
-
protected _hasRuntime(): boolean;
|
|
15
|
-
protected _runtimeType(): string;
|
|
16
|
-
protected _closeRuntime(): Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { type EnvRunnerData, NodeWorkerEnvRunner };
|
|
1
|
+
import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs";
|
|
2
|
+
import { t as NodeWorkerEnvRunner } from "../../_chunks/runner3.mjs";
|
|
3
|
+
export { EnvRunnerData, NodeWorkerEnvRunner };
|
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { Worker } from "node:worker_threads";
|
|
5
|
-
//#region src/runners/node-worker/runner.ts
|
|
6
|
-
let _defaultEntry;
|
|
7
|
-
var NodeWorkerEnvRunner = class extends BaseEnvRunner {
|
|
8
|
-
#worker;
|
|
9
|
-
constructor(opts) {
|
|
10
|
-
_defaultEntry ||= fileURLToPath(import.meta.resolve("env-runner/runners/node-worker/worker"));
|
|
11
|
-
super({
|
|
12
|
-
...opts,
|
|
13
|
-
workerEntry: opts.workerEntry || _defaultEntry
|
|
14
|
-
});
|
|
15
|
-
this.#initWorker();
|
|
16
|
-
}
|
|
17
|
-
sendMessage(message) {
|
|
18
|
-
if (!this.#worker) throw new Error("Node env worker should be initialized before sending messages.");
|
|
19
|
-
this.#worker.postMessage(message);
|
|
20
|
-
}
|
|
21
|
-
_hasRuntime() {
|
|
22
|
-
return Boolean(this.#worker);
|
|
23
|
-
}
|
|
24
|
-
_runtimeType() {
|
|
25
|
-
return "worker";
|
|
26
|
-
}
|
|
27
|
-
async _closeRuntime() {
|
|
28
|
-
if (!this.#worker) return;
|
|
29
|
-
this.#worker.removeAllListeners();
|
|
30
|
-
await this.#worker.terminate().catch((error) => {
|
|
31
|
-
console.error(error);
|
|
32
|
-
});
|
|
33
|
-
this.#worker = void 0;
|
|
34
|
-
}
|
|
35
|
-
#initWorker() {
|
|
36
|
-
if (!existsSync(this._workerEntry)) {
|
|
37
|
-
this.close(`worker entry not found in "${this._workerEntry}".`);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
const worker = new Worker(this._workerEntry, {
|
|
41
|
-
env: { ...process.env },
|
|
42
|
-
workerData: {
|
|
43
|
-
name: this._name,
|
|
44
|
-
...this._data
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
worker.once("exit", (code) => {
|
|
48
|
-
worker._exitCode = code;
|
|
49
|
-
this.close(`worker exited with code ${code}`);
|
|
50
|
-
});
|
|
51
|
-
worker.once("error", (error) => {
|
|
52
|
-
console.error(`Worker error:`, error);
|
|
53
|
-
this.close(error);
|
|
54
|
-
});
|
|
55
|
-
worker.on("message", (message) => {
|
|
56
|
-
this._handleMessage(message);
|
|
57
|
-
});
|
|
58
|
-
this.#worker = worker;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
//#endregion
|
|
1
|
+
import { t as NodeWorkerEnvRunner } from "../../_chunks/runner3.mjs";
|
|
62
2
|
export { NodeWorkerEnvRunner };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/runners/vercel/worker.ts
|
|
2
|
+
const SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
|
|
3
|
+
const waitUntilPromises = /* @__PURE__ */ new Set();
|
|
4
|
+
const cacheStore = /* @__PURE__ */ new Map();
|
|
5
|
+
const cacheTags = /* @__PURE__ */ new Set();
|
|
6
|
+
globalThis[SYMBOL_FOR_REQ_CONTEXT] = { get: () => ({
|
|
7
|
+
waitUntil(promise) {
|
|
8
|
+
waitUntilPromises.add(promise);
|
|
9
|
+
promise.finally(() => waitUntilPromises.delete(promise));
|
|
10
|
+
},
|
|
11
|
+
cache: {
|
|
12
|
+
async get(key) {
|
|
13
|
+
const entry = cacheStore.get(key);
|
|
14
|
+
if (!entry) return null;
|
|
15
|
+
if (entry.ttl && entry.lastModified + entry.ttl * 1e3 < Date.now()) {
|
|
16
|
+
cacheStore.delete(key);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(entry.value);
|
|
20
|
+
},
|
|
21
|
+
async set(key, value, options) {
|
|
22
|
+
cacheStore.set(key, {
|
|
23
|
+
value: JSON.stringify(value ?? null),
|
|
24
|
+
lastModified: Date.now(),
|
|
25
|
+
ttl: options?.ttl,
|
|
26
|
+
tags: new Set(options?.tags || [])
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
async delete(key) {
|
|
30
|
+
cacheStore.delete(key);
|
|
31
|
+
},
|
|
32
|
+
async expireTag(tag) {
|
|
33
|
+
const tags = Array.isArray(tag) ? tag : [tag];
|
|
34
|
+
for (const [key, entry] of cacheStore) if (tags.some((t) => entry.tags.has(t))) cacheStore.delete(key);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
purge: {
|
|
38
|
+
invalidateByTag: (_tag) => Promise.resolve(),
|
|
39
|
+
dangerouslyDeleteByTag: (_tag) => Promise.resolve(),
|
|
40
|
+
invalidateBySrcImage: (_src) => Promise.resolve(),
|
|
41
|
+
dangerouslyDeleteBySrcImage: (_src) => Promise.resolve()
|
|
42
|
+
},
|
|
43
|
+
addCacheTag(tag) {
|
|
44
|
+
for (const t of Array.isArray(tag) ? tag : [tag]) cacheTags.add(t);
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
}
|
|
47
|
+
}) };
|
|
48
|
+
await import("../node-worker/worker.mjs");
|
|
49
|
+
//#endregion
|
|
50
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "env-runner",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Generic environment runner for JavaScript runtimes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "unjs/env-runner",
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"./runners/deno-process/worker": "./dist/runners/deno-process/worker.mjs",
|
|
25
25
|
"./runners/self": "./dist/runners/self/runner.mjs",
|
|
26
26
|
"./runners/miniflare": "./dist/runners/miniflare/runner.mjs",
|
|
27
|
+
"./runners/vercel": "./dist/runners/vercel/runner.mjs",
|
|
28
|
+
"./runners/vercel/worker": "./dist/runners/vercel/worker.mjs",
|
|
29
|
+
"./runners/netlify": "./dist/runners/netlify/runner.mjs",
|
|
30
|
+
"./runners/netlify/worker": "./dist/runners/netlify/worker.mjs",
|
|
27
31
|
"./vite": "./dist/vite.mjs"
|
|
28
32
|
},
|
|
29
33
|
"scripts": {
|
|
@@ -39,31 +43,37 @@
|
|
|
39
43
|
},
|
|
40
44
|
"dependencies": {
|
|
41
45
|
"crossws": "^0.4.4",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
46
|
+
"exsolve": "^1.0.8",
|
|
47
|
+
"httpxy": "^0.5.0",
|
|
48
|
+
"srvx": "^0.11.13"
|
|
44
49
|
},
|
|
45
50
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
+
"@netlify/runtime": "^4.1.20",
|
|
52
|
+
"@types/node": "^25.5.0",
|
|
53
|
+
"@typescript/native-preview": "^7.0.0-dev.20260327.2",
|
|
54
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
55
|
+
"automd": "^0.4.3",
|
|
56
|
+
"changelogen": "^0.6.2",
|
|
51
57
|
"cjs-module-lexer": "^2.2.0",
|
|
52
|
-
"env-runner-fixture": "link
|
|
53
|
-
"miniflare": "^4.
|
|
54
|
-
"obuild": "
|
|
55
|
-
"oxfmt": "
|
|
56
|
-
"oxlint": "
|
|
57
|
-
"typescript": "
|
|
58
|
-
"vitest": "
|
|
58
|
+
"env-runner-fixture": "link:",
|
|
59
|
+
"miniflare": "^4.20260317.3",
|
|
60
|
+
"obuild": "^0.4.32",
|
|
61
|
+
"oxfmt": "^0.42.0",
|
|
62
|
+
"oxlint": "^1.57.0",
|
|
63
|
+
"typescript": "^6.0.2",
|
|
64
|
+
"vitest": "^4.1.2"
|
|
59
65
|
},
|
|
60
66
|
"peerDependencies": {
|
|
61
|
-
"
|
|
67
|
+
"@netlify/runtime": "^4",
|
|
68
|
+
"miniflare": "^4.20260317.3"
|
|
62
69
|
},
|
|
63
70
|
"peerDependenciesMeta": {
|
|
64
71
|
"miniflare": {
|
|
65
72
|
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"@netlify/runtime": {
|
|
75
|
+
"optional": true
|
|
66
76
|
}
|
|
67
77
|
},
|
|
68
|
-
"packageManager": "pnpm@10.
|
|
78
|
+
"packageManager": "pnpm@10.33.0"
|
|
69
79
|
}
|