@rcompat/runtime
v0.13.0
Published
Standard library runtime context
Readme
@rcompat/runtime
Runtime detection for JavaScript environments.
What is @rcompat/runtime?
A cross-runtime module that tells you which JavaScript runtime your code is executing in, and provides runtime-specific utilities like the executable path, current script, arguments, and process exit. Uses runtime keys for accurate detection without any runtime overhead.
Installation
npm install @rcompat/runtimepnpm add @rcompat/runtimeyarn add @rcompat/runtimebun add @rcompat/runtimeUsage
Basic detection
import runtime from "@rcompat/runtime";
console.log(runtime.name);
// "node" | "bun" | "deno" | "browser"Conditional logic
import runtime from "@rcompat/runtime";
if (runtime.name === "bun") {
// Bun-specific code
} else if (runtime.name === "deno") {
// Deno-specific code
} else if (runtime.name === "node") {
// Node.js-specific code
}Executable path
import runtime from "@rcompat/runtime";
console.log(runtime.bin);
// "/usr/local/bin/node"
// "/home/user/.bun/bin/bun"
// "/usr/bin/deno"Current script
import runtime from "@rcompat/runtime";
console.log(runtime.script);
// "/path/to/your/script.js"Program arguments
import runtime from "@rcompat/runtime";
// running: node app.js foo bar
console.log(runtime.args);
// ["foo", "bar"]runtime.args always contains only your program's arguments — the runtime
executable and script path are stripped away, consistently across all runtimes.
Exiting the process
import runtime from "@rcompat/runtime";
runtime.exit(0); // success
runtime.exit(1); // failureruntime.exit is undefined in browser and edge runtimes where process exit
has no meaning.
Supported Runtimes
| Runtime | Value | Environment |
|----------------|-------------|----------------------------|
| Node.js | "node" | Standard Node.js |
| Bun | "bun" | Bun runtime |
| Deno | "deno" | Deno runtime |
| Cloudflare | "workerd" | Cloudflare Workers |
| Vercel | "vercel" | Vercel Edge Functions |
| Netlify | "netlify" | Netlify Edge Functions |
| Fastly | "fastly" | Fastly Compute@Edge |
| Browser | "browser" | Web browsers |
API Reference
runtime.name
runtime.name: "node" | "bun" | "deno" | "workerd" | "vercel" | "netlify" | "fastly" | "browser";A string identifying the current runtime environment.
runtime.bin
runtime.bin: string | undefined;Full path to the runtime executable. undefined in browser and edge runtimes.
runtime.script
runtime.script: string | undefined;Full path to the currently executing script. undefined in browser and edge
runtimes.
runtime.args
runtime.args: string[];Program arguments, with the runtime executable and script path stripped.
Always an array — empty if no arguments were passed. [] in browser and edge
runtimes.
runtime.exit
runtime.exit: ((code?: number) => never) | undefined;Exit the current process with an optional exit code. undefined in browser
and edge runtimes where process exit has no meaning.
runtime.resolve
runtime.resolve(specifier: string, from: string): stringResolve a path or package specifier from a directory.
- Relative specifiers like
./foo.jsonand../tsconfig.jsonare resolved fromfrom - Absolute paths are returned as absolute paths
- Package specifiers like
apekit/tsconfigare resolved using the current runtime’s package resolution
How It Works
This package uses runtime keys,
a WinterCG proposal for runtime detection. The exports field in package.json
routes to different files based on the runtime condition, meaning detection
happens at import time with zero runtime overhead.
{
"exports": {
".": {
"bun": "./lib/public/bun.js",
"deno": "./lib/public/deno.js",
"workerd": "./lib/public/cloudflare.js",
"node": "./lib/public/node.js"
}
}
}Each file simply exports the runtime object for that environment:
// node.ts
export default {
name: "node",
bin: process.execPath,
script: process.argv[1],
args: process.argv.slice(2),
exit: (code?: number) => process.exit(code),
};Examples
Relaunching with custom flags
import runtime from "@rcompat/runtime";
import io from "@rcompat/io";
// relaunch self with --conditions=source
await io.spawn(
`${runtime.bin} --conditions="@rcompat/source" ${runtime.script} ${runtime.args.join(" ")}`,
{ inherit: true }
);
runtime.exit(0);Runtime-specific logging
import runtime from "@rcompat/runtime";
const logger = {
info(message) {
console.log(`[${runtime.name}]`, message);
}
};
logger.info("Server started");
// [node] Server started
// [bun] Server startedEnvironment checks
import runtime from "@rcompat/runtime";
const isServerRuntime = ["node", "bun", "deno"].includes(runtime.name);
const isEdgeRuntime = ["workerd", "vercel", "netlify", "fastly"].includes(runtime.name);
const isClientRuntime = runtime.name === "browser";Debug information
import runtime from "@rcompat/runtime";
function getDebugInfo() {
return {
runtime: runtime.name,
script: runtime.script,
args: runtime.args,
timestamp: Date.now(),
};
}Reading tsconfig customConditions recursively
import fs from "@rcompat/fs":
type TSConfig = {
compilerOptions?: {
customConditions?: string[];
};
extends?: string;
};
async function read_conditions(file: FileRef) {
const json = await file.json<TSConfig>();
if (json.compilerOptions?.customConditions?.length) {
return json.compilerOptions.customConditions;
}
if (json.extends === undefined) {
return [];
}
const next = runtime.resolve(json.extends, file.directory.path);
return read_conditions(fs.ref(next));
}Cross-Runtime Compatibility
| Runtime | Supported | |--------------------|-----------| | Node.js | ✓ | | Bun | ✓ | | Deno | ✓ | | Browser | ✓ |
No configuration required — just import and use.
License
MIT
Contributing
See CONTRIBUTING.md in the repository root.
