@laminardb/node 0.30.0-alpha.1

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/dist/index.js ADDED
@@ -0,0 +1,420 @@
1
+ "use strict";
2
+ /**
3
+ * Public API of `@laminardb/node` (plan 00 D8).
4
+ *
5
+ * This module is the documented surface; the generated napi binding
6
+ * (`index.js` at the package root) is an internal seam. Everything here
7
+ * wraps the native calls so failures surface as the typed
8
+ * {@link LaminarError} hierarchy.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.LaminarDB = void 0;
12
+ exports.QueryStream = void 0;
13
+ exports.PushSubscription = void 0;
14
+ exports.Subscription = void 0;
15
+ exports.Connection = void 0;
16
+ exports.Writer = void 0;
17
+ exports.tableFrom = void 0;
18
+ exports.toLaminarError = void 0;
19
+ exports.LaminarInternalError = void 0;
20
+ exports.LaminarSubscriptionError = void 0;
21
+ exports.LaminarQueryError = void 0;
22
+ exports.LaminarIngestionError = void 0;
23
+ exports.LaminarSchemaError = void 0;
24
+ exports.LaminarConnectionError = void 0;
25
+ exports.LaminarError = void 0;
26
+ const errors_js_1 = require("./errors.js");
27
+ var errors_js_2 = require("./errors.js");
28
+ Object.defineProperty(exports, "LaminarError", { enumerable: true, get: function () { return errors_js_2.LaminarError; } });
29
+ Object.defineProperty(exports, "LaminarConnectionError", { enumerable: true, get: function () { return errors_js_2.LaminarConnectionError; } });
30
+ Object.defineProperty(exports, "LaminarSchemaError", { enumerable: true, get: function () { return errors_js_2.LaminarSchemaError; } });
31
+ Object.defineProperty(exports, "LaminarIngestionError", { enumerable: true, get: function () { return errors_js_2.LaminarIngestionError; } });
32
+ Object.defineProperty(exports, "LaminarQueryError", { enumerable: true, get: function () { return errors_js_2.LaminarQueryError; } });
33
+ Object.defineProperty(exports, "LaminarSubscriptionError", { enumerable: true, get: function () { return errors_js_2.LaminarSubscriptionError; } });
34
+ Object.defineProperty(exports, "LaminarInternalError", { enumerable: true, get: function () { return errors_js_2.LaminarInternalError; } });
35
+ Object.defineProperty(exports, "toLaminarError", { enumerable: true, get: function () { return errors_js_2.toLaminarError; } });
36
+ var arrow_js_1 = require("./arrow.js");
37
+ Object.defineProperty(exports, "tableFrom", { enumerable: true, get: function () { return arrow_js_1.tableFrom; } });
38
+ const native = require('../index.js') ?? undefined;
39
+ /** Streaming writer for one source; single-owner. */
40
+ class Writer {
41
+ #native;
42
+ /** @internal */
43
+ constructor(native) {
44
+ this.#native = native;
45
+ }
46
+ name() {
47
+ return this.#native.name();
48
+ }
49
+ schema() {
50
+ return (0, errors_js_1.wrapSync)(() => this.#native.schema());
51
+ }
52
+ /** Push one batch built from row objects; returns rows written. `Date`
53
+ * values are converted to epoch milliseconds automatically. */
54
+ writeRows(rows) {
55
+ return (0, errors_js_1.wrapSync)(() => this.#native.writeRows(normalizeRows(rows)));
56
+ }
57
+ /** Push every batch from an Arrow IPC stream `Buffer`. */
58
+ writeArrow(bytes) {
59
+ return (0, errors_js_1.wrapSync)(() => this.#native.writeArrow(bytes));
60
+ }
61
+ /** Advance the event-time watermark (milliseconds since epoch). */
62
+ watermark(timestamp) {
63
+ this.#native.watermark(timestamp);
64
+ }
65
+ currentWatermark() {
66
+ return this.#native.currentWatermark();
67
+ }
68
+ /** Rows buffered in the source, not yet consumed by the pipeline. */
69
+ pending() {
70
+ return this.#native.pending();
71
+ }
72
+ capacity() {
73
+ return this.#native.capacity();
74
+ }
75
+ /** True when the source buffer is more than 80% full — slow down. */
76
+ isBackpressured() {
77
+ return this.#native.isBackpressured();
78
+ }
79
+ /** Idempotent; writes after close throw `LaminarIngestionError` (301). */
80
+ close() {
81
+ this.#native.close();
82
+ }
83
+ }
84
+ exports.Writer = Writer;
85
+ /** Convert `Date` instances to epoch milliseconds (the native seam's
86
+ * temporal convention) inside row objects; other values pass through. */
87
+ function normalizeRows(rows) {
88
+ let changed = false;
89
+ const normalized = rows.map((row) => {
90
+ let rowChanged = false;
91
+ const copy = {};
92
+ for (const [key, value] of Object.entries(row)) {
93
+ if (value instanceof Date) {
94
+ copy[key] = value.getTime();
95
+ rowChanged = true;
96
+ }
97
+ else {
98
+ copy[key] = value;
99
+ }
100
+ }
101
+ if (rowChanged)
102
+ changed = true;
103
+ return rowChanged ? copy : row;
104
+ });
105
+ return changed ? normalized : rows;
106
+ }
107
+ /**
108
+ * An open LaminarDB connection. Safe to share across async contexts;
109
+ * `close()` is idempotent, and use after close throws
110
+ * `LaminarConnectionError` (101) rather than crashing.
111
+ *
112
+ * DDL that changes topology (`CREATE SOURCE`/`STREAM`/`SINK`) must run
113
+ * before `start()`; the engine rejects topology changes on a running
114
+ * pipeline.
115
+ */
116
+ class Connection {
117
+ #native;
118
+ /** @internal */
119
+ constructor(native) {
120
+ this.#native = native;
121
+ }
122
+ /**
123
+ * Execute one SQL statement. `SELECT` returns `kind: 'query'` with the
124
+ * fully collected `result`; SHOW/DESCRIBE return `kind: 'metadata'`.
125
+ */
126
+ execute(sql) {
127
+ return (0, errors_js_1.wrapAsync)(() => this.#native.execute(sql)).then(mapOutcome);
128
+ }
129
+ /** Execute a query and return its collected result; non-query SQL throws
130
+ * `LaminarQueryError` (400). */
131
+ query(sql) {
132
+ return (0, errors_js_1.wrapAsync)(() => this.#native.query(sql)).then(wrapResult);
133
+ }
134
+ /** Ingest row objects into a source; returns rows pushed. `Date` values
135
+ * are converted to epoch milliseconds automatically. */
136
+ insert(source, rows) {
137
+ return (0, errors_js_1.wrapSync)(() => this.#native.insert(source, normalizeRows(rows)));
138
+ }
139
+ /** Ingest an Arrow IPC stream `Buffer` into a source; returns rows pushed. */
140
+ insertArrow(source, bytes) {
141
+ return (0, errors_js_1.wrapSync)(() => this.#native.insertArrow(source, bytes));
142
+ }
143
+ /** Open a streaming writer for a source (throws 200 if unknown). */
144
+ writer(source) {
145
+ return (0, errors_js_1.wrapSync)(() => new Writer(this.#native.writer(source)));
146
+ }
147
+ /** Start the streaming pipeline (idempotent). */
148
+ start() {
149
+ return (0, errors_js_1.wrapAsync)(() => this.#native.start());
150
+ }
151
+ /**
152
+ * Trigger a manual checkpoint. Requires checkpointing in the open config
153
+ * and at least one stream or sink in the topology (the core wires the
154
+ * coordinator only for real pipelines).
155
+ */
156
+ checkpoint() {
157
+ return (0, errors_js_1.wrapAsync)(() => this.#native.checkpoint());
158
+ }
159
+ isCheckpointEnabled() {
160
+ return this.#native.isCheckpointEnabled();
161
+ }
162
+ listSources() {
163
+ return (0, errors_js_1.wrapAsync)(() => this.#native.listSources());
164
+ }
165
+ listStreams() {
166
+ return (0, errors_js_1.wrapAsync)(() => this.#native.listStreams());
167
+ }
168
+ listSinks() {
169
+ return (0, errors_js_1.wrapAsync)(() => this.#native.listSinks());
170
+ }
171
+ sourceInfos() {
172
+ return (0, errors_js_1.wrapAsync)(() => this.#native.sourceInfos());
173
+ }
174
+ /** Schema of a source; unknown names throw `LaminarSchemaError` (200). */
175
+ schema(name) {
176
+ return (0, errors_js_1.wrapAsync)(() => this.#native.schema(name));
177
+ }
178
+ /** Subscribe to a stream or materialized view (pull style). The returned
179
+ * subscription is async-iterable; terminal failures throw
180
+ * `LaminarSubscriptionError` (502 lag / 500 otherwise) and end iteration. */
181
+ subscribe(name, options) {
182
+ return (0, errors_js_1.wrapAsync)(() => this.#native.subscribe(name, options?.filter ?? null, options?.fromEpoch ?? null)).then((subscription) => new Subscription(subscription));
183
+ }
184
+ /** Subscribe push style: `onData` per frame (awaited per delivery —
185
+ * backpressure, not queueing). Errors and open failures surface via
186
+ * `onError`, always followed by `onClose`. */
187
+ subscribeWith(name, handlers, options) {
188
+ // WHY the wrapper: native delivery awaits the returned promise, so sync
189
+ // handlers must still produce one; this is the settlement-aware
190
+ // backpressure contract (plan 03).
191
+ const userHandler = handlers.onData;
192
+ const promiseReturning = (frame) => {
193
+ const settled = userHandler(frame);
194
+ return settled instanceof Promise ? settled : Promise.resolve();
195
+ };
196
+ const native = (0, errors_js_1.wrapSync)(() => this.#native.subscribeWith(name, options?.filter ?? null, options?.fromEpoch ?? null, promiseReturning, handlers.onError ?? (() => { }), handlers.onClose ?? (() => { })));
197
+ return new PushSubscription(native);
198
+ }
199
+ /** Execute a query and stream its batches on demand; non-query SQL throws
200
+ * `LaminarQueryError` (400). The stream is async-iterable. */
201
+ streamQuery(sql) {
202
+ return (0, errors_js_1.wrapAsync)(() => this.#native.streamQuery(sql)).then((stream) => new QueryStream(stream));
203
+ }
204
+ /** Cancel a query by the id reported by `streamQuery().queryId`. */
205
+ cancelQuery(queryId) {
206
+ return (0, errors_js_1.wrapAsync)(() => this.#native.cancelQuery(queryId));
207
+ }
208
+ /** Aggregate pipeline counters. */
209
+ metrics() {
210
+ return (0, errors_js_1.wrapAsync)(() => this.#native.metrics());
211
+ }
212
+ /** Counters for one source; unknown names throw (200). */
213
+ sourceMetrics(name) {
214
+ return (0, errors_js_1.wrapAsync)(() => this.#native.sourceMetrics(name));
215
+ }
216
+ /** Counters for every source. */
217
+ allSourceMetrics() {
218
+ return (0, errors_js_1.wrapAsync)(() => this.#native.allSourceMetrics());
219
+ }
220
+ /** Counters for one stream; unknown names throw (200). */
221
+ streamMetrics(name) {
222
+ return (0, errors_js_1.wrapAsync)(() => this.#native.streamMetrics(name));
223
+ }
224
+ /** Counters for every stream. */
225
+ allStreamMetrics() {
226
+ return (0, errors_js_1.wrapAsync)(() => this.#native.allStreamMetrics());
227
+ }
228
+ /** Engine lifecycle state name (e.g. `Running`). */
229
+ pipelineState() {
230
+ return (0, errors_js_1.wrapAsync)(() => this.#native.pipelineState());
231
+ }
232
+ /** Minimum event-time watermark across sources (epoch milliseconds). */
233
+ pipelineWatermark() {
234
+ return (0, errors_js_1.wrapAsync)(() => this.#native.pipelineWatermark());
235
+ }
236
+ /** Total events the pipeline has processed. */
237
+ totalEventsProcessed() {
238
+ return (0, errors_js_1.wrapAsync)(() => this.#native.totalEventsProcessed());
239
+ }
240
+ isClosed() {
241
+ return this.#native.isClosed();
242
+ }
243
+ /** Graceful shutdown; idempotent and safe under concurrent calls. */
244
+ close() {
245
+ return (0, errors_js_1.wrapAsync)(() => this.#native.close());
246
+ }
247
+ }
248
+ exports.Connection = Connection;
249
+ /** A pull-based framed subscription; async-iterable:
250
+ * `for await (const frame of conn.subscribe('rollup'))`. */
251
+ class Subscription {
252
+ #native;
253
+ /** @internal */
254
+ constructor(native) {
255
+ this.#native = native;
256
+ }
257
+ schema() {
258
+ return (0, errors_js_1.wrapSync)(() => this.#native.schema());
259
+ }
260
+ /** Next frame, or `null` at end-of-stream / after `cancel()`. */
261
+ nextFrame() {
262
+ return (0, errors_js_1.wrapAsync)(() => this.#native.nextFrame());
263
+ }
264
+ isActive() {
265
+ return this.#native.isActive();
266
+ }
267
+ /** Idempotent; a pending `nextFrame` resolves `null`. */
268
+ cancel() {
269
+ this.#native.cancel();
270
+ }
271
+ [Symbol.asyncIterator]() {
272
+ return {
273
+ next: async () => {
274
+ const frame = await this.nextFrame();
275
+ return frame === null
276
+ ? { value: undefined, done: true }
277
+ : { value: frame, done: false };
278
+ },
279
+ return: async () => {
280
+ this.cancel();
281
+ return { value: undefined, done: true };
282
+ },
283
+ };
284
+ }
285
+ }
286
+ exports.Subscription = Subscription;
287
+ /** A push-based subscription handle; `close()` stops delivery and resolves
288
+ * after the reader has stopped (no callbacks fire afterwards). */
289
+ class PushSubscription {
290
+ #native;
291
+ /** @internal */
292
+ constructor(native) {
293
+ this.#native = native;
294
+ }
295
+ isActive() {
296
+ return this.#native.isActive();
297
+ }
298
+ /** Stop delivery and wait for the reader. Idempotent. */
299
+ close() {
300
+ return (0, errors_js_1.wrapAsync)(() => this.#native.close());
301
+ }
302
+ }
303
+ exports.PushSubscription = PushSubscription;
304
+ /** A streaming query result; async-iterable over `ArrowBatch`es:
305
+ * `for await (const batch of conn.streamQuery(sql))`. */
306
+ class QueryStream {
307
+ #native;
308
+ /** @internal */
309
+ constructor(native) {
310
+ this.#native = native;
311
+ }
312
+ schema() {
313
+ return (0, errors_js_1.wrapSync)(() => this.#native.schema());
314
+ }
315
+ /** Query id, usable with `Connection.cancelQuery`. */
316
+ queryId() {
317
+ return this.#native.queryId();
318
+ }
319
+ /** Next batch, or `null` at end-of-stream / after `cancel()`. */
320
+ nextBatch() {
321
+ return (0, errors_js_1.wrapAsync)(() => this.#native.nextBatch());
322
+ }
323
+ /** Idempotent; a pending `nextBatch` resolves `null`. */
324
+ cancel() {
325
+ this.#native.cancel();
326
+ }
327
+ [Symbol.asyncIterator]() {
328
+ return {
329
+ next: async () => {
330
+ const batch = await this.nextBatch();
331
+ return batch === null
332
+ ? { value: undefined, done: true }
333
+ : { value: batch, done: false };
334
+ },
335
+ return: async () => {
336
+ this.cancel();
337
+ return { value: undefined, done: true };
338
+ },
339
+ };
340
+ }
341
+ }
342
+ exports.QueryStream = QueryStream;
343
+ /** Entry point. */
344
+ class LaminarDB {
345
+ constructor() {
346
+ throw new Error('LaminarDB is a static entry point; use LaminarDB.open()');
347
+ }
348
+ /**
349
+ * Open an embedded database. `open()` and `open(':memory:')` are
350
+ * in-memory; `open(path)` sets the storage directory (local-durable
351
+ * embedded mode when `checkpoint` is configured); `config.storageDir`
352
+ * wins over the positional path.
353
+ */
354
+ static open(path, config) {
355
+ return (0, errors_js_1.wrapAsync)(() => native.open(path, config)).then((connection) => new Connection(connection));
356
+ }
357
+ /** Binding and pinned-core version, e.g. `0.30.0-alpha.1 (core v0.30.0)`. */
358
+ static version() {
359
+ return native.version();
360
+ }
361
+ }
362
+ exports.LaminarDB = LaminarDB;
363
+ class QueryResultImpl {
364
+ #native;
365
+ constructor(native) {
366
+ this.#native = native;
367
+ }
368
+ schema() {
369
+ return (0, errors_js_1.wrapSync)(() => this.#native.schema());
370
+ }
371
+ numRows() {
372
+ return this.#native.numRows();
373
+ }
374
+ numBatches() {
375
+ return this.#native.numBatches();
376
+ }
377
+ batch(index) {
378
+ return (0, errors_js_1.wrapSync)(() => new ArrowBatchImpl(this.#native.batch(index)));
379
+ }
380
+ toIPC() {
381
+ return (0, errors_js_1.wrapSync)(() => this.#native.toIPC());
382
+ }
383
+ toArray() {
384
+ return (0, errors_js_1.wrapSync)(() => this.#native.toArray());
385
+ }
386
+ }
387
+ class ArrowBatchImpl {
388
+ #native;
389
+ constructor(native) {
390
+ this.#native = native;
391
+ }
392
+ numRows() {
393
+ return this.#native.numRows();
394
+ }
395
+ numColumns() {
396
+ return this.#native.numColumns();
397
+ }
398
+ schema() {
399
+ return (0, errors_js_1.wrapSync)(() => this.#native.schema());
400
+ }
401
+ toIPC() {
402
+ return (0, errors_js_1.wrapSync)(() => this.#native.toIPC());
403
+ }
404
+ toArray() {
405
+ return (0, errors_js_1.wrapSync)(() => this.#native.toArray());
406
+ }
407
+ }
408
+ function wrapResult(native) {
409
+ return new QueryResultImpl(native);
410
+ }
411
+ function mapOutcome(native) {
412
+ return {
413
+ kind: native.kind,
414
+ statementType: native.statementType,
415
+ objectName: native.objectName,
416
+ rowsAffected: native.rowsAffected,
417
+ queryId: native.queryId,
418
+ result: native.result === undefined ? undefined : wrapResult(native.result),
419
+ };
420
+ }