env-runner
Advanced tools
| import { MessageHandler, RetryHandler } from "@vercel/queue"; | ||
| interface VercelQueueDevConsumer { | ||
| /** Topic name. Wildcard patterns (e.g. `"user-*"`) are supported. */ | ||
| topic: string; | ||
| /** Function invoked with each delivered message. */ | ||
| handler: MessageHandler; | ||
| /** | ||
| * Logical consumer identifier. Re-registering with the same group on the same | ||
| * topic replaces the previous handler (HMR-safe). Use distinct groups to fan | ||
| * a topic out to multiple coexisting handlers. | ||
| * | ||
| * @default "env-runner-vercel-dev" | ||
| */ | ||
| consumerGroup?: string; | ||
| /** | ||
| * Lock duration for in-flight messages. Forwarded to the SDK's | ||
| * `coreHandleCallback`. | ||
| */ | ||
| visibilityTimeoutSeconds?: number; | ||
| /** | ||
| * Convenience: rescheduled re-delivery delay applied when the handler throws. | ||
| * Equivalent to `retry: () => ({ afterSeconds })`. Ignored if `retry` is set. | ||
| */ | ||
| retryAfterSeconds?: number; | ||
| /** | ||
| * Full retry handler. Receives the thrown error and message metadata; return | ||
| * `{ afterSeconds }` to reschedule, `{ acknowledge: true }` to drop, or | ||
| * `undefined` to let the error propagate. | ||
| */ | ||
| retry?: RetryHandler; | ||
| } | ||
| /** | ||
| * Bind a handler to a topic. Resolves to an unregister function. | ||
| * | ||
| * The first call across the worker process lazily loads `@vercel/queue` and | ||
| * constructs a shared `QueueClient`. Re-registering with the same topic | ||
| * replaces the handler (HMR-safe; the SDK keys consumers by `consumerGroup`, | ||
| * so calling unregister on a replaced registration is a no-op). | ||
| * | ||
| * If `@vercel/queue` is not installed or does not expose `registerDevConsumer`, | ||
| * resolves to a no-op unregister and logs a one-time warning. | ||
| */ | ||
| declare function registerVercelQueueConsumer(consumer: VercelQueueDevConsumer): Promise<() => void>; | ||
| export { VercelQueueDevConsumer, registerVercelQueueConsumer }; |
| const DEFAULT_CONSUMER_GROUP = "env-runner-vercel-dev"; | ||
| let sdkPromise; | ||
| let client; | ||
| const noop = () => {}; | ||
| async function registerVercelQueueConsumer(consumer) { | ||
| const sdk = await ensureSdk(); | ||
| if (!sdk || !client) return noop; | ||
| return sdk.registerDevConsumer({ | ||
| topic: consumer.topic, | ||
| client, | ||
| handler: consumer.handler, | ||
| consumerGroup: consumer.consumerGroup ?? DEFAULT_CONSUMER_GROUP, | ||
| visibilityTimeoutSeconds: consumer.visibilityTimeoutSeconds, | ||
| retry: consumer.retry ?? (consumer.retryAfterSeconds === void 0 ? void 0 : () => ({ afterSeconds: consumer.retryAfterSeconds })) | ||
| }); | ||
| } | ||
| function ensureSdk() { | ||
| if (sdkPromise) return sdkPromise; | ||
| sdkPromise = (async () => { | ||
| let mod; | ||
| try { | ||
| mod = await import("@vercel/queue"); | ||
| } catch { | ||
| console.warn("[env-runner:vercel-queue] `@vercel/queue` is not installed. Local queue delivery is disabled."); | ||
| return null; | ||
| } | ||
| if (typeof mod.registerDevConsumer !== "function") { | ||
| console.warn("[env-runner:vercel-queue] Installed `@vercel/queue` does not export `registerDevConsumer`. Upgrade @vercel/queue@^0.2.0 to enable local queue delivery."); | ||
| return null; | ||
| } | ||
| client = new mod.QueueClient(); | ||
| return mod; | ||
| })(); | ||
| return sdkPromise; | ||
| } | ||
| export { registerVercelQueueConsumer }; |
| import { a as RunnerMessageListener, l as WorkerAddress, t as EnvRunner, u as WorkerHooks } from "./types.mjs"; | ||
| import { IncomingMessage } from "node:http"; | ||
| import { Socket } from "node:net"; | ||
| //#region src/common/base-runner.d.ts | ||
| interface EnvRunnerData { | ||
@@ -48,3 +46,2 @@ name?: string; | ||
| } | ||
| //#endregion | ||
| export { EnvRunnerData as n, BaseEnvRunner as t }; |
| import { rm } from "node:fs/promises"; | ||
| import { proxyFetch, proxyUpgrade } from "httpxy"; | ||
| //#region src/common/base-runner.ts | ||
| var BaseEnvRunner = class { | ||
@@ -128,3 +127,2 @@ closed = false; | ||
| }; | ||
| //#endregion | ||
| export { BaseEnvRunner as t }; |
@@ -1,2 +0,1 @@ | ||
| //#region node_modules/.pnpm/cjs-module-lexer@2.2.0/node_modules/cjs-module-lexer/dist/lexer.mjs | ||
| let A; | ||
@@ -146,3 +145,2 @@ const B = 1 === new Uint8Array(new Uint16Array([1]).buffer)[0]; | ||
| } | ||
| //#endregion | ||
| export { parse as n, init as t }; |
| import { u as WorkerHooks } from "./types.mjs"; | ||
| import { n as EnvRunnerData, t as BaseEnvRunner } from "./base-runner.mjs"; | ||
| //#region src/runners/deno-process/runner.d.ts | ||
| declare class DenoProcessEnvRunner extends BaseEnvRunner { | ||
@@ -19,3 +17,2 @@ #private; | ||
| } | ||
| //#endregion | ||
| export { DenoProcessEnvRunner as t }; |
@@ -5,3 +5,2 @@ import { t as BaseEnvRunner } from "./base-runner.mjs"; | ||
| import { fileURLToPath } from "node:url"; | ||
| //#region src/runners/deno-process/runner.ts | ||
| let _defaultEntry; | ||
@@ -99,3 +98,2 @@ var DenoProcessEnvRunner = class extends BaseEnvRunner { | ||
| }; | ||
| //#endregion | ||
| export { DenoProcessEnvRunner as t }; |
@@ -5,4 +5,2 @@ import { u as WorkerHooks } from "./types.mjs"; | ||
| import { Socket } from "node:net"; | ||
| //#region src/runners/miniflare/runner.d.ts | ||
| /** Result from a module transform (compatible with Vite's `TransformResult`). */ | ||
@@ -87,3 +85,2 @@ interface TransformResult { | ||
| } | ||
| //#endregion | ||
| export { TransformResult as i, MiniflareEnvRunnerOptions as n, MiniflareExportInfo as r, MiniflareEnvRunner as t }; |
@@ -9,22 +9,4 @@ import { t as BaseEnvRunner } from "./base-runner.mjs"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| //#region src/runners/miniflare/wrapper.ts | ||
| const IPC_PATH$1 = "/__env_runner_ipc"; | ||
| /** Service binding name used for cross-request IPC (worker → runner). */ | ||
| const IPC_PATH = "/__env_runner_ipc"; | ||
| const IPC_BINDING = "__ENV_RUNNER_IPC"; | ||
| /** | ||
| * Generates a wrapper module that imports the user entry and adds IPC glue. | ||
| * | ||
| * The user module is expected to export `fetch` and optionally `ipc`. | ||
| * The wrapper uses a persistent WebSocket pair for bidirectional IPC: | ||
| * - Init: `fetch` with `upgrade: websocket` creates a WebSocketPair | ||
| * - Messages: JSON over the WebSocket (no per-message `dispatchFetch`) | ||
| * - Reload: `{ type: "reload" }` triggers cache-busted re-import | ||
| * - Shutdown: `{ type: "shutdown" }` calls `ipc.onClose()` | ||
| * | ||
| * For outgoing messages during fetch request handling, uses a service binding | ||
| * (`__ENV_RUNNER_IPC`) to avoid workerd's cross-request I/O restriction on | ||
| * the WebSocket object. | ||
| * | ||
| * Passed as an in-memory `script` to Miniflare (no temp files needed). | ||
| */ | ||
| function generateWrapper(entryPath, opts) { | ||
@@ -52,3 +34,3 @@ const staticReExport = opts?.dynamicOnly ? "" : `export * from ${JSON.stringify(entryPath)};`; | ||
| const __IPC_PATH = "${IPC_PATH$1}"; | ||
| const __IPC_PATH = "${IPC_PATH}"; | ||
| const __IPC_BINDING = "${IPC_BINDING}"; | ||
@@ -199,5 +181,2 @@ const __entryPath = ${JSON.stringify(entryPath)}; | ||
| } | ||
| //#endregion | ||
| //#region src/runners/miniflare/runner.ts | ||
| const IPC_PATH = "/__env_runner_ipc"; | ||
| const _miniflareCache = /* @__PURE__ */ new Map(); | ||
@@ -228,3 +207,2 @@ var MiniflareEnvRunner = class extends BaseEnvRunner { | ||
| } | ||
| /** Dispose all persistent Miniflare instances from the cache. */ | ||
| static async disposeAll() { | ||
@@ -235,3 +213,2 @@ const entries = [..._miniflareCache.values()]; | ||
| } | ||
| /** Fully dispose the Miniflare instance (even if persistent). */ | ||
| async dispose() { | ||
@@ -275,9 +252,2 @@ if (this.#miniflare) { | ||
| } | ||
| /** | ||
| * Hot-reload the user entry module without recreating the Miniflare instance. | ||
| * | ||
| * Sends `reload-module` event over the WebSocket. The worker wrapper uses | ||
| * `unsafeEvalBinding` to re-import the entry with a cache-busting query string | ||
| * and responds with `module-reloaded` when done. | ||
| */ | ||
| async reloadModule(timeout = 5e3) { | ||
@@ -522,3 +492,3 @@ if (!this.#ws) throw new Error("Miniflare env runner should be initialized before reloading."); | ||
| } | ||
| const initRes = await this.#miniflare.dispatchFetch("http://localhost" + IPC_PATH, { headers: { upgrade: "websocket" } }); | ||
| const initRes = await this.#miniflare.dispatchFetch("http://localhost/__env_runner_ipc", { headers: { upgrade: "websocket" } }); | ||
| const ws = initRes.webSocket; | ||
@@ -543,6 +513,2 @@ if (!ws) { | ||
| }; | ||
| /** | ||
| * Detect `export class` declarations in the entry file. | ||
| * Merges with explicitly declared exports from options. | ||
| */ | ||
| function detectExportedClasses(entryPath, explicit) { | ||
@@ -558,7 +524,5 @@ const names = new Set(Object.keys(explicit)); | ||
| } | ||
| /** Convert PascalCase/camelCase to SCREAMING_SNAKE_CASE (e.g. `Counter` → `COUNTER`, `MyDurableObject` → `MY_DURABLE_OBJECT`). */ | ||
| function toScreamingSnakeCase(name) { | ||
| return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase(); | ||
| } | ||
| /** Compute a stable cache key for persistent Miniflare instances. */ | ||
| function computeCacheKey(entryPath, opts) { | ||
@@ -584,3 +548,2 @@ const serializableOpts = {}; | ||
| } | ||
| //#endregion | ||
| export { MiniflareEnvRunner as t }; |
| import { u as WorkerHooks } from "./types.mjs"; | ||
| import { n as EnvRunnerData, t as BaseEnvRunner } from "./base-runner.mjs"; | ||
| //#region src/runners/node-worker/runner.d.ts | ||
| declare class NodeWorkerEnvRunner extends BaseEnvRunner { | ||
@@ -18,3 +16,2 @@ #private; | ||
| } | ||
| //#endregion | ||
| export { NodeWorkerEnvRunner as t }; |
@@ -5,3 +5,2 @@ import { t as BaseEnvRunner } from "./base-runner.mjs"; | ||
| import { Worker } from "node:worker_threads"; | ||
| //#region src/runners/node-worker/runner.ts | ||
| let _defaultEntry; | ||
@@ -62,3 +61,2 @@ var NodeWorkerEnvRunner = class extends BaseEnvRunner { | ||
| }; | ||
| //#endregion | ||
| export { NodeWorkerEnvRunner as t }; |
| import { u as WorkerHooks } from "./types.mjs"; | ||
| import { n as EnvRunnerData } from "./base-runner.mjs"; | ||
| import { t as NodeWorkerEnvRunner } from "./runner3.mjs"; | ||
| //#region src/runners/vercel/runner.d.ts | ||
| declare class VercelEnvRunner extends NodeWorkerEnvRunner { | ||
@@ -16,3 +14,2 @@ constructor(opts: { | ||
| } | ||
| //#endregion | ||
| export { VercelEnvRunner as t }; |
| import { t as NodeWorkerEnvRunner } from "./runner3.mjs"; | ||
| import { fileURLToPath } from "node:url"; | ||
| //#region src/runners/vercel/runner.ts | ||
| import { randomBytes } from "node:crypto"; | ||
| let _warned = false; | ||
| function warnIfVercelOidcTokenInvalid(token) { | ||
| const result = _checkVercelOidcToken(token); | ||
| if (_warned) return result; | ||
| if (result.status === "missing") { | ||
| _warned = true; | ||
| console.warn("[env-runner:vercel] VERCEL_OIDC_TOKEN is not set. Vercel SDK features (e.g. @vercel/functions waitUntil, cache) may not work. Run `vercel env pull` to set it."); | ||
| } else if (result.status === "expired") { | ||
| _warned = true; | ||
| console.warn(`[env-runner:vercel] VERCEL_OIDC_TOKEN expired at ${result.expiresAt.toISOString()}. Vercel SDK authentication will fail. Run \`vercel env pull\` to refresh it.`); | ||
| } else if (result.status === "invalid") { | ||
| _warned = true; | ||
| console.warn("[env-runner:vercel] VERCEL_OIDC_TOKEN is malformed (not a valid JWT). Vercel SDK authentication will fail. Run `vercel env pull` to get a fresh token."); | ||
| } | ||
| return result; | ||
| } | ||
| function _checkVercelOidcToken(token = process.env.VERCEL_OIDC_TOKEN) { | ||
| if (!token) return { status: "missing" }; | ||
| const parts = token.split("."); | ||
| if (parts.length !== 3) return { status: "invalid" }; | ||
| let payload; | ||
| try { | ||
| const json = Buffer.from(parts[1], "base64url").toString("utf8"); | ||
| payload = JSON.parse(json); | ||
| } catch { | ||
| return { status: "invalid" }; | ||
| } | ||
| if (!payload || typeof payload !== "object") return { status: "invalid" }; | ||
| const exp = payload.exp; | ||
| if (typeof exp !== "number" || !Number.isFinite(exp)) return { status: "invalid" }; | ||
| const expiresAt = /* @__PURE__ */ new Date(exp * 1e3); | ||
| if (expiresAt.getTime() <= Date.now()) return { | ||
| status: "expired", | ||
| expiresAt | ||
| }; | ||
| return { | ||
| status: "valid", | ||
| expiresAt | ||
| }; | ||
| } | ||
| let _defaultEntry; | ||
| const _podId = Math.random().toString(32).slice(-5); | ||
| function generateVercelId() { | ||
| return `dev1::${_podId}-${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`; | ||
| } | ||
| var VercelEnvRunner = class extends NodeWorkerEnvRunner { | ||
@@ -12,5 +56,7 @@ constructor(opts) { | ||
| }); | ||
| warnIfVercelOidcTokenInvalid(); | ||
| } | ||
| async fetch(input, init) { | ||
| const headers = new Headers(input instanceof Request ? input.headers : init?.headers); | ||
| const requestId = generateVercelId(); | ||
| if (this._address && this._address.port != null && !headers.has("x-vercel-deployment-url")) { | ||
@@ -20,2 +66,3 @@ const host = this._address.host || "127.0.0.1"; | ||
| } | ||
| if (!headers.has("x-vercel-id")) headers.set("x-vercel-id", requestId); | ||
| const clientIp = headers.get("x-forwarded-for")?.split(",")[0]?.trim() || headers.get("x-real-ip") || "127.0.0.1"; | ||
@@ -30,10 +77,15 @@ if (!headers.has("x-vercel-forwarded-for")) headers.set("x-vercel-forwarded-for", clientIp); | ||
| } catch {} | ||
| if (input instanceof Request) return super.fetch(new Request(input, { | ||
| const res = await super.fetch(input, { | ||
| ...init, | ||
| headers | ||
| })); | ||
| return super.fetch(input, { | ||
| ...init, | ||
| headers | ||
| }); | ||
| const resHeaders = new Headers(res.headers); | ||
| if (!resHeaders.has("server")) resHeaders.set("server", "Vercel"); | ||
| if (!resHeaders.has("x-vercel-id")) resHeaders.set("x-vercel-id", requestId); | ||
| if (!resHeaders.has("x-vercel-cache")) resHeaders.set("x-vercel-cache", "MISS"); | ||
| return new Response(res.body, { | ||
| status: res.status, | ||
| statusText: res.statusText, | ||
| headers: resHeaders | ||
| }); | ||
| } | ||
@@ -44,3 +96,2 @@ _runtimeType() { | ||
| }; | ||
| //#endregion | ||
| export { VercelEnvRunner as t }; |
| import { u as WorkerHooks } from "./types.mjs"; | ||
| import { n as EnvRunnerData } from "./base-runner.mjs"; | ||
| import { t as NodeWorkerEnvRunner } from "./runner3.mjs"; | ||
| //#region src/runners/netlify/runner.d.ts | ||
| declare class NetlifyEnvRunner extends NodeWorkerEnvRunner { | ||
@@ -16,3 +14,2 @@ constructor(opts: { | ||
| } | ||
| //#endregion | ||
| export { NetlifyEnvRunner as t }; |
| import { t as NodeWorkerEnvRunner } from "./runner3.mjs"; | ||
| import { fileURLToPath } from "node:url"; | ||
| //#region src/runners/netlify/runner.ts | ||
| let _defaultEntry; | ||
@@ -46,3 +45,2 @@ var NetlifyEnvRunner = class extends NodeWorkerEnvRunner { | ||
| }; | ||
| //#endregion | ||
| export { NetlifyEnvRunner as t }; |
| import { watch } from "node:fs"; | ||
| //#region src/manager.ts | ||
| /** | ||
| * Manages an active `EnvRunner` instance, proxying all calls to it. | ||
| * Supports hot-reload, auto-restart on unexpected exit, and message queueing. | ||
| */ | ||
| var RunnerManager = class { | ||
@@ -24,3 +19,2 @@ _runner; | ||
| } | ||
| /** Replace the active runner with a new one. Closes the previous runner. */ | ||
| async reload(runner) { | ||
@@ -171,4 +165,2 @@ this._reloading = true; | ||
| }; | ||
| //#endregion | ||
| //#region src/loader.ts | ||
| const loaders = { | ||
@@ -187,4 +179,2 @@ "node-worker": () => import("env-runner/runners/node-worker").then((m) => m.NodeWorkerEnvRunner), | ||
| } | ||
| //#endregion | ||
| //#region src/server.ts | ||
| var EnvServer = class extends RunnerManager { | ||
@@ -196,7 +186,5 @@ _opts; | ||
| runner = null; | ||
| /** Register a listener called when the runner is reloaded due to a file change. */ | ||
| onReload(listener) { | ||
| this._reloadListeners.add(listener); | ||
| } | ||
| /** Remove a previously registered reload listener. */ | ||
| offReload(listener) { | ||
@@ -209,3 +197,2 @@ this._reloadListeners.delete(listener); | ||
| } | ||
| /** Start the server by loading and attaching the runner. */ | ||
| async start() { | ||
@@ -259,3 +246,2 @@ this.runner = await this._createRunner(); | ||
| }; | ||
| //#endregion | ||
| export { loadRunner as n, RunnerManager as r, EnvServer as t }; |
| import { IncomingMessage } from "node:http"; | ||
| import { Socket } from "node:net"; | ||
| //#region src/types.d.ts | ||
| /** Handler for proxying HTTP requests to the worker. */ | ||
@@ -75,3 +73,2 @@ type FetchHandler = (input: string | URL | Request, init?: RequestInit) => Promise<Response>; | ||
| } | ||
| //#endregion | ||
| export { RunnerMessageListener as a, UpgradeHandler as c, RPCOptions as i, WorkerAddress as l, FetchHandler as n, RunnerRPCHooks as o, NodeUpgradeContext as r, UpgradeContext as s, EnvRunner as t, WorkerHooks as u }; |
| import { readFileSync } from "node:fs"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import { isAbsolute } from "node:path"; | ||
| //#region src/common/worker-utils.ts | ||
| async function resolveEntry(entryPath) { | ||
@@ -18,6 +17,2 @@ const mod = await import(_toImportPath(entryPath)); | ||
| } | ||
| /** | ||
| * Re-import the user entry module with cache busting. | ||
| * Tears down old IPC hooks and re-initializes new ones. | ||
| */ | ||
| async function reloadEntryModule(entryPath, currentEntry, sendMessage) { | ||
@@ -43,3 +38,2 @@ await currentEntry.ipc?.onClose?.(); | ||
| } | ||
| //#endregion | ||
| export { reloadEntryModule as n, resolveEntry as r, parseServerAddress as t }; |
+0
-2
@@ -5,3 +5,2 @@ import { t as EnvServer } from "./_chunks/server.mjs"; | ||
| import { parseArgs } from "node:util"; | ||
| //#region src/cli.ts | ||
| const { values, positionals } = parseArgs({ | ||
@@ -71,3 +70,2 @@ allowPositionals: true, | ||
| }); | ||
| //#endregion | ||
| export {}; |
+0
-9
@@ -9,4 +9,2 @@ import { a as RunnerMessageListener, c as UpgradeHandler, i as RPCOptions, l as WorkerAddress, n as FetchHandler, o as RunnerRPCHooks, r as NodeUpgradeContext, s as UpgradeContext, t as EnvRunner, u as WorkerHooks } from "./_chunks/types.mjs"; | ||
| import { Hooks } from "crossws"; | ||
| //#region src/manager.d.ts | ||
| /** | ||
@@ -50,4 +48,2 @@ * Manages an active `EnvRunner` instance, proxying all calls to it. | ||
| } | ||
| //#endregion | ||
| //#region src/loader.d.ts | ||
| type RunnerName = "node-worker" | "node-process" | "bun-process" | "deno-process" | "self" | "miniflare" | "vercel" | "netlify"; | ||
@@ -64,4 +60,2 @@ interface LoadRunnerOptions { | ||
| declare function loadRunner(runner: RunnerName, opts: LoadRunnerOptions): Promise<EnvRunner>; | ||
| //#endregion | ||
| //#region src/server.d.ts | ||
| interface EnvServerOptions { | ||
@@ -104,4 +98,2 @@ /** Runner implementation to use. */ | ||
| } | ||
| //#endregion | ||
| //#region src/common/worker-utils.d.ts | ||
| interface AppEntryIPCContext { | ||
@@ -123,3 +115,2 @@ sendMessage: (message: unknown) => void; | ||
| } | ||
| //#endregion | ||
| 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 }; |
| import { u as WorkerHooks } from "../../_chunks/types.mjs"; | ||
| import { n as EnvRunnerData, t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| //#region src/runners/bun-process/runner.d.ts | ||
| declare class BunProcessEnvRunner extends BaseEnvRunner { | ||
@@ -19,3 +17,2 @@ #private; | ||
| } | ||
| //#endregion | ||
| export { BunProcessEnvRunner, type EnvRunnerData as BunProcessEnvRunnerData }; |
@@ -7,3 +7,2 @@ import { t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| import { homedir } from "node:os"; | ||
| //#region src/runners/bun-process/runner.ts | ||
| let _defaultEntry; | ||
@@ -130,3 +129,2 @@ let _bunPath; | ||
| }; | ||
| //#endregion | ||
| export { BunProcessEnvRunner }; |
| import { n as reloadEntryModule, r as resolveEntry, t as parseServerAddress } from "../../_chunks/worker-utils.mjs"; | ||
| import { serve } from "srvx"; | ||
| import { plugin } from "crossws/server"; | ||
| //#region src/runners/bun-process/worker.ts | ||
| const data = JSON.parse(process.env.ENV_RUNNER_DATA || "{}"); | ||
@@ -55,3 +54,2 @@ let entry = await resolveEntry(data.entry); | ||
| }); | ||
| //#endregion | ||
| export {}; |
| import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs"; | ||
| import { t as DenoProcessEnvRunner } from "../../_chunks/runner.mjs"; | ||
| export { DenoProcessEnvRunner, EnvRunnerData as DenoProcessEnvRunnerData }; | ||
| export { DenoProcessEnvRunner, type EnvRunnerData as DenoProcessEnvRunnerData }; |
| import { n as reloadEntryModule, r as resolveEntry, t as parseServerAddress } from "../../_chunks/worker-utils.mjs"; | ||
| import { serve } from "srvx"; | ||
| import { plugin } from "crossws/server"; | ||
| //#region src/runners/deno-process/worker.ts | ||
| const data = JSON.parse(process.env.ENV_RUNNER_DATA || "{}"); | ||
@@ -78,3 +77,2 @@ let entry = await resolveEntry(data.entry); | ||
| readMessages().catch(() => {}); | ||
| //#endregion | ||
| export {}; |
| import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs"; | ||
| import { i as TransformResult, n as MiniflareEnvRunnerOptions, r as MiniflareExportInfo, t as MiniflareEnvRunner } from "../../_chunks/runner2.mjs"; | ||
| export { MiniflareEnvRunner, EnvRunnerData as MiniflareEnvRunnerData, MiniflareEnvRunnerOptions, MiniflareExportInfo, TransformResult }; | ||
| export { MiniflareEnvRunner, type EnvRunnerData as MiniflareEnvRunnerData, MiniflareEnvRunnerOptions, MiniflareExportInfo, TransformResult }; |
| import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs"; | ||
| import { t as NetlifyEnvRunner } from "../../_chunks/runner5.mjs"; | ||
| export { EnvRunnerData, NetlifyEnvRunner }; | ||
| export { type EnvRunnerData, NetlifyEnvRunner }; |
@@ -1,2 +0,1 @@ | ||
| //#region src/runners/netlify/worker.ts | ||
| try { | ||
@@ -42,3 +41,2 @@ const { startRuntime } = await import("@netlify/runtime"); | ||
| await import("../node-worker/worker.mjs"); | ||
| //#endregion | ||
| export {}; |
| import { u as WorkerHooks } from "../../_chunks/types.mjs"; | ||
| import { n as EnvRunnerData, t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| //#region src/runners/node-process/runner.d.ts | ||
| declare class NodeProcessEnvRunner extends BaseEnvRunner { | ||
@@ -19,3 +17,2 @@ #private; | ||
| } | ||
| //#endregion | ||
| export { NodeProcessEnvRunner, type EnvRunnerData as ProcessEnvRunnerData }; |
@@ -5,3 +5,2 @@ import { t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| import { fileURLToPath } from "node:url"; | ||
| //#region src/runners/node-process/runner.ts | ||
| let _defaultEntry; | ||
@@ -67,3 +66,2 @@ var NodeProcessEnvRunner = class extends BaseEnvRunner { | ||
| }; | ||
| //#endregion | ||
| export { NodeProcessEnvRunner }; |
| import { n as reloadEntryModule, r as resolveEntry, t as parseServerAddress } from "../../_chunks/worker-utils.mjs"; | ||
| import { serve } from "srvx"; | ||
| import { plugin } from "crossws/server/node"; | ||
| //#region src/runners/node-process/worker.ts | ||
| const data = JSON.parse(process.env.ENV_RUNNER_DATA || "{}"); | ||
@@ -55,3 +54,2 @@ let entry = await resolveEntry(data.entry); | ||
| }); | ||
| //#endregion | ||
| export {}; |
| import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs"; | ||
| import { t as NodeWorkerEnvRunner } from "../../_chunks/runner3.mjs"; | ||
| export { EnvRunnerData, NodeWorkerEnvRunner }; | ||
| export { type EnvRunnerData, NodeWorkerEnvRunner }; |
@@ -5,3 +5,2 @@ import { n as reloadEntryModule, r as resolveEntry, t as parseServerAddress } from "../../_chunks/worker-utils.mjs"; | ||
| import { plugin } from "crossws/server/node"; | ||
| //#region src/runners/node-worker/worker.ts | ||
| const data = workerData || {}; | ||
@@ -57,3 +56,2 @@ let entry = await resolveEntry(data.entry); | ||
| }); | ||
| //#endregion | ||
| export {}; |
| import { u as WorkerHooks } from "../../_chunks/types.mjs"; | ||
| import { n as EnvRunnerData, t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| import * as node_http0 from "node:http"; | ||
| import * as node_net0 from "node:net"; | ||
| //#region src/runners/self/runner.d.ts | ||
| declare class SelfEnvRunner extends BaseEnvRunner { | ||
@@ -17,4 +13,4 @@ #private; | ||
| node: { | ||
| req: node_http0.IncomingMessage; | ||
| socket: node_net0.Socket; | ||
| req: import("node:http").IncomingMessage; | ||
| socket: import("node:net").Socket; | ||
| head: any; | ||
@@ -29,3 +25,2 @@ }; | ||
| } | ||
| //#endregion | ||
| export { SelfEnvRunner, type EnvRunnerData as SelfEnvRunnerData }; |
| import { t as BaseEnvRunner } from "../../_chunks/base-runner.mjs"; | ||
| import { n as reloadEntryModule, r as resolveEntry } from "../../_chunks/worker-utils.mjs"; | ||
| //#region src/runners/self/runner.ts | ||
| var SelfEnvRunner = class extends BaseEnvRunner { | ||
@@ -92,3 +91,2 @@ #active = false; | ||
| }; | ||
| //#endregion | ||
| export { SelfEnvRunner }; |
| import { n as EnvRunnerData } from "../../_chunks/base-runner.mjs"; | ||
| import { t as VercelEnvRunner } from "../../_chunks/runner4.mjs"; | ||
| export { EnvRunnerData, VercelEnvRunner }; | ||
| export { type EnvRunnerData, VercelEnvRunner }; |
@@ -1,2 +0,4 @@ | ||
| //#region src/runners/vercel/worker.ts | ||
| process.env.VERCEL = process.env.VERCEL || "1"; | ||
| process.env.VERCEL_ENV = process.env.VERCEL_ENV || "development"; | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "development"; | ||
| const SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context"); | ||
@@ -49,3 +51,2 @@ const waitUntilPromises = /* @__PURE__ */ new Set(); | ||
| await import("../node-worker/worker.mjs"); | ||
| //#endregion | ||
| export {}; |
+0
-3
| import { o as RunnerRPCHooks } from "./_chunks/types.mjs"; | ||
| //#region src/vite.d.ts | ||
| /** Vite HotChannel-compatible interface (avoids hard dependency on vite types). */ | ||
@@ -31,3 +29,2 @@ interface ViteHotChannel { | ||
| declare function createViteTransport(sendMessage: (data: any) => void, onMessage: (listener: (value: any) => void) => void, envName: string): ViteTransport; | ||
| //#endregion | ||
| export { ViteHotChannel, ViteTransport, createViteHotChannel, createViteTransport }; |
+0
-14
@@ -1,8 +0,1 @@ | ||
| //#region src/vite.ts | ||
| /** | ||
| * Create a Vite `HotChannel` from an env-runner's RPC hooks. | ||
| * | ||
| * Use on the **host side** to bridge env-runner IPC → Vite's DevEnvironment transport. | ||
| * Messages are namespaced by `envName` so multiple Vite environments can share one runner. | ||
| */ | ||
| function createViteHotChannel(hooks, envName) { | ||
@@ -36,8 +29,2 @@ const listeners = /* @__PURE__ */ new WeakMap(); | ||
| } | ||
| /** | ||
| * Create a Vite `ModuleRunner` transport from worker-side IPC primitives. | ||
| * | ||
| * Use on the **worker side** to bridge worker IPC → Vite's `ModuleRunner` transport. | ||
| * Filters messages by `envName` so multiple Vite environments can share one IPC channel. | ||
| */ | ||
| function createViteTransport(sendMessage, onMessage, envName) { | ||
@@ -58,3 +45,2 @@ return { | ||
| } | ||
| //#endregion | ||
| export { createViteHotChannel, createViteTransport }; |
+23
-17
| { | ||
| "name": "env-runner", | ||
| "version": "0.1.7", | ||
| "version": "0.1.8", | ||
| "description": "Generic environment runner for JavaScript runtimes.", | ||
@@ -29,2 +29,3 @@ "license": "MIT", | ||
| "./runners/vercel/worker": "./dist/runners/vercel/worker.mjs", | ||
| "./runners/vercel/queue-dev": "./dist/runners/vercel/queue-dev.mjs", | ||
| "./runners/netlify": "./dist/runners/netlify/runner.mjs", | ||
@@ -46,12 +47,13 @@ "./runners/netlify/worker": "./dist/runners/netlify/worker.mjs", | ||
| "dependencies": { | ||
| "crossws": "^0.4.4", | ||
| "crossws": "^0.4.5", | ||
| "exsolve": "^1.0.8", | ||
| "httpxy": "^0.5.0", | ||
| "srvx": "^0.11.13" | ||
| "httpxy": "^0.5.3", | ||
| "srvx": "^0.11.15" | ||
| }, | ||
| "devDependencies": { | ||
| "@netlify/runtime": "^4.1.20", | ||
| "@types/node": "^25.5.0", | ||
| "@typescript/native-preview": "^7.0.0-dev.20260327.2", | ||
| "@vitest/coverage-v8": "^4.1.2", | ||
| "@netlify/runtime": "^4.1.24", | ||
| "@types/node": "^25.9.1", | ||
| "@typescript/native-preview": "7.0.0-dev.20260521.1", | ||
| "@vercel/queue": "^0.2.0", | ||
| "@vitest/coverage-v8": "^4.1.7", | ||
| "automd": "^0.4.3", | ||
@@ -61,12 +63,13 @@ "changelogen": "^0.6.2", | ||
| "env-runner-fixture": "link:", | ||
| "miniflare": "^4.20260317.3", | ||
| "obuild": "^0.4.32", | ||
| "oxfmt": "^0.42.0", | ||
| "oxlint": "^1.57.0", | ||
| "typescript": "^6.0.2", | ||
| "vitest": "^4.1.2" | ||
| "miniflare": "^4.20260520.0", | ||
| "obuild": "^0.4.35", | ||
| "oxfmt": "^0.51.0", | ||
| "oxlint": "^1.66.0", | ||
| "typescript": "^6.0.3", | ||
| "vitest": "^4.1.7" | ||
| }, | ||
| "peerDependencies": { | ||
| "@netlify/runtime": "^4", | ||
| "miniflare": "^4.20260317.3" | ||
| "@netlify/runtime": "^4.1.23", | ||
| "@vercel/queue": "^0.2.0", | ||
| "miniflare": "^4.20260515.0" | ||
| }, | ||
@@ -79,5 +82,8 @@ "peerDependenciesMeta": { | ||
| "optional": true | ||
| }, | ||
| "@vercel/queue": { | ||
| "optional": true | ||
| } | ||
| }, | ||
| "packageManager": "pnpm@10.33.0" | ||
| "packageManager": "pnpm@11.2.2" | ||
| } |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances
138426
0.75%56
3.7%33
-2.94%7
16.67%15
7.14%2262
-0.48%30
30.43%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
Updated
Updated
Updated