npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@forst/node-runtime

v0.3.1

Published

Node.js runtime bootstrap and TypeScript indexer for Forst Node interop

Readme

@forst/node-runtime

Node runtime for Forst → TypeScript interop. Compiled Go binaries call your legacy .ts and .js modules over a closed RPC channel. The Forst compiler uses this package at build time to index TypeScript exports.

Status: experimental. Pin this package and verify with the examples before production use.

Full guide → Call JavaScript from Forst

Install

npm install @forst/node-runtime
npx jsr add @forst/node-runtime

Requires Node.js 18+. When your Forst program uses import node, you also need tsx on the path for TypeScript loading.

| Registry | Package | | --- | --- | | npm | @forst/node-runtime | | JSR | @forst/node-runtime |

What you get

The runtime is built on Effect: structured logs via Effect.log* and Effect.fn programs, with ForstNodeRuntimeLayer (stderr pretty logging + FORST_NODE_LOG_LEVEL) provided at process boundaries via NodeRuntime.runMain or Effect.runPromise.

Custom Effect runtime

Default entrypoints (bootstrap.js, @forst/node-runtime/host) use ForstNodeRuntimeLayer. To bring your own logging, tracing, or services, build a setup and pass it at the process boundary:

import { NodeRuntime } from "@effect/platform-node";
import { Effect, Layer, Logger } from "effect";
import {
  bootstrapMain,
  bootstrapFatal,
  createNodeRuntimeSetup,
  makeForstNodeRuntimeLayer,
  startRpcServer,
  startForstNodeHost,
} from "@forst/node-runtime";

const myLayer = makeForstNodeRuntimeLayer();
const { layer, runtime } = createNodeRuntimeSetup(myLayer);

// Bootstrap child (stdin/stdout RPC). disablePrettyLogger keeps stdout for frames only.
NodeRuntime.runMain(
  bootstrapMain({ runtime }).pipe(
    Effect.catchAllDefect((cause) => bootstrapFatal(cause)),
    Effect.provide(layer)
  ),
  { disablePrettyLogger: true }
);

// Or wire RPC directly
NodeRuntime.runMain(
  startRpcServer(process.stdin, process.stdout, {
    exitProcessOnShutdown: true,
    runtime,
  }).pipe(Effect.provide(layer)),
  { disablePrettyLogger: true }
);

// Host mode: pass runtimeLayer so RPC forks use the same setup
await Effect.runPromise(
  startForstNodeHost({ runtimeLayer: layer }).pipe(Effect.provide(layer))
);

Use the same layer for Effect.provide and the matching runtime for async RPC dispatch sites (startRpcServer, host connection forks).

| Piece | Role | | --- | --- | | bootstrap.js | RPC server process Go spawns in bootstrap mode | | @forst/node-runtime/host | In process RPC when your app runs the Node child | | forst-node-index | CLI the compiler invokes to read TypeScript exports | | Schema types | forst-node-manifest-v1 and forst-index-v1 validation |

Project setup

Enable node interop in ftconfig.json:

{
  "files": {
    "include": ["**/*.ft", "**/*.ts"]
  },
  "node": {
    "enabled": true,
    "runtimeEnabled": true
  }
}

Use opt in imports in Forst source:

import node "./legacy/payment"

func main() {
    result := payment.create(100.0, "USD")
}

Build and run with the Forst compiler (@forst/cli):

npx forst build -root . ./main.ft
npx forst run -root . ./main.ft

Runtime modes

Bootstrap (default): Go starts a dedicated Node child that runs dist/bootstrap.js. Isolated process. Logs on stderr. Stdout is RPC only.

Host: Go starts your app (node.binary + node.args). RPC listens on a local socket inside that process so module cache and globals stay shared. Import from @forst/node-runtime/host and call signalForstAppReady() when your app is ready.

See runtime modes in the docs.

CLI

forst-node-index --root . --format forst-index-v1 --files legacy/payment.ts

The compiler calls this during type checking. You rarely run it yourself.

Environment variables

Bootstrap and logging

| Variable | Purpose | | --- | --- | | FORST_NODE_LOG_LEVEL | Log verbosity: debug, info, warn, or error (default info). Per-RPC trace (rpc_recv, call, module_cache_hit, …) requires debug. | | FORST_NODE_LOG_FORMAT | Log format: pretty (default) or json for structured stderr lines. | | FORST_NODE_BOOTSTRAP | Absolute path to bootstrap.js (bootstrap mode spawn planning) |

Host mode (set by Go on the direct app-shim child)

| Variable | Purpose | | --- | --- | | FORST_NODE_HOST | When "1", enables in-process host RPC (startForstNodeHost). Unset in bootstrap mode. | | FORST_NODE_HOST_LEADER | When "1", marks the Go-spawned leader process. Required together with register.mjs in process.execArgv; workers skip binding. | | FORST_NODE_SOCKET | Absolute Unix socket path (TCP URL on Windows) for Go↔Node RPC in host mode. | | FORST_NODE_HOST_READY | Absolute path to JSON readiness file ({socket}.ready); Go waits for phase: "app". | | FORST_NODE_APP_READY_MODULE | Optional path to a module loaded before app readiness when node.hostAppReadyModule is configured. |

See Call JavaScript from Forst — host mode environment variables for spawn layout, readiness phases, and troubleshooting.

Development

From the monorepo:

cd packages/node-runtime
bun run build
bun test

Publishing

Release Please tags node-runtime-v* bump package.json and jsr.json. CI publishes to npm and JSR via .github/workflows/publish-packages.yml.

Manual publish from packages/node-runtime:

bun run build
npm publish --access public
npx jsr publish

Dry run:

bun run pack:dry
npx jsr publish --dry-run

License

MIT. See LICENSE.