@loradb/lora-node 0.2.0 → 0.4.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
@@ -1,7 +1,7 @@
1
1
  # lora-node
2
2
 
3
- Node.js / TypeScript bindings for the [Lora](../../README.md) in-memory
4
- graph engine. The package exposes a first-class typed API: query results are
3
+ Node.js / TypeScript bindings for the [Lora](../../README.md) graph
4
+ engine. The package exposes a first-class typed API: query results are
5
5
  modelled as discriminated unions, temporal values carry `kind` tags, and the
6
6
  `Database` class is strongly typed in both directions (params and rows).
7
7
 
@@ -29,13 +29,13 @@ to `package.json`.
29
29
  ## Usage
30
30
 
31
31
  `lora-node` is **async-only** — the sole initialization pattern is
32
- `createDatabase()`. There is no synchronous constructor and no
32
+ `createDatabase(...)`. There is no synchronous constructor and no
33
33
  `Database.create()` static; `Database` is a type-only export.
34
34
 
35
35
  ```ts
36
36
  import { createDatabase, isNode, type LoraNode } from "lora-node";
37
37
 
38
- const db = await createDatabase();
38
+ const db = await createDatabase(); // in-memory by default
39
39
  await db.execute("CREATE (:Person {name: $n, age: $a})", { n: "Alice", a: 30 });
40
40
 
41
41
  const res = await db.execute<{ n: LoraNode }>("MATCH (n:Person) RETURN n");
@@ -46,9 +46,32 @@ for (const row of res.rows) {
46
46
  }
47
47
  ```
48
48
 
49
- The API matches `lora-wasm` verbatim — same shared types, same
50
- `createDatabase()` entry point, same async method signatures — so
51
- switching backends is a single import change.
49
+ The initialization rule is:
50
+
51
+ ```ts
52
+ import { createDatabase } from "lora-node";
53
+
54
+ const inMemory = await createDatabase(); // in-memory only
55
+ const persistent = await createDatabase("./app"); // persistent: pass a directory string
56
+ ```
57
+
58
+ If you want persistence, pass a **directory string** to `createDatabase(...)`.
59
+
60
+ Node also has a WAL-backed convenience overload:
61
+
62
+ ```ts
63
+ import { createDatabase } from "lora-node";
64
+
65
+ const db = await createDatabase("./.lora-wal"); // persistent: directory string
66
+ ```
67
+
68
+ The string is treated as the WAL directory path verbatim. Relative
69
+ paths resolve from the current working directory. This is a Node-only
70
+ initialization convenience; the query surface, shared types, and async
71
+ method signatures still match `lora-wasm`.
72
+
73
+ Call `db.dispose()` when you need to release the native handle eagerly,
74
+ especially before reopening the same WAL directory in the same process.
52
75
 
53
76
  ## Typed value model
54
77
 
@@ -128,3 +151,9 @@ identical to `lora-wasm`.
128
151
  path would require extending the value serializer.
129
152
  - **Cancellation.** The napi `Task` abstraction does not support
130
153
  cancellation once dispatched; a runaway query runs to completion.
154
+ - **WAL surface.** This first Node persistence slice only exposes
155
+ WAL-backed initialization via `createDatabase(walDir)`. Checkpoint,
156
+ truncate, status, and sync-mode controls are not exposed yet.
157
+ - **WAL directory ownership.** A WAL directory can only be open by one
158
+ live handle at a time. Dispose the first handle before reopening the
159
+ same directory.
package/dist/index.d.ts CHANGED
@@ -7,20 +7,33 @@
7
7
  * native surface into the strongly-typed `QueryResult<T>` / `LoraParams`
8
8
  * shapes defined in the shared TS contract (`crates/shared-ts/types.ts`).
9
9
  *
10
- * **Initialization is async-only.** The one canonical entry point is
11
- * `createDatabase()`; there is no synchronous constructor. See the docs at
10
+ * **Initialization is async-only.** The canonical entry point is
11
+ * `createDatabase(...)`, optionally with a WAL directory path. There is no
12
+ * synchronous constructor. See the docs at
12
13
  * https://loradb.com/docs/getting-started/node for the full rationale.
13
14
  */
14
15
  import type { LoraParams, LoraValue, QueryResult } from "./types.js";
15
16
  declare const NativeDatabase: typeof import("./native.js").Database;
16
17
  export * from "./types.js";
17
18
  /**
18
- * In-memory Lora graph database instance.
19
+ * Metadata returned by `saveSnapshot` / `loadSnapshot`. Mirrors the Rust
20
+ * `SnapshotMeta` struct and matches the shape used by every other binding
21
+ * (Python, WASM, Go, FFI) so snapshots can be described in the same way
22
+ * regardless of language.
23
+ */
24
+ export interface SnapshotMeta {
25
+ formatVersion: number;
26
+ nodeCount: number;
27
+ relationshipCount: number;
28
+ walLsn: number | null;
29
+ }
30
+ /**
31
+ * Lora graph database instance.
19
32
  *
20
- * Obtained exclusively via `createDatabase()`. There is no public constructor
21
- * and no synchronous factory — the async entry point lets the binding
22
- * extend initialization later (lazy native loading, warmup, schema
23
- * preflight) without breaking callers.
33
+ * Obtained exclusively via `createDatabase()`. There is no public
34
+ * constructor and no synchronous factory. With no args the instance is
35
+ * purely in-memory; with a WAL directory path it replays committed WAL
36
+ * state from disk before serving queries.
24
37
  *
25
38
  * Instances are independent — each owns its own in-memory graph. Multiple
26
39
  * concurrent `execute()` calls against one instance run one at a time
@@ -41,6 +54,29 @@ declare class DatabaseImpl {
41
54
  nodeCount(): Promise<number>;
42
55
  /** Number of relationships currently in the graph. */
43
56
  relationshipCount(): Promise<number>;
57
+ /**
58
+ * Release the native database handle. Idempotent.
59
+ *
60
+ * Call this when a WAL-backed database needs to be reopened in the same
61
+ * process. New operations after disposal reject with `database is closed`.
62
+ */
63
+ 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>;
74
+ /**
75
+ * 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.
78
+ */
79
+ loadSnapshot(path: string): Promise<SnapshotMeta>;
44
80
  }
45
81
  /**
46
82
  * Public type for a LoraDB instance.
@@ -56,24 +92,36 @@ declare class DatabaseImpl {
56
92
  */
57
93
  export type Database = DatabaseImpl;
58
94
  /**
59
- * Create and initialize a new in-memory LoraDB instance.
95
+ * Create and initialize a new LoraDB instance.
60
96
  *
61
97
  * **This is the only supported initialization pattern** for `lora-node`.
62
98
  * Synchronous construction is not available — the async factory guarantees
63
- * the native layer is ready before the first query dispatches and keeps
64
- * the Node and WASM surfaces symmetric.
99
+ * the native layer is ready before the first query dispatches.
65
100
  *
66
101
  * ```ts
67
102
  * import { createDatabase } from "lora-node";
68
103
  *
69
- * const db = await createDatabase();
104
+ * const db = await createDatabase(); // in-memory by default
70
105
  * const res = await db.execute(
71
106
  * "CREATE (n:Person {name: $name}) RETURN n",
72
107
  * { name: "Alice" },
73
108
  * );
74
109
  * ```
75
110
  *
111
+ * Optional Node-only persistence convenience:
112
+ *
113
+ * ```ts
114
+ * import { createDatabase } from "lora-node";
115
+ *
116
+ * const inMemory = await createDatabase(); // in-memory
117
+ * const persistent = await createDatabase("./app"); // persistent: pass a directory string
118
+ * ```
119
+ *
120
+ * If you want persistence, pass a directory string. The string is treated
121
+ * as a WAL directory path verbatim. Relative paths resolve from the
122
+ * current working directory.
123
+ *
76
124
  * Each call returns an independent graph — no shared state between instances.
77
125
  */
78
- export declare function createDatabase(): Promise<Database>;
126
+ export declare function createDatabase(walDir?: string): Promise<Database>;
79
127
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;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;;;;;;;;;;;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;IAI5B,8CAA8C;IACxC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAIlC,sDAAsD;IAChD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;CAG3C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAExD"}
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"}
package/dist/index.js CHANGED
@@ -8,8 +8,9 @@
8
8
  * native surface into the strongly-typed `QueryResult<T>` / `LoraParams`
9
9
  * shapes defined in the shared TS contract (`crates/shared-ts/types.ts`).
10
10
  *
11
- * **Initialization is async-only.** The one canonical entry point is
12
- * `createDatabase()`; there is no synchronous constructor. See the docs at
11
+ * **Initialization is async-only.** The canonical entry point is
12
+ * `createDatabase(...)`, optionally with a WAL directory path. There is no
13
+ * synchronous constructor. See the docs at
13
14
  * https://loradb.com/docs/getting-started/node for the full rationale.
14
15
  */
15
16
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -38,12 +39,12 @@ const native_js_1 = __importDefault(require("./native.js"));
38
39
  const NativeDatabase = native_js_1.default.Database;
39
40
  __exportStar(require("./types.js"), exports);
40
41
  /**
41
- * In-memory Lora graph database instance.
42
+ * Lora graph database instance.
42
43
  *
43
- * Obtained exclusively via `createDatabase()`. There is no public constructor
44
- * and no synchronous factory — the async entry point lets the binding
45
- * extend initialization later (lazy native loading, warmup, schema
46
- * preflight) without breaking callers.
44
+ * Obtained exclusively via `createDatabase()`. There is no public
45
+ * constructor and no synchronous factory. With no args the instance is
46
+ * purely in-memory; with a WAL directory path it replays committed WAL
47
+ * state from disk before serving queries.
47
48
  *
48
49
  * Instances are independent — each owns its own in-memory graph. Multiple
49
50
  * concurrent `execute()` calls against one instance run one at a time
@@ -70,38 +71,114 @@ class DatabaseImpl {
70
71
  }
71
72
  /** Drop every node and relationship. Constant-time under the hood. */
72
73
  async clear() {
73
- this.#inner.clear();
74
+ try {
75
+ this.#inner.clear();
76
+ }
77
+ catch (err) {
78
+ throw (0, types_js_1.wrapError)(err);
79
+ }
74
80
  }
75
81
  /** Number of nodes currently in the graph. */
76
82
  async nodeCount() {
77
- return this.#inner.nodeCount();
83
+ try {
84
+ return this.#inner.nodeCount();
85
+ }
86
+ catch (err) {
87
+ throw (0, types_js_1.wrapError)(err);
88
+ }
78
89
  }
79
90
  /** Number of relationships currently in the graph. */
80
91
  async relationshipCount() {
81
- return this.#inner.relationshipCount();
92
+ try {
93
+ return this.#inner.relationshipCount();
94
+ }
95
+ catch (err) {
96
+ throw (0, types_js_1.wrapError)(err);
97
+ }
98
+ }
99
+ /**
100
+ * Release the native database handle. Idempotent.
101
+ *
102
+ * Call this when a WAL-backed database needs to be reopened in the same
103
+ * process. New operations after disposal reject with `database is closed`.
104
+ */
105
+ dispose() {
106
+ try {
107
+ this.#inner.dispose();
108
+ }
109
+ catch (err) {
110
+ throw (0, types_js_1.wrapError)(err);
111
+ }
112
+ }
113
+ /**
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.
117
+ *
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.
121
+ */
122
+ async saveSnapshot(path) {
123
+ try {
124
+ return this.#inner.saveSnapshot(path);
125
+ }
126
+ catch (err) {
127
+ throw (0, types_js_1.wrapError)(err);
128
+ }
129
+ }
130
+ /**
131
+ * 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.
134
+ */
135
+ async loadSnapshot(path) {
136
+ try {
137
+ return this.#inner.loadSnapshot(path);
138
+ }
139
+ catch (err) {
140
+ throw (0, types_js_1.wrapError)(err);
141
+ }
82
142
  }
83
143
  }
84
144
  /**
85
- * Create and initialize a new in-memory LoraDB instance.
145
+ * Create and initialize a new LoraDB instance.
86
146
  *
87
147
  * **This is the only supported initialization pattern** for `lora-node`.
88
148
  * Synchronous construction is not available — the async factory guarantees
89
- * the native layer is ready before the first query dispatches and keeps
90
- * the Node and WASM surfaces symmetric.
149
+ * the native layer is ready before the first query dispatches.
91
150
  *
92
151
  * ```ts
93
152
  * import { createDatabase } from "lora-node";
94
153
  *
95
- * const db = await createDatabase();
154
+ * const db = await createDatabase(); // in-memory by default
96
155
  * const res = await db.execute(
97
156
  * "CREATE (n:Person {name: $name}) RETURN n",
98
157
  * { name: "Alice" },
99
158
  * );
100
159
  * ```
101
160
  *
161
+ * Optional Node-only persistence convenience:
162
+ *
163
+ * ```ts
164
+ * import { createDatabase } from "lora-node";
165
+ *
166
+ * const inMemory = await createDatabase(); // in-memory
167
+ * const persistent = await createDatabase("./app"); // persistent: pass a directory string
168
+ * ```
169
+ *
170
+ * If you want persistence, pass a directory string. The string is treated
171
+ * as a WAL directory path verbatim. Relative paths resolve from the
172
+ * current working directory.
173
+ *
102
174
  * Each call returns an independent graph — no shared state between instances.
103
175
  */
104
- async function createDatabase() {
105
- return new DatabaseImpl(new NativeDatabase());
176
+ async function createDatabase(walDir) {
177
+ try {
178
+ return new DatabaseImpl(walDir === undefined ? new NativeDatabase() : new NativeDatabase(walDir));
179
+ }
180
+ catch (err) {
181
+ throw (0, types_js_1.wrapError)(err);
182
+ }
106
183
  }
107
184
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;;;;;;AAsGH,wCAEC;AAjGD,yCAAuC;AAEvC,6DAA6D;AAC7D,wDAAwD;AACxD,4DAAiC;AAEjC,MAAM,cAAc,GAA0C,mBAAM,CAAC,QAAQ,CAAC;AAE9E,6CAA2B;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,YAAY;IACP,MAAM,CAAsC;IAErD,YAAY,KAA0C;QACpD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAEX,KAAa,EAAE,MAAmB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC;YAC7D,OAAO,GAAqB,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAA,oBAAS,EAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,iBAAiB;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;CACF;AAgBD;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,cAAc;IAClC,OAAO,IAAI,YAAY,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;AAChD,CAAC"}
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.2.0",
3
+ "version": "0.4.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.2.0",
93
- "@loradb/lora-node-linux-arm64-gnu": "0.2.0",
94
- "@loradb/lora-node-darwin-x64": "0.2.0",
95
- "@loradb/lora-node-darwin-arm64": "0.2.0",
96
- "@loradb/lora-node-win32-x64-msvc": "0.2.0"
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"
97
97
  }
98
98
  }
package/ts/native.d.ts CHANGED
@@ -11,8 +11,15 @@ export interface NativeQueryResult {
11
11
  rows: Array<Record<string, unknown>>;
12
12
  }
13
13
 
14
+ export interface NativeSnapshotMeta {
15
+ formatVersion: number;
16
+ nodeCount: number;
17
+ relationshipCount: number;
18
+ walLsn: number | null;
19
+ }
20
+
14
21
  export declare class Database {
15
- constructor();
22
+ constructor(walDir?: string | null);
16
23
  /** Non-blocking: runs on the libuv threadpool, returns a Promise. */
17
24
  execute(
18
25
  query: string,
@@ -21,4 +28,9 @@ export declare class Database {
21
28
  clear(): void;
22
29
  nodeCount(): number;
23
30
  relationshipCount(): number;
31
+ dispose(): void;
32
+ /** Atomic save. Synchronous under the store mutex. */
33
+ saveSnapshot(path: string): NativeSnapshotMeta;
34
+ /** Replace the current graph with the snapshot at `path`. */
35
+ loadSnapshot(path: string): NativeSnapshotMeta;
24
36
  }