@laminardb/node 0.30.0-alpha.1 → 0.30.0-alpha.3
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 +76 -66
- package/index.mjs +24 -0
- package/package.json +20 -10
package/README.md
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
# laminardb
|
|
1
|
+
# @laminardb/node
|
|
2
2
|
|
|
3
|
-
Embedded streaming SQL for Node.js and TypeScript
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
shape as [`laminardb-java`](https://github.com/laminardb/laminardb-java) and
|
|
7
|
-
`laminardb-python`, adapted to Node idioms: every data-plane call is a `Promise`, Arrow
|
|
8
|
-
data moves as IPC `Buffer`s, and failures throw a typed error hierarchy.
|
|
3
|
+
Embedded streaming SQL for Node.js and TypeScript, with no compilation step: install,
|
|
4
|
+
import, and query. Prebuilt native binaries ship for every major platform — nothing to
|
|
5
|
+
build, no postinstall scripts, no node-gyp.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```sh
|
|
8
|
+
npm install @laminardb/node
|
|
9
|
+
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
**Requirements:** Node.js 20 or later, on macOS (x64, arm64), Linux (x64 or arm64, glibc
|
|
12
|
+
or musl), or Windows (x64). TypeScript types are included — no `@types` package needed.
|
|
13
|
+
(npm 11+ recommended; pnpm and yarn work as-is.)
|
|
14
|
+
|
|
15
|
+
## Your first pipeline
|
|
14
16
|
|
|
15
17
|
```js
|
|
16
18
|
import { LaminarDB } from '@laminardb/node'
|
|
@@ -27,37 +29,41 @@ await conn.insert('sensors', [
|
|
|
27
29
|
const result = await conn.query(
|
|
28
30
|
'SELECT device, avg(value) AS avg_value FROM sensors GROUP BY device',
|
|
29
31
|
)
|
|
30
|
-
console.log(result.toArray())
|
|
31
|
-
|
|
32
|
-
await conn.close()
|
|
32
|
+
console.log(result.toArray())
|
|
33
|
+
// [{ device: 'd1', avg_value: 21.5 }, { device: 'd2', avg_value: 18.25 }]
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
That's the whole loop: define a source, start the pipeline, insert rows, query. `CommonJS`
|
|
37
|
+
works too — `const { LaminarDB } = require('@laminardb/node')`.
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
**Durable mode** is one argument:
|
|
40
|
+
`LaminarDB.open('./data', { checkpoint: { intervalMs: 5000 } })` keeps your pipeline and
|
|
41
|
+
data across restarts.
|
|
42
|
+
|
|
43
|
+
> Two rules from the engine: `CREATE SOURCE` / `CREATE STREAM` / `CREATE SINK` must run
|
|
44
|
+
> **before** `start()`, and manual `checkpoint()` needs at least one stream or sink in the
|
|
45
|
+
> topology.
|
|
46
|
+
|
|
47
|
+
## Reading results
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
- `result.toArray()` — plain row objects, zero dependencies. `Date`-like columns are epoch
|
|
50
|
+
milliseconds; 64-bit integers are JS `BigInt`.
|
|
51
|
+
- `result.toIPC()` — an [Apache Arrow](https://www.npmjs.com/package/apache-arrow) IPC
|
|
52
|
+
`Buffer`, for when rows get big: `tableFromIPC(result.toIPC())` (or the bundled
|
|
53
|
+
`tableFrom(result)`).
|
|
54
|
+
- Batch at a time: `result.numBatches()`, `result.batch(i)`.
|
|
44
55
|
|
|
45
|
-
##
|
|
56
|
+
## Writing data
|
|
46
57
|
|
|
47
|
-
- `
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- `
|
|
51
|
-
|
|
52
|
-
dependency): `tableFromIPC(result.toIPC())` or the bundled `tableFrom(result)` helper.
|
|
53
|
-
- `conn.insertArrow(source, buffer)` / `writer.writeArrow(buffer)` — bulk ingestion
|
|
54
|
-
straight from Arrow IPC data.
|
|
55
|
-
- `conn.writer(source)` — streaming writer with `writeRows`, `watermark`, and backpressure
|
|
56
|
-
visibility (`pending` / `capacity` / `isBackpressured`).
|
|
58
|
+
- `conn.insert('sensors', rows)` — row objects, validated per value with a clear error
|
|
59
|
+
naming the column.
|
|
60
|
+
- `conn.insertArrow('sensors', ipcBuffer)` — bulk load straight from Arrow IPC data.
|
|
61
|
+
- `conn.writer('sensors')` — streaming writer with event-time `watermark(ts)` and
|
|
62
|
+
backpressure visibility (`pending()`, `isBackpressured()`).
|
|
57
63
|
|
|
58
|
-
##
|
|
64
|
+
## Subscribing to streams
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
Consume a stream or materialized view as it computes — async iteration first:
|
|
61
67
|
|
|
62
68
|
```js
|
|
63
69
|
const sub = await conn.subscribe('sensor_rollup')
|
|
@@ -67,56 +73,60 @@ for await (const frame of sub) {
|
|
|
67
73
|
}
|
|
68
74
|
```
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
queries work the same way:
|
|
73
|
-
|
|
74
|
-
Telemetry (`metrics()`, `sourceMetrics()`, `pipelineState()`, `pipelineWatermark()`,
|
|
75
|
-
`totalEventsProcessed()`) and query cancellation (`cancelQuery(id)`) round out the runtime
|
|
76
|
-
surface. Benchmark baseline: `docs/benchmarks.md`.
|
|
76
|
+
Prefer callbacks? `conn.subscribeWith('sensor_rollup', { onData, onError, onClose })`
|
|
77
|
+
delivers awaited frames — a slow handler slows the stream instead of growing a queue.
|
|
78
|
+
Streaming queries work the same way:
|
|
79
|
+
`for await (const batch of conn.streamQuery(sql)) {}`.
|
|
77
80
|
|
|
78
81
|
## Errors
|
|
79
82
|
|
|
80
|
-
Every failure throws a `LaminarError` subclass
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
Every failure throws a `LaminarError` subclass with a numeric `code`:
|
|
84
|
+
|
|
85
|
+
| Class | Codes | Meaning |
|
|
86
|
+
| -------------------------- | ----- | ----------------------------------------- |
|
|
87
|
+
| `LaminarConnectionError` | 100s | connection lifecycle |
|
|
88
|
+
| `LaminarSchemaError` | 200s | unknown table, schema problems |
|
|
89
|
+
| `LaminarIngestionError` | 300s | bad rows, wrong types, closed writer |
|
|
90
|
+
| `LaminarQueryError` | 400s | SQL errors, non-queries |
|
|
91
|
+
| `LaminarSubscriptionError` | 500s | subscription failures (502 = fell behind) |
|
|
92
|
+
| `LaminarInternalError` | 900s | engine or binding internals |
|
|
84
93
|
|
|
85
94
|
```js
|
|
86
95
|
try {
|
|
87
96
|
conn.insert('sensors', [{ ts: 1, device: 'd1', value: 'oops' }])
|
|
88
97
|
} catch (error) {
|
|
89
|
-
if (error
|
|
90
|
-
//
|
|
98
|
+
if (error instanceof LaminarIngestionError) {
|
|
99
|
+
// "column 'value': expected a number, got string (row 0)"
|
|
91
100
|
}
|
|
92
101
|
}
|
|
93
102
|
```
|
|
94
103
|
|
|
95
|
-
|
|
104
|
+
Runtime observability: `conn.metrics()`, `conn.sourceMetrics(name)`,
|
|
105
|
+
`conn.pipelineState()`, `conn.pipelineWatermark()`, `conn.totalEventsProcessed()`; long
|
|
106
|
+
queries can be cancelled with `conn.cancelQuery(id)`.
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
## Status
|
|
98
109
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
just verify # fmt + clippy -D warnings + rust tests + build + vitest
|
|
104
|
-
```
|
|
110
|
+
`0.30.0-alpha` — the embedded surface is complete (queries, ingestion, subscriptions,
|
|
111
|
+
telemetry); the API may still change before 1.0. This binding pins
|
|
112
|
+
[LaminarDB](https://github.com/laminardb/laminardb) core `v0.30.0` and covers embedded
|
|
113
|
+
mode; multi-node clusters run through the server, not in-process.
|
|
105
114
|
|
|
106
|
-
|
|
107
|
-
registry in `CORE_PIN.md`) — expect a long cold build.
|
|
115
|
+
## Developing this repository
|
|
108
116
|
|
|
109
|
-
|
|
117
|
+
Contributions need Rust stable (≥ 1.95), Node ≥ 20, and
|
|
118
|
+
[just](https://github.com/casey/just):
|
|
110
119
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
```sh
|
|
121
|
+
just install # pnpm install
|
|
122
|
+
just build # native addon + TypeScript layer
|
|
123
|
+
just test # full suite against the built addon
|
|
124
|
+
just verify # fmt + clippy + rust tests + build + vitest
|
|
125
|
+
```
|
|
116
126
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
The first build compiles the pinned Rust core — expect a long cold build. Engineering
|
|
128
|
+
records live in `docs/plans/` (decision records, phase plans) and `docs/reviews/`;
|
|
129
|
+
`CORE_PIN.md` tracks which core release each version ships; `docs/benchmarks.md` holds the
|
|
130
|
+
measured baseline.
|
|
121
131
|
|
|
122
132
|
Apache-2.0, like the core.
|
package/index.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ESM entry. The implementation layer (dist/index.js) is CommonJS; this
|
|
2
|
+
// shim gives `import { LaminarDB } from '@laminardb/node'` real named ESM
|
|
3
|
+
// exports on every Node version, independent of CJS named-export detection.
|
|
4
|
+
// __test__/package-surface.spec.mjs asserts this list matches the CJS
|
|
5
|
+
// surface, so the two cannot drift.
|
|
6
|
+
import laminardb from './dist/index.js'
|
|
7
|
+
|
|
8
|
+
export const {
|
|
9
|
+
LaminarDB,
|
|
10
|
+
Connection,
|
|
11
|
+
Writer,
|
|
12
|
+
Subscription,
|
|
13
|
+
PushSubscription,
|
|
14
|
+
QueryStream,
|
|
15
|
+
toLaminarError,
|
|
16
|
+
tableFrom,
|
|
17
|
+
LaminarError,
|
|
18
|
+
LaminarConnectionError,
|
|
19
|
+
LaminarSchemaError,
|
|
20
|
+
LaminarIngestionError,
|
|
21
|
+
LaminarQueryError,
|
|
22
|
+
LaminarSubscriptionError,
|
|
23
|
+
LaminarInternalError,
|
|
24
|
+
} = laminardb
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@laminardb/node",
|
|
3
|
-
"version": "0.30.0-alpha.
|
|
4
|
-
"description": "Embedded streaming SQL for Node.js
|
|
3
|
+
"version": "0.30.0-alpha.3",
|
|
4
|
+
"description": "Embedded streaming SQL for Node.js — official LaminarDB native binding",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"index.js",
|
|
9
|
+
"index.mjs",
|
|
9
10
|
"dist"
|
|
10
11
|
],
|
|
11
12
|
"napi": {
|
|
@@ -65,13 +66,22 @@
|
|
|
65
66
|
"access": "public",
|
|
66
67
|
"registry": "https://registry.npmjs.org/"
|
|
67
68
|
},
|
|
69
|
+
"exports": {
|
|
70
|
+
".": {
|
|
71
|
+
"types": "./dist/index.d.ts",
|
|
72
|
+
"import": "./index.mjs",
|
|
73
|
+
"require": "./dist/index.js",
|
|
74
|
+
"default": "./dist/index.js"
|
|
75
|
+
},
|
|
76
|
+
"./package.json": "./package.json"
|
|
77
|
+
},
|
|
68
78
|
"optionalDependencies": {
|
|
69
|
-
"@laminardb/node-
|
|
70
|
-
"@laminardb/node-
|
|
71
|
-
"@laminardb/node-linux-
|
|
72
|
-
"@laminardb/node-linux-
|
|
73
|
-
"@laminardb/node-
|
|
74
|
-
"@laminardb/node-
|
|
75
|
-
"@laminardb/node-win32-x64-msvc": "0.30.0-alpha.
|
|
79
|
+
"@laminardb/node-linux-x64-gnu": "0.30.0-alpha.3",
|
|
80
|
+
"@laminardb/node-linux-x64-musl": "0.30.0-alpha.3",
|
|
81
|
+
"@laminardb/node-linux-arm64-gnu": "0.30.0-alpha.3",
|
|
82
|
+
"@laminardb/node-linux-arm64-musl": "0.30.0-alpha.3",
|
|
83
|
+
"@laminardb/node-darwin-x64": "0.30.0-alpha.3",
|
|
84
|
+
"@laminardb/node-darwin-arm64": "0.30.0-alpha.3",
|
|
85
|
+
"@laminardb/node-win32-x64-msvc": "0.30.0-alpha.3"
|
|
76
86
|
}
|
|
77
|
-
}
|
|
87
|
+
}
|