Skip to content

Node.js Modules

Import Node.js builtins the way you always have. There is no GJSify-specific spelling and nothing extra to install:

TypeScript
import { readFile, writeFile } from 'node:fs/promises';
import { createServer } from 'node:http';
import { createHash, randomUUID } from 'node:crypto';
import { EventEmitter } from 'node:events';
import path from 'node:path';

In an --app gjs build each import is rewritten to its @gjsify/* implementation: node:fs to Gio.File, node:http to Soup.Server, node:crypto to GLib.Checksum and GLib.Hmac. The same file also builds for --app node, where the imports stay as written and Node, Bun and Deno answer them from their own builtins.

The bare form works too. import fs from 'fs' resolves the same way, which is why dependencies written before the node: prefix existed keep working unchanged.

process, Buffer, URL, structuredClone, queueMicrotask and setImmediate are there without one. An --app gjs build scans the bundled output, finds the ones you actually reach, and injects only those. An --app node build injects none of them, because Node, Bun and Deno already define them.

TypeScript
const port = Number(process.env.PORT ?? '8080');
const body = Buffer.from('hello', 'utf-8');

Three levels of completeness. Full means everything a normal app touches is there. Partial means the core works and specific corners are missing, each one named in the table. Stub means the module resolves so a dependency check passes, but does nothing useful.

Node.js API Coverage

38 of 41 Node.js modules

User-facing Node modules backed by GLib, Gio, Soup, and native Vala bridges. 3 deprecated or browser-irrelevant modules ship as stubs so dependency checks resolve.

93% 33 full 5 partial 3 stub
4 / 4 Full Full Full Full 8 / 8 Full Full Full Server + ClientRequest + Agent Full Full h2 via ALPN; pushStream/respondWithFD/respondWithFile via @gjsify/http2-native (libnghttp2) Full Full npm ws drop-in; Autobahn 510 OK / 0 FAIL Partial 4 / 4 Full Full Full Full 1 / 1 Full 3 / 4 Full Cross-process IPC, file-based workers Partial Full Stub 6 / 6 Full Full Full Full Full Full 9 / 11 Full Full Full Full Full Full GLib-source-safe (GLib.timeout_add) Full Full Deprecated alias for util Full Stub Deprecated by Node Stub 1 / 1 Partial 2 / 2 runInThisContext via eval; no realm isolation Partial Wire-format v15 serialize/deserialize; no heap snapshot or CPU profile Partial
ModuleBacked byStatusWorth knowing
assertpure TSFullAssertionError, deepEqual, throws, strict
async_hookspure TSFullAsyncLocalStorage, AsyncResource, createHook
bufferpure TSFullalloc, from, concat, every encoding, read/write helpers, plus the Blob and File classes Node re-exports here
child_processGioFullexec, execFile, spawn, and their sync variants, via Gio.Subprocess. Shell, detached, argv0 and signal numbers resolve per platform. Per-platform contract: package README
clusterpure TSStubisPrimary / isWorker only; fork() throws
consolepure TSFullConsole class, format specifiers, table, group, count, time
constantspure TSFullThe deprecated flat alias for os.constants plus fs.constants
cryptoGLibFullHash, Hmac, PBKDF2, HKDF, scrypt, AES, DH, ECDH, Sign / Verify, KeyObject, X509
dgramGioFullUDP over Gio.Socket, incl. multicast, broadcast, TTL, IPv6
diagnostics_channelpure TSFullChannel, TracingChannel, subscribe / unsubscribe
dnsGioFulllookup, resolve4/6, reverse via Gio.Resolver, plus dns/promises
domainpure TSStubDeprecated in Node; pass-through
eventspure TSFullEventEmitter with enumerable prototype methods, so socket.io v4 works
fsGioFullsync, callback, promises, streams, FSWatcher, FileHandle; URL path args everywhere
globalsGLibFullNot an import. This is @gjsify/node-globals, the package behind process, Buffer, URL, URLSearchParams, structuredClone, queueMicrotask, btoa / atob and the timer family
httpSoup 3.0FullServer, IncomingMessage, ServerResponse, Agent, chunked streaming, upgrade
http2Soup 3.0Fullh2 over ALPN, plus respondWithFile and respondWithFD via @gjsify/http2-native. pushStream builds the PUSH_PROMISE and hands you a working stream object, but Soup exposes no way to put it on the wire
httpsSoup 3.0FullTLS Agent, request / get, createServer
inspectorpure TSStubSession stub; the V8 inspector protocol has no GJS equivalent
moduleGio, GLibFullbuiltinModules, isBuiltin, createRequire (PnP aware)
netGioFullSocket over Gio.SocketClient, Server over Gio.SocketService, isIP
osGLibFullhomedir, hostname, cpus, platform, userInfo, networkInterfaces, loadavg
pathpure TSFullPOSIX and Win32 flavours, selected per host
perf_hookspure TSFullperformance, marks and measures, PerformanceObserver, timerify
processGLibFullEventEmitter based; env, cwd, argv, platform, hrtime, nextTick, memoryUsage
querystringpure TSFullparse / stringify with full encoding
readlinepure TSFullInterface, createInterface, question, prompt, async iterator, cursor control
sqliteGda 6.0PartialDatabaseSync and StatementSync on the libgda SQLite provider
streampure TSFullReadable, Writable, Duplex, Transform, PassThrough, objectMode, backpressure
string_decoderpure TSFullUTF-8, Base64, hex, streaming
syspure TSFullDeprecated alias, re-exports util
timerspure TSFullsetTimeout / setInterval / setImmediate plus timers/promises, on GLib sources
tlsGioFullTLSSocket over Gio.TlsClientConnection; mTLS, ALPN, peer certificates
ttyGLib, @gjsify/terminal-nativeFullReadStream / WriteStream, isatty, ANSI escapes, window size, raw mode
urlGLibFullURL incl. createObjectURL / revokeObjectURL, URLSearchParams over GLib.Uri
utilpure TSFullinspect, format, promisify, callbackify, styleText, types
v8GLibPartialserialize / deserialize (wire format v15); getHeapStatistics is approximated from OS process memory (/proc/self/status on Linux, ps on macOS) and reports all zeros where neither is readable. No heap snapshots, no CPU profiles
vmpure TSPartialrunInThisContext, runInNewContext, Script, compileFunction, without realm isolation
worker_threadsGio, GLibPartialMessageChannel, MessagePort, BroadcastChannel; Worker runs as a subprocess. SharedArrayBuffer is cross-process and file backed via @gjsify/sab-native
ws (npm)Soup 3.0PartialDrop-in for the ws package: client plus WebSocketServer over @gjsify/websocket
zlibGioFullgzip, deflate and deflate-raw over Gio.ZlibCompressor. A host that brings its own Compression Streams API gets that path instead

ws is in this list because import { WebSocketServer } from 'ws' is aliased to @gjsify/ws, so packages that depend on ws work without a change. isomorphic-ws and node-fetch are aliased the same way.

Every package declares which runtimes it supports, in a gjsify.runtimes field. Pure TypeScript modules such as path, buffer, events, querystring and string_decoder also run in the browser and under NativeScript. The Gio-backed ones such as fs, net, http and crypto declare an implementation for GJS only: they call into GIO and Soup directly, and on Node, Bun and Deno the same import resolves to that runtime’s own builtin instead. Runtimes has the whole picture, and Platform Support covers which operating systems each native bridge reaches.