@loradb/lora-node 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,6 +73,40 @@ method signatures still match `lora-wasm`.
73
73
  Call `db.dispose()` when you need to release the native handle eagerly,
74
74
  especially before reopening the same WAL directory in the same process.
75
75
 
76
+ ## Snapshots
77
+
78
+ `saveSnapshot(path)` writes the current graph to a local file. It also accepts
79
+ typed formats: `"binary"` returns a Node `Buffer`, `"base64"` returns base64
80
+ text, and `{ format: "path", path }` accepts either a path string or `file:`
81
+ URL.
82
+
83
+ `loadSnapshot` accepts a `NodeSnapshotSource`: a filesystem path, `file:` URL,
84
+ HTTP(S) or `data:` URL, `Buffer`, `Uint8Array`, `ArrayBuffer`, Node
85
+ `Readable`, web `ReadableStream`, or async iterable of byte chunks.
86
+
87
+ ```ts
88
+ import { readFile } from "node:fs/promises";
89
+ import { createReadStream } from "node:fs";
90
+ import { pathToFileURL } from "node:url";
91
+ import { createDatabase } from "lora-node";
92
+
93
+ const db = await createDatabase();
94
+ await db.execute("CREATE (:Person {name: 'Alice'})");
95
+ await db.saveSnapshot("./graph.lorasnap");
96
+ const bytes = await db.saveSnapshot("binary");
97
+ const base64 = await db.saveSnapshot({ format: "base64" });
98
+
99
+ await db.loadSnapshot("./graph.lorasnap");
100
+ await db.loadSnapshot(pathToFileURL("./graph.lorasnap"));
101
+ await db.loadSnapshot(await readFile("./graph.lorasnap"));
102
+ await db.loadSnapshot(createReadStream("./graph.lorasnap"));
103
+ await db.loadSnapshot(bytes);
104
+ await db.loadSnapshot(new URL("https://example.com/graph.lorasnap"));
105
+ ```
106
+
107
+ Use `loadSnapshotFromBytes(bytes)` when you already have in-memory bytes and
108
+ want to make that intent explicit.
109
+
76
110
  ## Typed value model
77
111
 
78
112
  | TS type | Runtime shape |
@@ -139,13 +173,12 @@ identical to `lora-wasm`.
139
173
 
140
174
  ## Known limitations
141
175
 
142
- - **Concurrent writes.** Each `execute()` hops through the threadpool and
143
- serialises on the store mutex inside Rust, so concurrent read/read and
144
- read/write traffic works. Firing many concurrent write queries against
145
- the same `Database` (e.g. 2 000 parallel `CREATE`s via `Promise.all`)
146
- can expose races in the underlying engine — treat the mutex as
147
- per-operation, not per-query. Prefer `await`-in-a-loop or a single
148
- batched query for heavy write workloads.
176
+ - **Concurrent writes.** Each `execute()` hops through the threadpool; read
177
+ queries can share the store read lock, while writes serialize on the store
178
+ write lock. Firing many concurrent write queries against the same
179
+ `Database` (e.g. 2 000 parallel `CREATE`s via `Promise.all`) works but
180
+ queues behind that write lock. Prefer `await`-in-a-loop or a single batched
181
+ query for heavy write workloads.
149
182
  - **I64 precision.** Integer values above `Number.MAX_SAFE_INTEGER`
150
183
  (2^53) are returned as JS `number` and lose precision. A `bigint`-aware
151
184
  path would require extending the value serializer.
package/dist/index.d.ts CHANGED
@@ -12,6 +12,8 @@
12
12
  * synchronous constructor. See the docs at
13
13
  * https://loradb.com/docs/getting-started/node for the full rationale.
14
14
  */
15
+ import { Buffer } from "node:buffer";
16
+ import { Readable } from "node:stream";
15
17
  import type { LoraParams, LoraValue, QueryResult } from "./types.js";
16
18
  declare const NativeDatabase: typeof import("./native.js").Database;
17
19
  export * from "./types.js";
@@ -27,6 +29,29 @@ export interface SnapshotMeta {
27
29
  relationshipCount: number;
28
30
  walLsn: number | null;
29
31
  }
32
+ export type NodeSnapshotChunk = string | Uint8Array | ArrayBuffer | Buffer;
33
+ export type NodeSnapshotSource = string | URL | Uint8Array | ArrayBuffer | Buffer | Readable | ReadableStream<NodeSnapshotChunk> | AsyncIterable<NodeSnapshotChunk>;
34
+ export type NodeSnapshotSaveFormat = "binary" | "base64";
35
+ export type NodeSnapshotSaveOptions = {
36
+ format: "path";
37
+ path: string | URL;
38
+ } | {
39
+ format: NodeSnapshotSaveFormat;
40
+ };
41
+ export type NodeSnapshotSaveTarget = string | URL | NodeSnapshotSaveFormat | NodeSnapshotSaveOptions;
42
+ export interface CreateDatabaseOptions {
43
+ databaseDir?: string;
44
+ }
45
+ export type TransactionMode = "read_write" | "read_only" | "readwrite" | "readonly" | "rw" | "ro";
46
+ export interface TransactionStatement {
47
+ query: string;
48
+ params?: LoraParams | null;
49
+ }
50
+ export interface RowStream<T extends Record<string, LoraValue> = Record<string, LoraValue>> extends AsyncIterableIterator<T> {
51
+ columns(): string[];
52
+ toArray(): Promise<T[]>;
53
+ close(): void;
54
+ }
30
55
  /**
31
56
  * Lora graph database instance.
32
57
  *
@@ -36,8 +61,8 @@ export interface SnapshotMeta {
36
61
  * state from disk before serving queries.
37
62
  *
38
63
  * Instances are independent — each owns its own in-memory graph. Multiple
39
- * concurrent `execute()` calls against one instance run one at a time
40
- * (serialised on the store mutex) but none of them block the event loop.
64
+ * concurrent read-only `execute()` calls against one instance can share
65
+ * the store read lock; writes serialize without blocking the event loop.
41
66
  */
42
67
  declare class DatabaseImpl {
43
68
  #private;
@@ -48,6 +73,24 @@ declare class DatabaseImpl {
48
73
  * with a narrowed `code` (`LORA_ERROR` / `INVALID_PARAMS`).
49
74
  */
50
75
  execute<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): Promise<QueryResult<T>>;
76
+ /**
77
+ * Return an async row iterator for a query.
78
+ *
79
+ * The binding exposes the same `for await` shape as the Rust stream API.
80
+ * Rows are materialized by the native `execute()` promise today, then
81
+ * yielded one at a time to JS consumers.
82
+ */
83
+ stream<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): RowStream<T>;
84
+ /** Alias for `stream()`, useful when naming the row-level API explicitly. */
85
+ rows<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): RowStream<T>;
86
+ /**
87
+ * Execute a statement batch inside one native transaction.
88
+ *
89
+ * Results are returned in statement order. If any statement fails, the
90
+ * native transaction is dropped before commit and all prior writes in the
91
+ * batch are rolled back.
92
+ */
93
+ transaction<T extends Record<string, LoraValue> = Record<string, LoraValue>>(statements: TransactionStatement[], mode?: TransactionMode): Promise<Array<QueryResult<T>>>;
51
94
  /** Drop every node and relationship. Constant-time under the hood. */
52
95
  clear(): Promise<void>;
53
96
  /** Number of nodes currently in the graph. */
@@ -61,22 +104,27 @@ declare class DatabaseImpl {
61
104
  * process. New operations after disposal reject with `database is closed`.
62
105
  */
63
106
  dispose(): void;
64
- /**
65
- * Save the graph to a snapshot file. Writes atomically via a `.tmp` +
66
- * rename dance — the target path is only replaced once the full payload
67
- * has been written and fsync'd.
68
- *
69
- * Synchronous in the native layer (point-in-time consistency requires
70
- * holding the store mutex for the duration of the save); the returned
71
- * Promise resolves immediately once the save returns.
72
- */
73
- saveSnapshot(path: string): Promise<SnapshotMeta>;
107
+ saveSnapshot(format: "binary"): Promise<Buffer>;
108
+ saveSnapshot(format: "base64"): Promise<string>;
109
+ saveSnapshot(path: string | URL): Promise<SnapshotMeta>;
110
+ saveSnapshot(options: {
111
+ format: "binary";
112
+ }): Promise<Buffer>;
113
+ saveSnapshot(options: {
114
+ format: "base64";
115
+ }): Promise<string>;
116
+ saveSnapshot(options: {
117
+ format: "path";
118
+ path: string | URL;
119
+ }): Promise<SnapshotMeta>;
120
+ saveSnapshotToBytes(): Promise<Buffer>;
74
121
  /**
75
122
  * Replace the current graph state with a snapshot loaded from `path`.
76
- * Concurrent `execute()` calls block on the store mutex until the load
77
- * completes.
123
+ * Concurrent `execute()` calls block on the store write lock until the
124
+ * load completes.
78
125
  */
79
- loadSnapshot(path: string): Promise<SnapshotMeta>;
126
+ loadSnapshot(source: NodeSnapshotSource): Promise<SnapshotMeta>;
127
+ loadSnapshotFromBytes(bytes: Uint8Array | ArrayBuffer | Buffer): Promise<SnapshotMeta>;
80
128
  }
81
129
  /**
82
130
  * Public type for a LoraDB instance.
@@ -123,5 +171,5 @@ export type Database = DatabaseImpl;
123
171
  *
124
172
  * Each call returns an independent graph — no shared state between instances.
125
173
  */
126
- export declare function createDatabase(walDir?: string): Promise<Database>;
174
+ export declare function createDatabase(databaseName?: string, options?: CreateDatabaseOptions): Promise<Database>;
127
175
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACZ,MAAM,YAAY,CAAC;AAOpB,QAAA,MAAM,cAAc,EAAE,cAAc,aAAa,EAAE,QAA0B,CAAC;AAE9E,cAAc,YAAY,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,cAAM,YAAY;;gBAGJ,KAAK,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC;IAItD;;;;OAIG;IACG,OAAO,CACX,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAC/D,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAS9D,sEAAsE;IAChE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,8CAA8C;IACxC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAQlC,sDAAsD;IAChD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ1C;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAQf;;;;;;;;OAQG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQvD;;;;OAIG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAOxD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAQvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -32,12 +32,178 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
34
  exports.createDatabase = createDatabase;
35
+ const node_buffer_1 = require("node:buffer");
36
+ const node_stream_1 = require("node:stream");
37
+ const node_url_1 = require("node:url");
35
38
  const types_js_1 = require("./types.js");
36
39
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
37
40
  // @ts-ignore - resolved at runtime via native.js loader
38
41
  const native_js_1 = __importDefault(require("./native.js"));
39
42
  const NativeDatabase = native_js_1.default.Database;
40
43
  __exportStar(require("./types.js"), exports);
44
+ class NativeRowStream {
45
+ #inner;
46
+ #streamId;
47
+ #closed = false;
48
+ constructor(inner, streamId) {
49
+ this.#inner = inner;
50
+ this.#streamId = streamId;
51
+ }
52
+ [Symbol.asyncIterator]() {
53
+ return this;
54
+ }
55
+ columns() {
56
+ try {
57
+ return this.#inner.streamColumns(this.#streamId);
58
+ }
59
+ catch (err) {
60
+ throw (0, types_js_1.wrapError)(err);
61
+ }
62
+ }
63
+ async next() {
64
+ if (this.#closed) {
65
+ return { done: true, value: undefined };
66
+ }
67
+ try {
68
+ const row = this.#inner.streamNext(this.#streamId);
69
+ if (row === null) {
70
+ this.#closed = true;
71
+ return { done: true, value: undefined };
72
+ }
73
+ return { done: false, value: row };
74
+ }
75
+ catch (err) {
76
+ this.#closed = true;
77
+ throw (0, types_js_1.wrapError)(err);
78
+ }
79
+ }
80
+ async return() {
81
+ this.close();
82
+ return { done: true, value: undefined };
83
+ }
84
+ async toArray() {
85
+ const rows = [];
86
+ for (;;) {
87
+ const next = await this.next();
88
+ if (next.done) {
89
+ return rows;
90
+ }
91
+ rows.push(next.value);
92
+ }
93
+ }
94
+ close() {
95
+ if (this.#closed)
96
+ return;
97
+ this.#closed = true;
98
+ try {
99
+ this.#inner.streamClose(this.#streamId);
100
+ }
101
+ catch (err) {
102
+ throw (0, types_js_1.wrapError)(err);
103
+ }
104
+ }
105
+ }
106
+ function isFetchUrl(url) {
107
+ return url.protocol === "http:" || url.protocol === "https:" || url.protocol === "data:";
108
+ }
109
+ function stringToUrl(value) {
110
+ try {
111
+ return new URL(value);
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ }
117
+ function bytesToUint8Array(bytes) {
118
+ if (bytes instanceof Uint8Array) {
119
+ return bytes;
120
+ }
121
+ return new Uint8Array(bytes);
122
+ }
123
+ function snapshotChunkToBuffer(chunk) {
124
+ return typeof chunk === "string"
125
+ ? node_buffer_1.Buffer.from(chunk)
126
+ : node_buffer_1.Buffer.from(bytesToUint8Array(chunk));
127
+ }
128
+ function resolveNodeSnapshotPath(path) {
129
+ if (path instanceof URL) {
130
+ if (path.protocol !== "file:") {
131
+ throw new Error(`LORA_ERROR: unsupported snapshot save URL protocol '${path.protocol}'`);
132
+ }
133
+ return (0, node_url_1.fileURLToPath)(path);
134
+ }
135
+ return path;
136
+ }
137
+ async function fetchSnapshotBytes(url) {
138
+ const res = await fetch(url);
139
+ if (!res.ok) {
140
+ throw new Error(`LORA_ERROR: snapshot fetch failed (${res.status} ${res.statusText})`);
141
+ }
142
+ return node_buffer_1.Buffer.from(await res.arrayBuffer());
143
+ }
144
+ function isReadableStream(source) {
145
+ return typeof source.getReader === "function";
146
+ }
147
+ function isAsyncIterable(source) {
148
+ return typeof source[Symbol.asyncIterator] === "function";
149
+ }
150
+ async function readableStreamToBuffer(stream) {
151
+ const reader = stream.getReader();
152
+ const chunks = [];
153
+ try {
154
+ for (;;) {
155
+ const { done, value } = await reader.read();
156
+ if (done) {
157
+ return node_buffer_1.Buffer.concat(chunks);
158
+ }
159
+ chunks.push(snapshotChunkToBuffer(value));
160
+ }
161
+ }
162
+ finally {
163
+ reader.releaseLock();
164
+ }
165
+ }
166
+ async function asyncIterableToBuffer(stream) {
167
+ const chunks = [];
168
+ for await (const chunk of stream) {
169
+ chunks.push(snapshotChunkToBuffer(chunk));
170
+ }
171
+ return node_buffer_1.Buffer.concat(chunks);
172
+ }
173
+ async function resolveNodeSnapshotSource(source) {
174
+ if (source instanceof URL) {
175
+ if (source.protocol === "file:") {
176
+ return (0, node_url_1.fileURLToPath)(source);
177
+ }
178
+ if (isFetchUrl(source)) {
179
+ return fetchSnapshotBytes(source);
180
+ }
181
+ throw new Error(`LORA_ERROR: unsupported snapshot URL protocol '${source.protocol}'`);
182
+ }
183
+ if (typeof source === "string") {
184
+ const url = stringToUrl(source);
185
+ if (!url) {
186
+ return source;
187
+ }
188
+ if (url.protocol === "file:") {
189
+ return (0, node_url_1.fileURLToPath)(url);
190
+ }
191
+ if (isFetchUrl(url)) {
192
+ return fetchSnapshotBytes(url);
193
+ }
194
+ return source;
195
+ }
196
+ if (isReadableStream(source)) {
197
+ return readableStreamToBuffer(source);
198
+ }
199
+ if (source instanceof node_stream_1.Readable) {
200
+ return asyncIterableToBuffer(source);
201
+ }
202
+ if (isAsyncIterable(source)) {
203
+ return asyncIterableToBuffer(source);
204
+ }
205
+ return node_buffer_1.Buffer.from(bytesToUint8Array(source));
206
+ }
41
207
  /**
42
208
  * Lora graph database instance.
43
209
  *
@@ -47,8 +213,8 @@ __exportStar(require("./types.js"), exports);
47
213
  * state from disk before serving queries.
48
214
  *
49
215
  * Instances are independent — each owns its own in-memory graph. Multiple
50
- * concurrent `execute()` calls against one instance run one at a time
51
- * (serialised on the store mutex) but none of them block the event loop.
216
+ * concurrent read-only `execute()` calls against one instance can share
217
+ * the store read lock; writes serialize without blocking the event loop.
52
218
  */
53
219
  class DatabaseImpl {
54
220
  #inner;
@@ -69,6 +235,41 @@ class DatabaseImpl {
69
235
  throw (0, types_js_1.wrapError)(err);
70
236
  }
71
237
  }
238
+ /**
239
+ * Return an async row iterator for a query.
240
+ *
241
+ * The binding exposes the same `for await` shape as the Rust stream API.
242
+ * Rows are materialized by the native `execute()` promise today, then
243
+ * yielded one at a time to JS consumers.
244
+ */
245
+ stream(query, params) {
246
+ try {
247
+ const streamId = this.#inner.openStream(query, params ?? null);
248
+ return new NativeRowStream(this.#inner, streamId);
249
+ }
250
+ catch (err) {
251
+ throw (0, types_js_1.wrapError)(err);
252
+ }
253
+ }
254
+ /** Alias for `stream()`, useful when naming the row-level API explicitly. */
255
+ rows(query, params) {
256
+ return this.stream(query, params);
257
+ }
258
+ /**
259
+ * Execute a statement batch inside one native transaction.
260
+ *
261
+ * Results are returned in statement order. If any statement fails, the
262
+ * native transaction is dropped before commit and all prior writes in the
263
+ * batch are rolled back.
264
+ */
265
+ async transaction(statements, mode = "read_write") {
266
+ try {
267
+ return (await this.#inner.transaction(statements, mode));
268
+ }
269
+ catch (err) {
270
+ throw (0, types_js_1.wrapError)(err);
271
+ }
272
+ }
72
273
  /** Drop every node and relationship. Constant-time under the hood. */
73
274
  async clear() {
74
275
  try {
@@ -111,17 +312,44 @@ class DatabaseImpl {
111
312
  }
112
313
  }
113
314
  /**
114
- * Save the graph to a snapshot file. Writes atomically via a `.tmp` +
115
- * rename dance — the target path is only replaced once the full payload
116
- * has been written and fsync'd.
315
+ * Save the graph as a snapshot.
117
316
  *
118
- * Synchronous in the native layer (point-in-time consistency requires
119
- * holding the store mutex for the duration of the save); the returned
120
- * Promise resolves immediately once the save returns.
317
+ * - `saveSnapshot(path)` and `saveSnapshot({ format: "path", path })`
318
+ * write atomically to a local file and return `SnapshotMeta`.
319
+ * - `saveSnapshot("binary")` / `{ format: "binary" }` return a `Buffer`.
320
+ * - `saveSnapshot("base64")` / `{ format: "base64" }` return base64 text.
121
321
  */
122
- async saveSnapshot(path) {
322
+ async saveSnapshot(target) {
323
+ try {
324
+ if (target === "binary" || (typeof target === "object"
325
+ && !(target instanceof URL)
326
+ && target.format === "binary")) {
327
+ return this.saveSnapshotToBytes();
328
+ }
329
+ if (target === "base64" || (typeof target === "object"
330
+ && !(target instanceof URL)
331
+ && target.format === "base64")) {
332
+ return (await this.saveSnapshotToBytes()).toString("base64");
333
+ }
334
+ let path;
335
+ if (typeof target === "object" && !(target instanceof URL)) {
336
+ if (target.format !== "path") {
337
+ throw new Error(`LORA_ERROR: unsupported snapshot save format '${target.format}'`);
338
+ }
339
+ path = target.path;
340
+ }
341
+ else {
342
+ path = target;
343
+ }
344
+ return this.#inner.saveSnapshot(resolveNodeSnapshotPath(path));
345
+ }
346
+ catch (err) {
347
+ throw (0, types_js_1.wrapError)(err);
348
+ }
349
+ }
350
+ async saveSnapshotToBytes() {
123
351
  try {
124
- return this.#inner.saveSnapshot(path);
352
+ return this.#inner.saveSnapshotToBytes();
125
353
  }
126
354
  catch (err) {
127
355
  throw (0, types_js_1.wrapError)(err);
@@ -129,12 +357,24 @@ class DatabaseImpl {
129
357
  }
130
358
  /**
131
359
  * Replace the current graph state with a snapshot loaded from `path`.
132
- * Concurrent `execute()` calls block on the store mutex until the load
133
- * completes.
360
+ * Concurrent `execute()` calls block on the store write lock until the
361
+ * load completes.
134
362
  */
135
- async loadSnapshot(path) {
363
+ async loadSnapshot(source) {
364
+ try {
365
+ const resolved = await resolveNodeSnapshotSource(source);
366
+ if (typeof resolved === "string") {
367
+ return this.#inner.loadSnapshot(resolved);
368
+ }
369
+ return this.#inner.loadSnapshotFromBytes(resolved);
370
+ }
371
+ catch (err) {
372
+ throw (0, types_js_1.wrapError)(err);
373
+ }
374
+ }
375
+ async loadSnapshotFromBytes(bytes) {
136
376
  try {
137
- return this.#inner.loadSnapshot(path);
377
+ return this.#inner.loadSnapshotFromBytes(node_buffer_1.Buffer.from(bytesToUint8Array(bytes)));
138
378
  }
139
379
  catch (err) {
140
380
  throw (0, types_js_1.wrapError)(err);
@@ -173,9 +413,11 @@ class DatabaseImpl {
173
413
  *
174
414
  * Each call returns an independent graph — no shared state between instances.
175
415
  */
176
- async function createDatabase(walDir) {
416
+ async function createDatabase(databaseName, options = {}) {
177
417
  try {
178
- return new DatabaseImpl(walDir === undefined ? new NativeDatabase() : new NativeDatabase(walDir));
418
+ return new DatabaseImpl(databaseName === undefined
419
+ ? new NativeDatabase()
420
+ : new NativeDatabase(databaseName, options.databaseDir ?? null));
179
421
  }
180
422
  catch (err) {
181
423
  throw (0, types_js_1.wrapError)(err);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loradb/lora-node",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Node.js / TypeScript bindings for the Lora in-memory graph database",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "LoraDB, Inc.",
@@ -89,10 +89,10 @@
89
89
  "vitest": "^2.1.1"
90
90
  },
91
91
  "optionalDependencies": {
92
- "@loradb/lora-node-linux-x64-gnu": "0.4.0",
93
- "@loradb/lora-node-linux-arm64-gnu": "0.4.0",
94
- "@loradb/lora-node-darwin-x64": "0.4.0",
95
- "@loradb/lora-node-darwin-arm64": "0.4.0",
96
- "@loradb/lora-node-win32-x64-msvc": "0.4.0"
92
+ "@loradb/lora-node-linux-x64-gnu": "0.5.0",
93
+ "@loradb/lora-node-linux-arm64-gnu": "0.5.0",
94
+ "@loradb/lora-node-darwin-x64": "0.5.0",
95
+ "@loradb/lora-node-darwin-arm64": "0.5.0",
96
+ "@loradb/lora-node-win32-x64-msvc": "0.5.0"
97
97
  }
98
98
  }
package/ts/native.d.ts CHANGED
@@ -19,18 +19,33 @@ export interface NativeSnapshotMeta {
19
19
  }
20
20
 
21
21
  export declare class Database {
22
- constructor(walDir?: string | null);
22
+ constructor(databaseName?: string | null, databaseDir?: string | null);
23
23
  /** Non-blocking: runs on the libuv threadpool, returns a Promise. */
24
24
  execute(
25
25
  query: string,
26
26
  params?: Record<string, unknown> | null,
27
27
  ): Promise<NativeQueryResult>;
28
+ openStream(
29
+ query: string,
30
+ params?: Record<string, unknown> | null,
31
+ ): number;
32
+ streamColumns(streamId: number): string[];
33
+ streamNext(streamId: number): Record<string, unknown> | null;
34
+ streamClose(streamId: number): void;
35
+ transaction(
36
+ statements: Array<{ query: string; params?: Record<string, unknown> | null }>,
37
+ mode?: "read_write" | "read_only" | "readwrite" | "readonly" | "rw" | "ro" | null,
38
+ ): Promise<NativeQueryResult[]>;
28
39
  clear(): void;
29
40
  nodeCount(): number;
30
41
  relationshipCount(): number;
31
42
  dispose(): void;
32
- /** Atomic save. Synchronous under the store mutex. */
43
+ /** Atomic save. Synchronous under the store read lock. */
33
44
  saveSnapshot(path: string): NativeSnapshotMeta;
45
+ /** Serialize the current graph into snapshot bytes. */
46
+ saveSnapshotToBytes(): Buffer;
34
47
  /** Replace the current graph with the snapshot at `path`. */
35
48
  loadSnapshot(path: string): NativeSnapshotMeta;
49
+ /** Replace the current graph with snapshot bytes. */
50
+ loadSnapshotFromBytes(bytes: Uint8Array | Buffer): NativeSnapshotMeta;
36
51
  }