dsviper for Node.js
The strongly typed Node.js runtime over the Viper C++ engine — the same surface as the Python dsviper, idiomatic to JavaScript and TypeScript. The back-end target: server-side JS/TS over the same engine and the same on-disk format.
Strong Typing
Like the Python runtime, dsviper raises immediately on type mismatch — values are validated at construction, never silently coerced.
// Type checking at construction — throws on mismatch
Value.create(Type.BOOL, 4); // ViperError
Value.create(Type.INT8, 256); // ViperError — outside int8 range JavaScript-native, Java-like values
JS natives (arrays, objects, bigint) are accepted as input ; metadata drives the conversion. A value is a typed handle, not a JS record — compare with .equals / .compare, never ==.
// JS natives accepted as input — metadata drives the conversion
Value.create(new TypeVector(Type.INT64), [1, 2, 3]);
// Let Viper infer the type from the native
Value.deduce(3.14); // double What's Included
The Node API surface mirrors the Python dsviper wheel one-to-one — same engine, same on-disk format, same 1.2 contract. See the documentation for the full reference.
Types & Values
Complete type system: primitives, containers, structures, enums, variants.
Definitions
The runtime catalogue — Types + Attachments. Embedded in every database and every payload ; merged on the fly. This is Metadata Everywhere.
Database
SQLite-backed persistence with transactions and schema migration.
Commit
Mutation DAG — CommitDatabase, CommitStore, the Commit Application Model — covered in its own dedicated section.
Service (client)
Consume typed function pools over the wire as a remote client
(ServiceRemote) — a back-end calls services, it doesn't
host them. See the Service section.
Serialization
Binary and JSON codecs. Streaming support for large data.
Blobs
Binary large objects up to 2GB with content-addressed storage.
DSM tooling
Parse .dsm into DSM Definitions (symbolic)
and Definitions (runtime). Encode and decode between DSM,
JSON, binary, and HTML.
Quick Start
# Install from npm
npm install @digitalsubstrate/dsviper
# Verify installation
node -e "console.log(require('@digitalsubstrate/dsviper').viperVersion())"
# Output: [ 1, 2, 17 ] — the embedded Viper runtime const { Value, Type, TypeVector, ValueInt64 } = require('@digitalsubstrate/dsviper');
// Universal constructor — Value.create(type, [initialValue])
Value.create(Type.DOUBLE).encoded(); // 0.0
Value.create(Type.STRING, 'hello').encoded(); // 'hello'
Value.create(new TypeVector(Type.INT64), [1, 2, 3]).size(); // 3
// Type checking enforced — immediate error on mismatch
Value.create(Type.BOOL, 4); // throws ViperError
// A value is a typed handle: compare with .equals, never ==
new ValueInt64(42n).equals(42n); // true (64-bit values are bigint) const {
Definitions, NameSpace, ValueUUId, Type,
CommitDatabase, CommitMutableState, CommitStateBuilder,
} = require('@digitalsubstrate/dsviper');
// Describe a schema: namespace, concept, attachment<User, INT64>
const defs = new Definitions();
const ns = new NameSpace(ValueUUId.create(), 'Tuto');
const User = defs.createConcept(ns, 'User');
const score = defs.createAttachment(ns, 'score', User, Type.INT64);
// Open an in-memory database and seal the schema into it
const db = CommitDatabase.createInMemory();
db.extendDefinitions(defs.const());
// Stage a typed write, then land it as a single commit
const alice = score.createKey();
const state = new CommitMutableState(CommitStateBuilder.initialState(db));
state.attachmentMutating().set(score, alice, 42);
db.commitMutations('Set alice score', state);
// Read back through the latest commit
CommitStateBuilder.state(db, db.lastCommitId())
.attachmentGetting().get(score, alice).unwrap(); // 42n Start Building
Install the Node binding and follow the tutorial to build your first back-end application.