@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.
Files changed (3) hide show
  1. package/README.md +76 -66
  2. package/index.mjs +24 -0
  3. package/package.json +20 -10
package/README.md CHANGED
@@ -1,16 +1,18 @@
1
- # laminardb-nodejs
1
+ # @laminardb/node
2
2
 
3
- Embedded streaming SQL for Node.js and TypeScript. This is the official Node.js binding
4
- for [LaminarDB](https://github.com/laminardb/laminardb), built as a
5
- [napi-rs](https://napi.rs) native addon over a pinned core release — the same two-layer
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
- Status: **alpha** — embedded MVP (Phase 1). Subscriptions (async iterators), Windows/musl
11
- CI, and npm distribution land over the next phases. Not yet on npm — build from source.
7
+ ```sh
8
+ npm install @laminardb/node
9
+ ```
12
10
 
13
- ## Quickstart
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()) // [{ device: 'd1', avg_value: 21.5 }, ...]
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
- Durable embedded mode is one argument plus checkpointing:
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
- ```js
38
- const conn = await LaminarDB.open('./data', { checkpoint: { intervalMs: 5000 } })
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
- Topology DDL (`CREATE SOURCE` / `STREAM` / `SINK`) must run before `start()`; manual
42
- `checkpoint()` requires at least one stream or sink in the topology (the core wires the
43
- checkpoint coordinator only for real pipelines).
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
- ## Data access
56
+ ## Writing data
46
57
 
47
- - `result.toArray()` / `batch.toArray()` — row objects, no dependencies. Conventions:
48
- temporal columns are **milliseconds since epoch** in and out; `Int64`/`UInt64` cross as
49
- JS `BigInt`.
50
- - `result.toIPC()` / `batch.toIPC()` one Arrow IPC stream `Buffer`; rehydrate with
51
- [`apache-arrow`](https://www.npmjs.com/package/apache-arrow) (an optional peer
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
- ## Subscriptions
64
+ ## Subscribing to streams
59
65
 
60
- Streams and materialized views are consumable frame by frame — async-iterable first:
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
- Push style delivers awaited frames to handlers (a slow handler backpressures instead of
71
- queueing): `conn.subscribeWith('sensor_rollup', { onData, onError, onClose })`. Streaming
72
- queries work the same way: `for await (const batch of conn.streamQuery(sql))`.
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 carrying the core's numeric `code`:
81
- `LaminarConnectionError` (100s), `LaminarSchemaError` (200s), `LaminarIngestionError`
82
- (300s), `LaminarQueryError` (400s), `LaminarSubscriptionError` (500s),
83
- `LaminarInternalError` (900s).
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.code === 300) {
90
- // error.message: column 'value': expected a number, got string (row 0)
98
+ if (error instanceof LaminarIngestionError) {
99
+ // "column 'value': expected a number, got string (row 0)"
91
100
  }
92
101
  }
93
102
  ```
94
103
 
95
- ## Build from source
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
- Requires Rust stable (≥ 1.95) and Node ≥ 20 with pnpm.
108
+ ## Status
98
109
 
99
- ```sh
100
- just install # pnpm install (@napi-rs/cli, vitest, prettier, typescript, apache-arrow)
101
- just build # debug addon + generated loader + TypeScript layer (dist/)
102
- just test # vitest suites against the built addon
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
- The first build clones and compiles the pinned LaminarDB core (git tag in `Cargo.toml`,
107
- registry in `CORE_PIN.md`) — expect a long cold build.
115
+ ## Developing this repository
108
116
 
109
- ## Platform support
117
+ Contributions need Rust stable (≥ 1.95), Node ≥ 20, and
118
+ [just](https://github.com/casey/just):
110
119
 
111
- The release matrix (Phase 3) covers macOS x64/arm64, Linux x64/arm64 (glibc and musl), and
112
- Windows x64, distributed as per-platform optional npm packages with no postinstall and no
113
- source compilation. Until then, `napi build` works anywhere the toolchain does.
114
-
115
- ## Documentation
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
- - `docs/plans/`decision records and phase plans (start at
118
- `00-overview-and-decisions.md`)
119
- - `CORE_PIN.md` which core release each binding version ships
120
- - `CHANGELOG.md`
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.1",
4
- "description": "Embedded streaming SQL for Node.js \u2014 official LaminarDB native binding",
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-darwin-x64": "0.30.0-alpha.1",
70
- "@laminardb/node-darwin-arm64": "0.30.0-alpha.1",
71
- "@laminardb/node-linux-x64-gnu": "0.30.0-alpha.1",
72
- "@laminardb/node-linux-x64-musl": "0.30.0-alpha.1",
73
- "@laminardb/node-linux-arm64-gnu": "0.30.0-alpha.1",
74
- "@laminardb/node-linux-arm64-musl": "0.30.0-alpha.1",
75
- "@laminardb/node-win32-x64-msvc": "0.30.0-alpha.1"
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
+ }