mcard-js 2.1.35 → 2.1.36

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
@@ -2,14 +2,14 @@
2
2
 
3
3
  Full-featured TypeScript implementation of MCard content-addressable storage, supporting both browser and Node.js environments.
4
4
 
5
- [![Tests](https://img.shields.io/badge/tests-814%20passed%20(52%20files)-brightgreen)](./tests)
5
+ [![Tests](https://img.shields.io/badge/tests-864%20passed%20(54%20files)-brightgreen)](./tests)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)](https://www.typescriptlang.org/)
7
7
  [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green)](https://nodejs.org/)
8
8
 
9
9
  ## Features
10
10
 
11
11
  - **Content Addressing**: SHA-256 via Web Crypto API (browser) or Node.js crypto
12
- - **3 Interchangeable Storage Engines**: `IndexedDBEngine` (browser), `SqliteNodeEngine` (Node.js/better-sqlite3), `SqliteWasmEngine` (browser/sql.js) verified by 162 cross-engine interchangeability tests
12
+ - **5 Interchangeable Storage Engines**: `IndexedDBEngine` (browser), `SqliteNodeEngine` (Node.js/better-sqlite3), `SqliteWasmEngine` (browser/sql.js), `DuckDBNodeEngine` (Node.js/@duckdb/node-api), `DuckDBWasmEngine` (browser/@duckdb/duckdb-wasm)
13
13
  - **UTF-8 Handles**: International support (文檔, مستند, ドキュメント, документ)
14
14
  - **Monadic API**: Maybe, Either, IO monads for functional composition
15
15
  - **PTR Runtime**: Polynomial Type Runtime with polyglot execution (JS, Python, Rust, C, WASM, Lean)
@@ -99,6 +99,39 @@ const count = db.countSync();
99
99
  db.close();
100
100
  ```
101
101
 
102
+ ### DuckDB (Node.js — Alternative OLAP Engine)
103
+ ```typescript
104
+ import { DuckDBNodeEngine } from './storage/DuckDBNodeEngine';
105
+
106
+ // Async factory — in-memory or file-backed
107
+ const db = await DuckDBNodeEngine.create(':memory:');
108
+ // or: await DuckDBNodeEngine.create('./mcard.duckdb');
109
+
110
+ // Same StorageEngine interface as SQLite
111
+ const card = await MCard.create('Hello from DuckDB!');
112
+ await db.add(card);
113
+
114
+ const retrieved = await db.get(card.hash);
115
+ console.log(retrieved?.getContentAsText());
116
+
117
+ await db.close();
118
+ ```
119
+
120
+ ### DuckDB WASM (Browser — In-Browser OLAP)
121
+ ```typescript
122
+ import { DuckDBWasmEngine } from './storage/DuckDBWasmEngine';
123
+
124
+ // Runs DuckDB entirely in WebAssembly via Web Worker
125
+ const db = new DuckDBWasmEngine();
126
+ await db.init(); // Downloads WASM bundle from CDN
127
+
128
+ // Same StorageEngine interface
129
+ const card = await MCard.create('Hello from DuckDB WASM!');
130
+ await db.add(card);
131
+
132
+ await db.close();
133
+ ```
134
+
102
135
  ## Database Schema
103
136
 
104
137
  The SQLite backend uses schemas matching the Python implementation for full interoperability.
package/dist/index.d.cts CHANGED
@@ -1,11 +1,202 @@
1
- import { M as MCard } from './StorageAdapter-DdDUiIvH.cjs';
2
- export { P as Page, S as StorageEngine } from './StorageAdapter-DdDUiIvH.cjs';
1
+ import { S as StorageEngine, M as MCard, P as Page } from './StorageAdapter-DdDUiIvH.cjs';
3
2
  import { CardCollection, Either, IO, Maybe } from './index.browser.cjs';
4
3
  export { ALGORITHM_HIERARCHY, ContentHandle, ContentTypeInterpreter, EVENT_CONSTANTS, ErrorCodes, ExecutionResult, FaroSidecar, FaroSidecarConfig, GTime, HandleValidationError, HashValidator, IndexedDBEngine, JsonRpcRequest, JsonRpcResponse, LensProtocol, LivenessMetric, MCardStore, PolynomialTerm, PrimeHash, Reader, SafetyViolation, ServiceWorkerPTR, State, ValidationRegistry, VerificationStatus, Writer, computeHash, validateHandle, validationRegistry } from './index.browser.cjs';
5
4
  export { SqliteWasmEngine } from './storage/SqliteWasmEngine.cjs';
6
5
  export { SqliteNodeEngine } from './storage/SqliteNodeEngine.cjs';
7
6
  import '@grafana/faro-web-sdk';
8
7
 
8
+ /**
9
+ * DuckDBNodeEngine — DuckDB storage backend for Node.js
10
+ *
11
+ * Implements the same StorageEngine interface as SqliteNodeEngine,
12
+ * using @duckdb/node-api (the "Neo" async client).
13
+ *
14
+ * Schema is loaded from the canonical SQL files via MCardSchema singleton
15
+ * with DuckDB-specific dialect transforms — single source of truth.
16
+ *
17
+ * Canonical schema files:
18
+ * schema/mcard_schema.sql (REQUIRED — core tables)
19
+ * schema/mcard_vector_schema.sql (optional — vector/graph/FTS)
20
+ *
21
+ * Usage:
22
+ * const engine = await DuckDBNodeEngine.create(':memory:');
23
+ * // ... use same StorageEngine interface as SqliteNodeEngine ...
24
+ * await engine.close();
25
+ */
26
+
27
+ /**
28
+ * DuckDB storage engine for Node.js.
29
+ *
30
+ * Because DuckDB init is async, use the static factory:
31
+ * const engine = await DuckDBNodeEngine.create(':memory:');
32
+ */
33
+ declare class DuckDBNodeEngine implements StorageEngine {
34
+ private instance;
35
+ private conn;
36
+ private dbPath;
37
+ private constructor();
38
+ /**
39
+ * Create a new DuckDBNodeEngine (async factory).
40
+ *
41
+ * @param dbPath Path to DuckDB file, or ':memory:' for in-memory
42
+ */
43
+ static create(dbPath?: string): Promise<DuckDBNodeEngine>;
44
+ /**
45
+ * Initialize schema from canonical SQL files via MCardSchema singleton.
46
+ */
47
+ private setupDatabase;
48
+ /**
49
+ * Close the DuckDB connection.
50
+ */
51
+ close(): Promise<void>;
52
+ getDbPath(): string;
53
+ /**
54
+ * Read all row objects from a SQL query (convenience wrapper).
55
+ */
56
+ private query;
57
+ /**
58
+ * Execute a statement (write operation).
59
+ */
60
+ private exec;
61
+ /**
62
+ * Bind parameters to a prepared statement.
63
+ * DuckDB uses 1-based indexing for parameters.
64
+ */
65
+ private bindParams;
66
+ /**
67
+ * Convert a DuckDB row object to an MCard.
68
+ */
69
+ private static rowToCard;
70
+ add(card: MCard): Promise<string>;
71
+ get(hash: string): Promise<MCard | null>;
72
+ delete(hash: string): Promise<void>;
73
+ getPage(pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
74
+ count(): Promise<number>;
75
+ searchByHash(hashPrefix: string): Promise<MCard[]>;
76
+ search(queryStr: string, pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
77
+ getAll(): Promise<MCard[]>;
78
+ clear(): Promise<void>;
79
+ registerHandle(handle: string, hash: string): Promise<void>;
80
+ resolveHandle(handle: string): Promise<string | null>;
81
+ getByHandle(handle: string): Promise<MCard | null>;
82
+ updateHandle(handle: string, newHash: string): Promise<string>;
83
+ getHandleHistory(handle: string): Promise<{
84
+ previousHash: string;
85
+ changedAt: string;
86
+ }[]>;
87
+ pruneHandleHistory(handle: string, options?: {
88
+ olderThan?: string;
89
+ deleteAll?: boolean;
90
+ }): Promise<number>;
91
+ getAllHandles(): Promise<{
92
+ handle: string;
93
+ hash: string;
94
+ }[]>;
95
+ removeHandle(handle: string): Promise<void>;
96
+ renameHandle(oldHandle: string, newHandle: string): Promise<void>;
97
+ deleteHistoryEntry(handle: string, previousHash: string): Promise<void>;
98
+ }
99
+
100
+ /**
101
+ * DuckDBWasmEngine — DuckDB WASM storage backend for browsers.
102
+ *
103
+ * Implements the same StorageEngine interface as SqliteWasmEngine,
104
+ * using @duckdb/duckdb-wasm (AsyncDuckDB with Web Worker).
105
+ *
106
+ * This engine is BROWSER-ONLY. For Node.js, use DuckDBNodeEngine.
107
+ *
108
+ * Schema is loaded from the canonical SQL files via MCardSchema singleton
109
+ * with DuckDB-specific dialect transforms — single source of truth.
110
+ *
111
+ * Usage (browser):
112
+ * const engine = new DuckDBWasmEngine();
113
+ * await engine.init();
114
+ * // ... use same StorageEngine interface as SqliteWasmEngine ...
115
+ * await engine.close();
116
+ */
117
+
118
+ /**
119
+ * DuckDB WASM storage engine for browsers.
120
+ *
121
+ * Uses @duckdb/duckdb-wasm which runs DuckDB entirely in WebAssembly
122
+ * inside a Web Worker. Provides the full `StorageEngine` interface
123
+ * with the same DuckDB dialect transforms as `DuckDBNodeEngine`.
124
+ *
125
+ * Browser-only: For Node.js, use `DuckDBNodeEngine` with `@duckdb/node-api`.
126
+ */
127
+ declare class DuckDBWasmEngine implements StorageEngine {
128
+ private db;
129
+ private conn;
130
+ private worker;
131
+ /**
132
+ * Initialize the DuckDB WASM engine.
133
+ *
134
+ * Spins up a Web Worker with the DuckDB WASM bundle from jsDelivr CDN.
135
+ * Must be called before any operations.
136
+ *
137
+ * @param customBundles Optional custom bundle URLs (for self-hosted WASM)
138
+ */
139
+ init(customBundles?: {
140
+ mainModule: string;
141
+ mainWorker: string;
142
+ pthreadWorker?: string;
143
+ }): Promise<void>;
144
+ /**
145
+ * Initialize schema from canonical SQL files via MCardSchema singleton.
146
+ */
147
+ private setupDatabase;
148
+ private ensureConn;
149
+ /**
150
+ * Close the DuckDB WASM connection and terminate the worker.
151
+ */
152
+ close(): Promise<void>;
153
+ /**
154
+ * Run a query and return row objects.
155
+ * duckdb-wasm conn.query() returns an Arrow Table.
156
+ */
157
+ private query;
158
+ /**
159
+ * Execute a write statement.
160
+ */
161
+ private exec;
162
+ /**
163
+ * Convert Arrow Table to array of plain objects.
164
+ */
165
+ private arrowToObjects;
166
+ /**
167
+ * Convert a row object to an MCard.
168
+ */
169
+ private static rowToCard;
170
+ add(card: MCard): Promise<string>;
171
+ get(hash: string): Promise<MCard | null>;
172
+ delete(hash: string): Promise<void>;
173
+ getPage(pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
174
+ count(): Promise<number>;
175
+ searchByHash(hashPrefix: string): Promise<MCard[]>;
176
+ search(queryStr: string, pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
177
+ getAll(): Promise<MCard[]>;
178
+ clear(): Promise<void>;
179
+ registerHandle(handle: string, hash: string): Promise<void>;
180
+ resolveHandle(handle: string): Promise<string | null>;
181
+ getByHandle(handle: string): Promise<MCard | null>;
182
+ updateHandle(handle: string, newHash: string): Promise<string>;
183
+ getHandleHistory(handle: string): Promise<{
184
+ previousHash: string;
185
+ changedAt: string;
186
+ }[]>;
187
+ pruneHandleHistory(handle: string, options?: {
188
+ olderThan?: string;
189
+ deleteAll?: boolean;
190
+ }): Promise<number>;
191
+ getAllHandles(): Promise<{
192
+ handle: string;
193
+ hash: string;
194
+ }[]>;
195
+ removeHandle(handle: string): Promise<void>;
196
+ renameHandle(oldHandle: string, newHandle: string): Promise<void>;
197
+ deleteHistoryEntry(handle: string, previousHash: string): Promise<void>;
198
+ }
199
+
9
200
  /**
10
201
  * SandboxWorker - Execute code in isolated Web Worker
11
202
  *
@@ -1057,4 +1248,4 @@ declare class CLMRunner {
1057
1248
  private buildRunCLM;
1058
1249
  }
1059
1250
 
1060
- export { CLMRunner, CardCollection, Either, FileIO, IO, LLMConfig, LLMRuntime, index as Lambda, LambdaRuntime, Loader, MCard, Maybe, SandboxWorker, chatMonad, promptMonad };
1251
+ export { CLMRunner, CardCollection, DuckDBNodeEngine, DuckDBWasmEngine, Either, FileIO, IO, LLMConfig, LLMRuntime, index as Lambda, LambdaRuntime, Loader, MCard, Maybe, Page, SandboxWorker, StorageEngine, chatMonad, promptMonad };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,202 @@
1
- import { M as MCard } from './StorageAdapter-DdDUiIvH.js';
2
- export { P as Page, S as StorageEngine } from './StorageAdapter-DdDUiIvH.js';
1
+ import { S as StorageEngine, M as MCard, P as Page } from './StorageAdapter-DdDUiIvH.js';
3
2
  import { CardCollection, Either, IO, Maybe } from './index.browser.js';
4
3
  export { ALGORITHM_HIERARCHY, ContentHandle, ContentTypeInterpreter, EVENT_CONSTANTS, ErrorCodes, ExecutionResult, FaroSidecar, FaroSidecarConfig, GTime, HandleValidationError, HashValidator, IndexedDBEngine, JsonRpcRequest, JsonRpcResponse, LensProtocol, LivenessMetric, MCardStore, PolynomialTerm, PrimeHash, Reader, SafetyViolation, ServiceWorkerPTR, State, ValidationRegistry, VerificationStatus, Writer, computeHash, validateHandle, validationRegistry } from './index.browser.js';
5
4
  export { SqliteWasmEngine } from './storage/SqliteWasmEngine.js';
6
5
  export { SqliteNodeEngine } from './storage/SqliteNodeEngine.js';
7
6
  import '@grafana/faro-web-sdk';
8
7
 
8
+ /**
9
+ * DuckDBNodeEngine — DuckDB storage backend for Node.js
10
+ *
11
+ * Implements the same StorageEngine interface as SqliteNodeEngine,
12
+ * using @duckdb/node-api (the "Neo" async client).
13
+ *
14
+ * Schema is loaded from the canonical SQL files via MCardSchema singleton
15
+ * with DuckDB-specific dialect transforms — single source of truth.
16
+ *
17
+ * Canonical schema files:
18
+ * schema/mcard_schema.sql (REQUIRED — core tables)
19
+ * schema/mcard_vector_schema.sql (optional — vector/graph/FTS)
20
+ *
21
+ * Usage:
22
+ * const engine = await DuckDBNodeEngine.create(':memory:');
23
+ * // ... use same StorageEngine interface as SqliteNodeEngine ...
24
+ * await engine.close();
25
+ */
26
+
27
+ /**
28
+ * DuckDB storage engine for Node.js.
29
+ *
30
+ * Because DuckDB init is async, use the static factory:
31
+ * const engine = await DuckDBNodeEngine.create(':memory:');
32
+ */
33
+ declare class DuckDBNodeEngine implements StorageEngine {
34
+ private instance;
35
+ private conn;
36
+ private dbPath;
37
+ private constructor();
38
+ /**
39
+ * Create a new DuckDBNodeEngine (async factory).
40
+ *
41
+ * @param dbPath Path to DuckDB file, or ':memory:' for in-memory
42
+ */
43
+ static create(dbPath?: string): Promise<DuckDBNodeEngine>;
44
+ /**
45
+ * Initialize schema from canonical SQL files via MCardSchema singleton.
46
+ */
47
+ private setupDatabase;
48
+ /**
49
+ * Close the DuckDB connection.
50
+ */
51
+ close(): Promise<void>;
52
+ getDbPath(): string;
53
+ /**
54
+ * Read all row objects from a SQL query (convenience wrapper).
55
+ */
56
+ private query;
57
+ /**
58
+ * Execute a statement (write operation).
59
+ */
60
+ private exec;
61
+ /**
62
+ * Bind parameters to a prepared statement.
63
+ * DuckDB uses 1-based indexing for parameters.
64
+ */
65
+ private bindParams;
66
+ /**
67
+ * Convert a DuckDB row object to an MCard.
68
+ */
69
+ private static rowToCard;
70
+ add(card: MCard): Promise<string>;
71
+ get(hash: string): Promise<MCard | null>;
72
+ delete(hash: string): Promise<void>;
73
+ getPage(pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
74
+ count(): Promise<number>;
75
+ searchByHash(hashPrefix: string): Promise<MCard[]>;
76
+ search(queryStr: string, pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
77
+ getAll(): Promise<MCard[]>;
78
+ clear(): Promise<void>;
79
+ registerHandle(handle: string, hash: string): Promise<void>;
80
+ resolveHandle(handle: string): Promise<string | null>;
81
+ getByHandle(handle: string): Promise<MCard | null>;
82
+ updateHandle(handle: string, newHash: string): Promise<string>;
83
+ getHandleHistory(handle: string): Promise<{
84
+ previousHash: string;
85
+ changedAt: string;
86
+ }[]>;
87
+ pruneHandleHistory(handle: string, options?: {
88
+ olderThan?: string;
89
+ deleteAll?: boolean;
90
+ }): Promise<number>;
91
+ getAllHandles(): Promise<{
92
+ handle: string;
93
+ hash: string;
94
+ }[]>;
95
+ removeHandle(handle: string): Promise<void>;
96
+ renameHandle(oldHandle: string, newHandle: string): Promise<void>;
97
+ deleteHistoryEntry(handle: string, previousHash: string): Promise<void>;
98
+ }
99
+
100
+ /**
101
+ * DuckDBWasmEngine — DuckDB WASM storage backend for browsers.
102
+ *
103
+ * Implements the same StorageEngine interface as SqliteWasmEngine,
104
+ * using @duckdb/duckdb-wasm (AsyncDuckDB with Web Worker).
105
+ *
106
+ * This engine is BROWSER-ONLY. For Node.js, use DuckDBNodeEngine.
107
+ *
108
+ * Schema is loaded from the canonical SQL files via MCardSchema singleton
109
+ * with DuckDB-specific dialect transforms — single source of truth.
110
+ *
111
+ * Usage (browser):
112
+ * const engine = new DuckDBWasmEngine();
113
+ * await engine.init();
114
+ * // ... use same StorageEngine interface as SqliteWasmEngine ...
115
+ * await engine.close();
116
+ */
117
+
118
+ /**
119
+ * DuckDB WASM storage engine for browsers.
120
+ *
121
+ * Uses @duckdb/duckdb-wasm which runs DuckDB entirely in WebAssembly
122
+ * inside a Web Worker. Provides the full `StorageEngine` interface
123
+ * with the same DuckDB dialect transforms as `DuckDBNodeEngine`.
124
+ *
125
+ * Browser-only: For Node.js, use `DuckDBNodeEngine` with `@duckdb/node-api`.
126
+ */
127
+ declare class DuckDBWasmEngine implements StorageEngine {
128
+ private db;
129
+ private conn;
130
+ private worker;
131
+ /**
132
+ * Initialize the DuckDB WASM engine.
133
+ *
134
+ * Spins up a Web Worker with the DuckDB WASM bundle from jsDelivr CDN.
135
+ * Must be called before any operations.
136
+ *
137
+ * @param customBundles Optional custom bundle URLs (for self-hosted WASM)
138
+ */
139
+ init(customBundles?: {
140
+ mainModule: string;
141
+ mainWorker: string;
142
+ pthreadWorker?: string;
143
+ }): Promise<void>;
144
+ /**
145
+ * Initialize schema from canonical SQL files via MCardSchema singleton.
146
+ */
147
+ private setupDatabase;
148
+ private ensureConn;
149
+ /**
150
+ * Close the DuckDB WASM connection and terminate the worker.
151
+ */
152
+ close(): Promise<void>;
153
+ /**
154
+ * Run a query and return row objects.
155
+ * duckdb-wasm conn.query() returns an Arrow Table.
156
+ */
157
+ private query;
158
+ /**
159
+ * Execute a write statement.
160
+ */
161
+ private exec;
162
+ /**
163
+ * Convert Arrow Table to array of plain objects.
164
+ */
165
+ private arrowToObjects;
166
+ /**
167
+ * Convert a row object to an MCard.
168
+ */
169
+ private static rowToCard;
170
+ add(card: MCard): Promise<string>;
171
+ get(hash: string): Promise<MCard | null>;
172
+ delete(hash: string): Promise<void>;
173
+ getPage(pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
174
+ count(): Promise<number>;
175
+ searchByHash(hashPrefix: string): Promise<MCard[]>;
176
+ search(queryStr: string, pageNumber?: number, pageSize?: number): Promise<Page<MCard>>;
177
+ getAll(): Promise<MCard[]>;
178
+ clear(): Promise<void>;
179
+ registerHandle(handle: string, hash: string): Promise<void>;
180
+ resolveHandle(handle: string): Promise<string | null>;
181
+ getByHandle(handle: string): Promise<MCard | null>;
182
+ updateHandle(handle: string, newHash: string): Promise<string>;
183
+ getHandleHistory(handle: string): Promise<{
184
+ previousHash: string;
185
+ changedAt: string;
186
+ }[]>;
187
+ pruneHandleHistory(handle: string, options?: {
188
+ olderThan?: string;
189
+ deleteAll?: boolean;
190
+ }): Promise<number>;
191
+ getAllHandles(): Promise<{
192
+ handle: string;
193
+ hash: string;
194
+ }[]>;
195
+ removeHandle(handle: string): Promise<void>;
196
+ renameHandle(oldHandle: string, newHandle: string): Promise<void>;
197
+ deleteHistoryEntry(handle: string, previousHash: string): Promise<void>;
198
+ }
199
+
9
200
  /**
10
201
  * SandboxWorker - Execute code in isolated Web Worker
11
202
  *
@@ -1057,4 +1248,4 @@ declare class CLMRunner {
1057
1248
  private buildRunCLM;
1058
1249
  }
1059
1250
 
1060
- export { CLMRunner, CardCollection, Either, FileIO, IO, LLMConfig, LLMRuntime, index as Lambda, LambdaRuntime, Loader, MCard, Maybe, SandboxWorker, chatMonad, promptMonad };
1251
+ export { CLMRunner, CardCollection, DuckDBNodeEngine, DuckDBWasmEngine, Either, FileIO, IO, LLMConfig, LLMRuntime, index as Lambda, LambdaRuntime, Loader, MCard, Maybe, Page, SandboxWorker, StorageEngine, chatMonad, promptMonad };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcard-js",
3
- "version": "2.1.35",
3
+ "version": "2.1.36",
4
4
  "description": "MCard - Content-addressable storage with cryptographic hashing, handle resolution, and vector search for Node.js and browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -58,6 +58,8 @@
58
58
  "yaml": "^2.8.2"
59
59
  },
60
60
  "optionalDependencies": {
61
+ "@duckdb/duckdb-wasm": "^1.33.1-dev20.0",
62
+ "@duckdb/node-api": "^1.5.0-r.1",
61
63
  "better-sqlite3": "^11.6.0",
62
64
  "sqlite-vec": "^0.1.7-alpha.2"
63
65
  },