TypeScript / Node generated SDK¶
The Node package supplies connection and native runtime primitives. Application models, values, managers, and query tokens come from the TypeScript package generated by the canonical Split-YAML workspace.
Install and generate¶
npm install @type-bridge/node
type-bridge --manifest typebridge.yaml schema check
type-bridge --manifest typebridge.yaml schema generate
Configure the generated target in typebridge.yaml:
Compile the generated package with its emitted TypeScript configuration. Do not
edit its sources or construct models with @type-bridge/node factories. The
package privately embeds the verified authority used by its managers and query
sessions; an ordinary Node application does not configure or read an external
JSON authority.
Connect¶
import { RustDatabase } from "@type-bridge/node";
const db = RustDatabase.connect("localhost:1729", "application", {
username: "admin",
password: "password",
httpPort: 8000,
});
Database lifecycle and credentials remain application-owned. Schema mutation is performed by explicit workspace migration commands, not model import.
Construct generated values¶
import {
Age,
Employment,
Person,
PersonId,
} from "./generated/typescript/dist/index.js";
const ada = Person.create({
personId: PersonId.create("ada"),
age: Age.create(36n),
});
Generated values are immutable. Integer attributes use JavaScript bigint so
the TypeDB integer domain is not silently truncated. Decimal and duration values
use their lossless generated boundary representations.
Managers¶
const manager = Person.manager(db);
const stored = manager.put(ada);
const people = manager.filter({ age__gte: Age.create(18n) }).all();
if (stored.iid !== null) {
const replacement = Person.create({
personId: PersonId.create("ada"),
age: Age.create(37n),
});
manager.update(stored.iid, replacement);
}
Generated entity and relation managers expose insert, insertMany, put,
putMany, immutable replacement update, delete, getByIid, filter,
all, first, count, and exists.
Packages whose schema uses ordered collections select the successor manager and
also expose atomic updateMany and deleteMany. Updates are readonly
[iid, replacement] tuples; deletes accept canonical IID strings. Insert, put,
and update batches return frozen values in input order, while delete returns no
affected-row count:
if (stored.iid !== null) {
const replacements = [
[stored.iid, Person.create({
personId: PersonId.create("ada"),
age: Age.create(38n),
})],
] as const;
const updated = manager.updateMany(replacements);
manager.deleteMany(replacements.map(([iid]) => iid));
}
Legacy unordered packages retain their existing manager surface and runtime resource exactly; regenerate from an ordered schema to use the successor batch methods.
The successor manager also exposes immutable, token-branded canonical filters:
const threshold = Person.manager(db)
.where(Person.fields.age, "gte", Age.create(18n));
const adults = threshold.all();
const ada = Person.manager(db)
.where(Person.fields.personId, "eq", PersonId.create("ada"))
.first();
Each where returns a reusable sibling. Canonical filters accept only generated
field tokens, exact generated values, and eq, ne, lt, lte, gt, or
gte; Boolean ordering rejects before I/O. Their first requires equality for
every effective reference-key field and proves optional singularity. The
object-based filter(...) API remains available for compatibility lookups and
keeps its existing arbitrary-first behavior.
Filter keys use generated TypeScript field names plus optional __eq, __ne,
__gt, __gte, __lt, or __lte suffixes. Use a trailing __eq when a
generated field name itself collides with a lookup suffix.
Relations¶
const employment = Employment.create({
employee: stored,
employer: acme,
});
Employment.manager(db).insert(employment);
The constructor admits only generated player types allowed by the canonical
plays facts. Generated reference values can supply an existing IID/key without
hydrating a complete player.
Direct queries¶
import { QuerySession } from "./generated/typescript/dist/index.js";
const session = new QuerySession(db);
const person = session.exact(Person);
const employmentVar = session.exact(Employment);
const adult = person.field(Person.age).gte(Age.create(18n));
const employee = employmentVar.role(Employment.employee).connects(person);
const rows = session
.query(person, employmentVar)
.where(adult, employee)
.rows({ limit: 100n });
The generated query facade supports exact/subtype bindings, owner-aware fields and roles, comparison/string/Boolean predicates, explicit cross joins, bounded reachability, positional/named/collected shapes, ordering, windows, pages, counts, existence, and direct reducers/grouping.
const left = session.exact(Person);
const right = session.exact(Person);
const pairs = session
.query(left, right)
.allowCrossJoin(left, right)
.rows({ limit: 10n });
Transactions¶
const transaction = db.transaction("write");
try {
const person = Person.manager(transaction).put(ada);
Employment.manager(transaction).insert(
Employment.create({ employee: person, employer: acme }),
);
transaction.commit();
} catch (error) {
transaction.rollback();
throw error;
}
Generated managers never commit a caller-owned transaction. Close read transactions after their final query terminal.
Remote queries¶
The generated package exports RemoteQuerySession and privately embeds its
verified Query V2 authority. Supply the exact server advertisement, a
caller-owned one-exchange callback, and resource limits—never an authority file
or QueryV2Authority:
import {
Person,
RemoteQuerySession,
} from "./generated/typescript/dist/index.js";
const remote = new RemoteQuerySession(
advertisementBytes,
exchange,
{
maxItems: 100n,
maxBytes: 8_388_608n,
maxCollectionMembers: 1_000n,
maxGraphNodes: 1_000n,
maxAttributeValues: 1_000n,
maxRolePlayers: 1_000n,
deadlineMs: 30_000n,
},
);
const person = remote.exact(Person);
const rows = await remote.query(person).rows({ limit: 50n });
advertisementBytes must come from the intended server over authenticated TLS
or be pinned out of band. exchange performs one authenticated request and
returns the exact response bytes; TypeBridge does not choose an HTTP client,
credential policy, or retry policy. Query composition performs no I/O; one,
first, bounded rows, pageBy, countBy, existsBy, and typed
aggregate/groupBy each perform one exchange and hydrate the same generated
classes and scalar groups as direct execution. Generated remote mutation APIs
are not advertised.
Runtime boundary¶
@type-bridge/node no longer serves as a model factory, schema parser, or
programmatic generator. The generated package installs canonical projection
bytes into the native runtime and native class identity checks reject
structural lookalikes or values from another generated package.
Packaging note¶
Generated TypeScript packages require @type-bridge/node 2.1 or newer within
the 2.x line. The npm package publishes native modules for Linux glibc
(x64/arm64), macOS (x64/arm64), and Windows (x64/arm64); other
targets build from source and must satisfy the repository toolchain.