@lastshotlabs/slingshot-runtime-node
v0.0.2
Published
Node.js runtime implementation for Slingshot
Readme
title: Human Guide description: Human-maintained guidance for @lastshotlabs/slingshot-runtime-node
@lastshotlabs/slingshot-runtime-node is the Node.js runtime implementation for Slingshot.
Pass the return value of nodeRuntime() to defineApp({ runtime }) in your app.config.ts.
What It Provides
- password —
argon2(peer dep) for argon2id hashing and constant-time verification - sqlite —
better-sqlite3(peer dep) opened in WAL mode with synchronous API - server —
@hono/node-server(peer dep) wrapping Nodehttp.Server; TLS viaopts.tls; WebSocket viawspeer dep - fs —
node:fs/promiseswith ENOENT-safereadFileandaccess-basedexists - glob —
fast-glob(peer dep) withdot: falseby default
Minimum Setup
import { defineApp } from '@lastshotlabs/slingshot';
import { nodeRuntime } from '@lastshotlabs/slingshot-runtime-node';
export default defineApp({
runtime: nodeRuntime(),
port: 3000,
});Peer Dependencies
All peer deps are loaded lazily via dynamic import() at first use, not at module import time.
Missing deps surface at the first call to the affected capability.
| Capability | Peer dep |
| ---------- | ------------------- |
| password | argon2 |
| sqlite | better-sqlite3 |
| server | @hono/node-server |
| websocket | ws |
| glob | fast-glob |
Operational Notes
readFile()returnsnullonENOENT. All other errors (EACCES,EISDIR, etc.) are re-thrown — they are not silently swallowed.fs.exists()usesfs.accessand returnsfalsefor any error, including permission errors, so it does not distinguish ENOENT from EACCES.- SQLite databases are opened in WAL mode (
PRAGMA journal_mode = WAL). Run your application's migration step before any reads or writes. The runtime does not run migrations itself. better-sqlite3is a native CJS addon and is loaded viacreateRequire(not dynamicimport()) so it works correctly in Node ESM where barerequireis unavailable.password.hash()defaults to argon2id. The hash output includes the algorithm identifier so it is forward-compatible if the algorithm default changes.- WebSocket upgrade uses a pending-upgrade map keyed by
sec-websocket-key. Upgrades that are not completed within the timeout period have their socket destroyed automatically. The timeout defaults to 30 s and is configurable viaupgradeTimeoutMsin the server options. server.publish(channel, message)broadcasts only to open (readyState === 1) sockets; closed sockets in a channel are silently skipped.- TLS is supported via
opts.tls.keyandopts.tls.cert. Pass PEM strings orBuffervalues.
Gotchas
connection.portmust be a number, not a string. Env-var values need explicit coercion:port: Number(process.env.PORT).glob.scan()returns paths relative tocwd, not absolute. Join withcwdwhen you need absolute paths for subsequent file operations.stop(true)callsserver.closeAllConnections()(Node 18.2+ API) to force-close active connections. Passfalse(or no argument) if you want graceful drain.argon2.verify()returnsfalserather than throwing for malformed hash strings.
Key Files
src/index.ts
