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

Installation
# 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
Basic Usage (dynamic API)
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)
Versioned Persistence (commit round-trip)
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.