@cqlite/node 0.12.0 → 0.14.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 +119 -13
- package/cqlite-node.darwin-arm64.node +0 -0
- package/cqlite-node.darwin-x64.node +0 -0
- package/cqlite-node.linux-arm64-gnu.node +0 -0
- package/cqlite-node.linux-x64-gnu.node +0 -0
- package/cqlite-node.win32-x64-msvc.node +0 -0
- package/lib/error-wrapper.js +161 -24
- package/lib/index.d.ts +240 -23
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@ import { Database } from '@cqlite/node';
|
|
|
16
16
|
// Open a database with schema
|
|
17
17
|
const db = await Database.open('path/to/sstables', { schema: 'schema.cql' });
|
|
18
18
|
|
|
19
|
-
// Execute queries
|
|
20
|
-
const result = await db.
|
|
19
|
+
// Execute queries (executeNative() returns native JS types with full precision)
|
|
20
|
+
const result = await db.executeNative('SELECT * FROM keyspace.table LIMIT 10');
|
|
21
21
|
for (const row of result.rows) {
|
|
22
22
|
console.log(row.name);
|
|
23
23
|
}
|
|
@@ -25,6 +25,20 @@ for (const row of result.rows) {
|
|
|
25
25
|
await db.close();
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
> **⚠️ Warning: `execute()` is deprecated and will be removed in the next major.**
|
|
29
|
+
> Prefer `executeNative()`. `execute()` returns **lossy** legacy JSON encodings:
|
|
30
|
+
> - `blob` → base64 **string** (not a `Buffer`)
|
|
31
|
+
> - `timestamp` → ISO-8601 **string** (not a `Date`)
|
|
32
|
+
> - `varint` → `"0x{hex}"` **string**
|
|
33
|
+
> - `decimal` → `"decimal:{scale}:0x{hex}"` **string**
|
|
34
|
+
> - `date`/`time` → **number** (days-since-epoch / nanoseconds-since-midnight)
|
|
35
|
+
>
|
|
36
|
+
> It is also slower (JSON off-loop, then JS on-loop — a double conversion).
|
|
37
|
+
> Calling `execute()` emits a one-time `DeprecationWarning`. Use `executeNative()`
|
|
38
|
+
> for native types (`BigInt`, `Buffer`, `Date`, `Set`, `Map`) with full fidelity.
|
|
39
|
+
> (`bigint`/`counter` currently come back as an exact `BigInt` on this napi build,
|
|
40
|
+
> so they are not presently rounded — but `execute()` is unsupported regardless.)
|
|
41
|
+
|
|
28
42
|
## Features
|
|
29
43
|
|
|
30
44
|
- **Zero cluster dependency** - Read SSTable files directly from disk
|
|
@@ -70,14 +84,14 @@ The `close()` method is idempotent - safe to call multiple times.
|
|
|
70
84
|
### Executing Queries
|
|
71
85
|
|
|
72
86
|
```typescript
|
|
73
|
-
// Simple query - returns
|
|
74
|
-
const result = await db.
|
|
87
|
+
// Simple query - executeNative() returns native JS types with full precision
|
|
88
|
+
const result = await db.executeNative('SELECT * FROM keyspace.table');
|
|
75
89
|
for (const row of result.rows) {
|
|
76
90
|
console.log(row);
|
|
77
91
|
}
|
|
78
92
|
|
|
79
93
|
// With LIMIT
|
|
80
|
-
const limited = await db.
|
|
94
|
+
const limited = await db.executeNative('SELECT name, age FROM users LIMIT 100');
|
|
81
95
|
|
|
82
96
|
// Access query metadata
|
|
83
97
|
console.log(`Rows returned: ${result.rowCount}`);
|
|
@@ -85,6 +99,9 @@ console.log(`Execution time: ${result.executionTimeMs}ms`);
|
|
|
85
99
|
console.log(`Columns: ${result.columns.map(c => c.name).join(', ')}`);
|
|
86
100
|
```
|
|
87
101
|
|
|
102
|
+
> Prefer `executeNative()` over the deprecated `execute()` — see the warning at
|
|
103
|
+
> the top of this README for the precision/encoding hazards of `execute()`.
|
|
104
|
+
|
|
88
105
|
### Native Types with executeNative()
|
|
89
106
|
|
|
90
107
|
Use `executeNative()` to get native JavaScript types instead of JSON-serializable values:
|
|
@@ -109,7 +126,13 @@ for (const row of result.rows) {
|
|
|
109
126
|
}
|
|
110
127
|
```
|
|
111
128
|
|
|
112
|
-
### JSON Encoding (execute method)
|
|
129
|
+
### JSON Encoding (deprecated `execute()` method)
|
|
130
|
+
|
|
131
|
+
> **⚠️ Deprecated — removed in the next major.** `execute()` returns lossy legacy
|
|
132
|
+
> JSON encodings and is slower than `executeNative()`. In particular blob comes
|
|
133
|
+
> back as a base64 string, timestamp as an ISO-8601 string, and varint/decimal
|
|
134
|
+
> as bespoke non-round-trippable strings. This section documents the encoding for
|
|
135
|
+
> the few callers that still depend on it; new code should use `executeNative()`.
|
|
113
136
|
|
|
114
137
|
The `execute()` method returns JSON-serializable values. For most types this works intuitively,
|
|
115
138
|
but `varint` and `decimal` types use a hex-based encoding to preserve arbitrary precision:
|
|
@@ -132,15 +155,16 @@ console.log(native.rows[0].amount);
|
|
|
132
155
|
- `varint`: `"0x{hex}"` - Two's complement big-endian hex encoding
|
|
133
156
|
- `decimal`: `"decimal:{scale}:0x{hex}"` - Scale (decimal places) + hex-encoded unscaled value
|
|
134
157
|
|
|
135
|
-
**Recommendation:** Use `executeNative()
|
|
136
|
-
|
|
158
|
+
**Recommendation:** Use `executeNative()`. The `execute()` method is deprecated
|
|
159
|
+
(removed in the next major); its JSON encoding is lossy (blob/timestamp/varint/
|
|
160
|
+
decimal come back as bespoke strings) and it is slower than `executeNative()`.
|
|
137
161
|
|
|
138
162
|
### Column Metadata
|
|
139
163
|
|
|
140
164
|
Each query result includes column information:
|
|
141
165
|
|
|
142
166
|
```typescript
|
|
143
|
-
const result = await db.
|
|
167
|
+
const result = await db.executeNative('SELECT * FROM keyspace.table');
|
|
144
168
|
|
|
145
169
|
for (const col of result.columns) {
|
|
146
170
|
console.log(`${col.name}: ${col.dataType}`);
|
|
@@ -158,6 +182,78 @@ console.log(`Total rows: ${stats.totalRows}`);
|
|
|
158
182
|
console.log(`Memory: ${stats.memoryUsedBytes} bytes`);
|
|
159
183
|
```
|
|
160
184
|
|
|
185
|
+
### Refreshing SSTables (v0.13)
|
|
186
|
+
|
|
187
|
+
If Cassandra (or another process) writes new SSTables while your `Database` handle
|
|
188
|
+
is open, call `refresh()` to re-discover them. Refresh is **explicit-only** (CQLite
|
|
189
|
+
never rescans behind your back) and **atomic / fail-closed**: if any newly found
|
|
190
|
+
generation fails to open, the swap is rolled back and the handle keeps serving the
|
|
191
|
+
prior, consistent set of readers.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// ... time passes; Cassandra flushes/compacts new SSTables to disk ...
|
|
195
|
+
|
|
196
|
+
const report = await db.refresh();
|
|
197
|
+
console.log(`Tables scanned: ${report.tablesScanned}`);
|
|
198
|
+
console.log(`Readers added: ${report.readersAdded}`);
|
|
199
|
+
console.log(`Readers removed: ${report.readersRemoved}`);
|
|
200
|
+
|
|
201
|
+
// Subsequent queries see the newly discovered data
|
|
202
|
+
const result = await db.executeNative('SELECT * FROM keyspace.table');
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`refresh(): Promise<RefreshReport>` resolves to a `RefreshReport` with the numeric
|
|
206
|
+
fields `tablesScanned`, `readersAdded`, and `readersRemoved`.
|
|
207
|
+
|
|
208
|
+
### Result Byte Budget (v0.13)
|
|
209
|
+
|
|
210
|
+
Non-streaming queries are bounded by a result-size budget of **64 MiB** by default.
|
|
211
|
+
When the materialized result's running byte estimate exceeds the budget, the query
|
|
212
|
+
rejects with a `CqliteError` whose `code === 'QUERY'`, directing you to add a
|
|
213
|
+
`LIMIT` clause or use `executeStreaming()`. Streaming queries are **not** subject
|
|
214
|
+
to this budget.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
try {
|
|
218
|
+
const result = await db.executeNative('SELECT * FROM keyspace.big_table');
|
|
219
|
+
for (const row of result.rows) {
|
|
220
|
+
process(row);
|
|
221
|
+
}
|
|
222
|
+
} catch (e) {
|
|
223
|
+
if (e.code === 'QUERY') {
|
|
224
|
+
// Result exceeded the 64 MiB byte budget — add a LIMIT or stream instead
|
|
225
|
+
for await (const row of db.executeStreaming('SELECT * FROM keyspace.big_table')) {
|
|
226
|
+
process(row);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### OpenTelemetry Tracing (v0.13)
|
|
235
|
+
|
|
236
|
+
CQLite can emit OpenTelemetry traces when built with the `observability` Cargo
|
|
237
|
+
feature; without that feature the configuration is accepted but is a no-op. Pass an
|
|
238
|
+
`otel` option to `Database.open()`:
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
const db = await Database.open('path/to/sstables', {
|
|
242
|
+
schema: 'schema.cql',
|
|
243
|
+
otel: {
|
|
244
|
+
enabled: true, // default false
|
|
245
|
+
endpoint: 'http://localhost:4317', // default 'http://localhost:4317'
|
|
246
|
+
protocol: 'grpc', // 'grpc' (default) or 'http'
|
|
247
|
+
serviceName: 'cqlite', // default 'cqlite'
|
|
248
|
+
serviceVersion: '0.13.0', // default: package version
|
|
249
|
+
samplingRatio: 1.0, // default 1.0
|
|
250
|
+
timeoutMs: 10000, // default 10000
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Options are layered over the `CQLITE_OTEL_*` environment variables.
|
|
256
|
+
|
|
161
257
|
### Error Handling
|
|
162
258
|
|
|
163
259
|
All errors include structured metadata for programmatic handling:
|
|
@@ -167,7 +263,7 @@ import { Database } from '@cqlite/node';
|
|
|
167
263
|
|
|
168
264
|
try {
|
|
169
265
|
const db = await Database.open('/path/to/data');
|
|
170
|
-
const result = await db.
|
|
266
|
+
const result = await db.executeNative('SELECT * FROM keyspace.table');
|
|
171
267
|
} catch (e) {
|
|
172
268
|
// Error code for programmatic handling
|
|
173
269
|
console.log(`Code: ${e.code}`); // 'IO', 'SCHEMA', 'QUERY', 'PARSE', etc.
|
|
@@ -240,11 +336,11 @@ const db = await Database.open('path/to/sstables', {
|
|
|
240
336
|
});
|
|
241
337
|
|
|
242
338
|
// Write rows via CQL INSERT, UPDATE, or DELETE
|
|
243
|
-
await db.
|
|
339
|
+
await db.executeNative(
|
|
244
340
|
"INSERT INTO test_basic.simple_table (id, name, age) " +
|
|
245
341
|
"VALUES (22222222-2222-2222-2222-222222222222, 'Bob', 25)"
|
|
246
342
|
);
|
|
247
|
-
await db.
|
|
343
|
+
await db.executeNative(
|
|
248
344
|
"UPDATE test_basic.simple_table SET age = 26 " +
|
|
249
345
|
"WHERE id = 22222222-2222-2222-2222-222222222222"
|
|
250
346
|
);
|
|
@@ -273,7 +369,8 @@ await db.close();
|
|
|
273
369
|
|
|
274
370
|
| Method / Property | Description |
|
|
275
371
|
|-------------------|-------------|
|
|
276
|
-
| `db.
|
|
372
|
+
| `db.executeNative(cql)` | Execute a CQL INSERT, UPDATE, or DELETE statement (recommended) |
|
|
373
|
+
| `db.execute(cql)` | **Deprecated** (removed next major; emits a `DeprecationWarning`). Same DML behavior as `executeNative()`, but lossy for SELECT — use `executeNative()` |
|
|
277
374
|
| `db.flushRun()` | Flush memtable to SSTable; returns the Data.db path or `""` if memtable was empty |
|
|
278
375
|
| `db.maintenanceStep(options?)` | Run STCS compaction for up to `options.budgetMs` ms (default: 100); returns `MaintenanceReport` |
|
|
279
376
|
| `db.writeStats` | Synchronous getter: `memtableSizeBytes`, `memtableRowCount`, `totalWrittenBytes`, `l0SstableCount` |
|
|
@@ -297,6 +394,15 @@ See the [examples/](examples/) directory for complete working examples:
|
|
|
297
394
|
- [streaming.ts](examples/streaming.ts) - Large result handling
|
|
298
395
|
- [performance.ts](examples/performance.ts) - Memory-optimized usage
|
|
299
396
|
|
|
397
|
+
> **Streaming concurrency caveat:** `executeStreaming()` fetches each batch of
|
|
398
|
+
> `K = bufferSize` rows on a libuv threadpool thread, so N concurrent streams can
|
|
399
|
+
> each occupy a libuv threadpool thread for the duration of a batch fetch. Heavy
|
|
400
|
+
> concurrent `fs`/`crypto` work in the same process may see added latency until
|
|
401
|
+
> the follow-up ([#1901](https://github.com/pmcfadin/cqlite/issues/1901)) moves
|
|
402
|
+
> streaming off the libuv pool onto the tokio runtime. If an error occurs
|
|
403
|
+
> mid-stream, rows already read in the in-flight batch (up to `bufferSize`) are
|
|
404
|
+
> not delivered — the iterator rejects with the error (errors are terminal).
|
|
405
|
+
|
|
300
406
|
## Resources
|
|
301
407
|
|
|
302
408
|
- [TypeScript Definitions](lib/index.d.ts) - Complete API type hints
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/error-wrapper.js
CHANGED
|
@@ -95,6 +95,89 @@ function wrapAsync(fn) {
|
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Build an AsyncIterator that yields ONE row per `next()` while fetching rows
|
|
100
|
+
* from the native stream in BATCHES (issue #1443).
|
|
101
|
+
*
|
|
102
|
+
* The native `StreamingResult.next()` returns `{ rows: Array<Row>, done }` — a
|
|
103
|
+
* whole batch per AsyncTask/`block_on` (K == the stream's `bufferSize`), instead
|
|
104
|
+
* of one row per task. This wrapper buffers that batch and drains it one row at
|
|
105
|
+
* a time, so the public per-row `for await ... of` contract is UNCHANGED
|
|
106
|
+
* (consumers still see exactly one row per iteration; batching is invisible).
|
|
107
|
+
* Amortising dispatch over K rows both raises throughput and stops a busy stream
|
|
108
|
+
* from monopolising libuv's small (default 4) threadpool and starving concurrent
|
|
109
|
+
* `fs`/`crypto` work.
|
|
110
|
+
*
|
|
111
|
+
* @param {() => Promise<{rows: Array<Object>, done: boolean}>} refill
|
|
112
|
+
* Fetches the next batch from the native stream. May throw (already enhanced).
|
|
113
|
+
* @param {(yielded: number) => (void|Promise<void>)} onReturn
|
|
114
|
+
* Invoked on early termination (`return()`/`break`) to close the native
|
|
115
|
+
* stream. Receives the exact number of rows this iterator YIELDED to the
|
|
116
|
+
* consumer, so the native span records rows-yielded rather than the whole
|
|
117
|
+
* fetched batch (the un-yielded tail of the last batch is discarded here on
|
|
118
|
+
* early break). See issue #1443.
|
|
119
|
+
* @param {() => boolean} [isCancelled]
|
|
120
|
+
* Optional predicate checked before each `next()`; when it returns true the
|
|
121
|
+
* iterator discards any buffered rows and reports `done` immediately. This is
|
|
122
|
+
* how an external `close()` on the stream object takes effect even though the
|
|
123
|
+
* batch buffer lives in this iterator's closure.
|
|
124
|
+
* @returns {AsyncIterator} Iterator yielding one row per `next()`.
|
|
125
|
+
*/
|
|
126
|
+
function batchedAsyncIterator(refill, onReturn, isCancelled) {
|
|
127
|
+
let buffer = [];
|
|
128
|
+
let bufIdx = 0;
|
|
129
|
+
let exhausted = false;
|
|
130
|
+
// Exact count of rows YIELDED to the consumer (one per `next()` that returns
|
|
131
|
+
// a value). Passed to `onReturn` on early break so the native span records
|
|
132
|
+
// rows-yielded, not the whole fetched batch (issue #1443).
|
|
133
|
+
let yielded = 0;
|
|
134
|
+
return {
|
|
135
|
+
async next() {
|
|
136
|
+
// Honour an external close(): discard buffered rows and end immediately.
|
|
137
|
+
if (isCancelled && isCancelled()) {
|
|
138
|
+
buffer = [];
|
|
139
|
+
bufIdx = 0;
|
|
140
|
+
exhausted = true;
|
|
141
|
+
return { value: undefined, done: true };
|
|
142
|
+
}
|
|
143
|
+
// Drain the buffered batch first — no native call, no threadpool dispatch.
|
|
144
|
+
if (bufIdx < buffer.length) {
|
|
145
|
+
yielded++;
|
|
146
|
+
return { value: buffer[bufIdx++], done: false };
|
|
147
|
+
}
|
|
148
|
+
if (exhausted) {
|
|
149
|
+
return { value: undefined, done: true };
|
|
150
|
+
}
|
|
151
|
+
// Refill: exactly ONE AsyncTask/block_on fetches a whole batch.
|
|
152
|
+
const batch = await refill();
|
|
153
|
+
buffer = (batch && batch.rows) || [];
|
|
154
|
+
bufIdx = 0;
|
|
155
|
+
// An empty batch always signals exhaustion (native `Done`); a `done` flag
|
|
156
|
+
// is honoured defensively too. A non-empty batch may still be the final
|
|
157
|
+
// one — the next refill then observes the empty batch and ends the stream.
|
|
158
|
+
if (!batch || batch.done || buffer.length === 0) {
|
|
159
|
+
exhausted = true;
|
|
160
|
+
}
|
|
161
|
+
if (bufIdx < buffer.length) {
|
|
162
|
+
yielded++;
|
|
163
|
+
return { value: buffer[bufIdx++], done: false };
|
|
164
|
+
}
|
|
165
|
+
return { value: undefined, done: true };
|
|
166
|
+
},
|
|
167
|
+
async return() {
|
|
168
|
+
// Early `break`/`return()`: discard any un-yielded buffered rows and close
|
|
169
|
+
// the native stream (which terminates the producer and finalises the
|
|
170
|
+
// span). Pass the exact rows yielded so the span is not over-counted by
|
|
171
|
+
// the discarded buffer tail (issue #1443).
|
|
172
|
+
buffer = [];
|
|
173
|
+
bufIdx = 0;
|
|
174
|
+
exhausted = true;
|
|
175
|
+
await onReturn(yielded);
|
|
176
|
+
return { value: undefined, done: true };
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
98
181
|
/**
|
|
99
182
|
* Create an async iterable wrapper around a native StreamingResult.
|
|
100
183
|
*
|
|
@@ -105,6 +188,7 @@ function wrapAsync(fn) {
|
|
|
105
188
|
* @returns {Object} An async iterable object with streaming functionality
|
|
106
189
|
*/
|
|
107
190
|
function createAsyncIterator(nativeStream) {
|
|
191
|
+
let closed = false;
|
|
108
192
|
return {
|
|
109
193
|
/**
|
|
110
194
|
* Number of rows received so far.
|
|
@@ -127,42 +211,70 @@ function createAsyncIterator(nativeStream) {
|
|
|
127
211
|
* Safe to call multiple times.
|
|
128
212
|
*/
|
|
129
213
|
close() {
|
|
214
|
+
closed = true;
|
|
130
215
|
return nativeStream.close();
|
|
131
216
|
},
|
|
132
217
|
|
|
133
218
|
/**
|
|
134
219
|
* Implement Symbol.asyncIterator for `for await...of` support.
|
|
220
|
+
*
|
|
221
|
+
* Yields one row per iteration while fetching in batches (issue #1443).
|
|
135
222
|
* @returns {AsyncIterator}
|
|
136
223
|
*/
|
|
137
224
|
[Symbol.asyncIterator]() {
|
|
138
|
-
return
|
|
139
|
-
|
|
140
|
-
* Get the next row from the stream.
|
|
141
|
-
* @returns {Promise<{value: Object|undefined, done: boolean}>}
|
|
142
|
-
*/
|
|
143
|
-
async next() {
|
|
225
|
+
return batchedAsyncIterator(
|
|
226
|
+
async () => {
|
|
144
227
|
try {
|
|
145
|
-
|
|
146
|
-
return result;
|
|
228
|
+
return await nativeStream.next();
|
|
147
229
|
} catch (error) {
|
|
148
230
|
throw enhanceError(error);
|
|
149
231
|
}
|
|
150
232
|
},
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
* Called automatically by JavaScript runtime.
|
|
155
|
-
* @returns {Promise<{value: undefined, done: true}>}
|
|
156
|
-
*/
|
|
157
|
-
async return() {
|
|
158
|
-
nativeStream.close();
|
|
159
|
-
return { value: undefined, done: true };
|
|
233
|
+
(yielded) => {
|
|
234
|
+
closed = true;
|
|
235
|
+
nativeStream.close(yielded);
|
|
160
236
|
},
|
|
161
|
-
|
|
237
|
+
() => closed
|
|
238
|
+
);
|
|
162
239
|
},
|
|
163
240
|
};
|
|
164
241
|
}
|
|
165
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Emit a one-time deprecation warning for the legacy `execute()` method.
|
|
245
|
+
*
|
|
246
|
+
* `execute()` returns lossy legacy JSON encodings — blob comes back as a base64
|
|
247
|
+
* string (not a Buffer), timestamp as an ISO-8601 string (not a Date), and
|
|
248
|
+
* varint/decimal in bespoke `"0x…"` / `"decimal:…"` strings no caller can
|
|
249
|
+
* round-trip (see index.d.ts). It also double-converts (JSON off-loop, then JS
|
|
250
|
+
* on-loop) so it is slower than `executeNative()`. It is deprecated and will be
|
|
251
|
+
* removed in the next major; `executeNative()` returns native types with full
|
|
252
|
+
* fidelity. We emit via `process.emitWarning(..., 'DeprecationWarning')` guarded
|
|
253
|
+
* by a module-level flag so it fires at most once per process, matching Node's
|
|
254
|
+
* own deprecation convention (issue #1457).
|
|
255
|
+
*
|
|
256
|
+
* @private
|
|
257
|
+
*/
|
|
258
|
+
let executeDeprecationWarned = false;
|
|
259
|
+
function warnExecuteDeprecated() {
|
|
260
|
+
if (executeDeprecationWarned) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
executeDeprecationWarned = true;
|
|
264
|
+
process.emitWarning(
|
|
265
|
+
"Database.execute() is deprecated and will be removed in the next major. " +
|
|
266
|
+
"It returns lossy legacy JSON encodings: blob becomes a base64 string " +
|
|
267
|
+
"(not a Buffer), timestamp an ISO-8601 string (not a Date), and " +
|
|
268
|
+
"varint/decimal bespoke non-round-trippable strings; it is also slower " +
|
|
269
|
+
"(double conversion). Use executeNative() for native types with full " +
|
|
270
|
+
"fidelity (BigInt, Buffer, Date, Set, Map).",
|
|
271
|
+
{
|
|
272
|
+
type: "DeprecationWarning",
|
|
273
|
+
code: "CQLITE_DEP0001",
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
166
278
|
/**
|
|
167
279
|
* Create a wrapped Database class with enhanced error handling.
|
|
168
280
|
*
|
|
@@ -187,6 +299,7 @@ function createWrappedDatabase(NativeDatabase, wrapPreparedStatement) {
|
|
|
187
299
|
}
|
|
188
300
|
|
|
189
301
|
async execute(query) {
|
|
302
|
+
warnExecuteDeprecated();
|
|
190
303
|
try {
|
|
191
304
|
const result = await this._native.execute(query);
|
|
192
305
|
// For SELECT: rowsAffected = rowCount (alias, Issue #348).
|
|
@@ -229,6 +342,25 @@ function createWrappedDatabase(NativeDatabase, wrapPreparedStatement) {
|
|
|
229
342
|
}
|
|
230
343
|
}
|
|
231
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Re-discover the data directory and apply changes to the held reader set.
|
|
347
|
+
*
|
|
348
|
+
* Newly present SSTable generations become queryable, removed generations
|
|
349
|
+
* stop being queried, and unchanged generations keep their warm parsed
|
|
350
|
+
* state. In-flight queries are unaffected; the refresh is atomic and
|
|
351
|
+
* fail-closed. See index.d.ts for the full contract (issue #1749).
|
|
352
|
+
*
|
|
353
|
+
* @returns {Promise<Object>} RefreshReport with tablesScanned, readersAdded, readersRemoved
|
|
354
|
+
* @throws {CqliteError} If the database is closed or a new generation fails to open
|
|
355
|
+
*/
|
|
356
|
+
async refresh() {
|
|
357
|
+
try {
|
|
358
|
+
return await this._native.refresh();
|
|
359
|
+
} catch (error) {
|
|
360
|
+
throw enhanceError(error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
232
364
|
async close() {
|
|
233
365
|
try {
|
|
234
366
|
return await this._native.close();
|
|
@@ -328,11 +460,16 @@ function createWrappedDatabase(NativeDatabase, wrapPreparedStatement) {
|
|
|
328
460
|
|
|
329
461
|
/**
|
|
330
462
|
* Implement Symbol.asyncIterator for `for await...of` support.
|
|
463
|
+
*
|
|
464
|
+
* Yields one row per iteration while the native stream is fetched in
|
|
465
|
+
* batches (issue #1443): each refill is a single AsyncTask/block_on that
|
|
466
|
+
* returns up to `bufferSize` rows, which are then drained one at a time.
|
|
467
|
+
* The per-row consumer contract is unchanged; batching is invisible.
|
|
331
468
|
* @returns {AsyncIterator}
|
|
332
469
|
*/
|
|
333
470
|
[Symbol.asyncIterator]() {
|
|
334
|
-
return
|
|
335
|
-
async
|
|
471
|
+
return batchedAsyncIterator(
|
|
472
|
+
async () => {
|
|
336
473
|
try {
|
|
337
474
|
const stream = await ensureInitialized();
|
|
338
475
|
return await stream.next();
|
|
@@ -340,13 +477,13 @@ function createWrappedDatabase(NativeDatabase, wrapPreparedStatement) {
|
|
|
340
477
|
throw enhanceError(error);
|
|
341
478
|
}
|
|
342
479
|
},
|
|
343
|
-
|
|
480
|
+
(yielded) => {
|
|
344
481
|
closed = true;
|
|
345
482
|
nativeStreamPromise = null;
|
|
346
|
-
nativeStream?.close();
|
|
347
|
-
return { value: undefined, done: true };
|
|
483
|
+
nativeStream?.close(yielded);
|
|
348
484
|
},
|
|
349
|
-
|
|
485
|
+
() => closed
|
|
486
|
+
);
|
|
350
487
|
},
|
|
351
488
|
};
|
|
352
489
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -200,19 +200,24 @@ export interface ColumnInfo {
|
|
|
200
200
|
*/
|
|
201
201
|
export interface QueryResult {
|
|
202
202
|
/**
|
|
203
|
-
* Result rows as JSON-
|
|
203
|
+
* Result rows as legacy JSON-serialized objects (returned by `execute()`).
|
|
204
204
|
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* - Blob
|
|
208
|
-
* - Timestamp
|
|
209
|
-
* -
|
|
210
|
-
* -
|
|
211
|
-
* -
|
|
205
|
+
* ⚠️ These values are lossy legacy JSON encodings of CQL types — see the
|
|
206
|
+
* hazards on {@link Database.execute}:
|
|
207
|
+
* - **Blob → base64 `string`** (not a `Buffer`).
|
|
208
|
+
* - **Timestamp → ISO-8601 `string`** (not a `Date`).
|
|
209
|
+
* - **Varint → hex `string` `"0x{hex}"`** (e.g., `"0x7f"` for 127).
|
|
210
|
+
* - **Decimal → `string` `"decimal:{scale}:0x{hex}"`** (e.g., `"decimal:2:0x7b"`).
|
|
211
|
+
* - **Date/Time → `number`** (days-since-epoch / nanoseconds-since-midnight).
|
|
212
|
+
* - Set/Map → Array representations.
|
|
212
213
|
*
|
|
213
|
-
*
|
|
214
|
+
* (BigInt/Counter are currently returned as an exact `BigInt` on this napi
|
|
215
|
+
* build, but `execute()` is deprecated and unsupported regardless.)
|
|
214
216
|
*
|
|
215
|
-
*
|
|
217
|
+
* For native types with full fidelity, use `executeNative()`.
|
|
218
|
+
*
|
|
219
|
+
* @deprecated The execute() method uses lossy legacy JSON encoding and is
|
|
220
|
+
* removed in the next major. Use executeNative() for proper type fidelity.
|
|
216
221
|
*/
|
|
217
222
|
rows: Record<string, unknown>[];
|
|
218
223
|
|
|
@@ -374,6 +379,115 @@ export interface DatabaseOptions {
|
|
|
374
379
|
* ```
|
|
375
380
|
*/
|
|
376
381
|
writeDir?: string;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Enable automatic (STCS) size-tiered compaction for the write engine.
|
|
385
|
+
* Default: true. Set false to disable compaction — `maintenanceStep`
|
|
386
|
+
* then performs no merges (issue #1619).
|
|
387
|
+
*/
|
|
388
|
+
autoCompaction?: boolean;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Memtable flush threshold in bytes for the write engine (issue #1620).
|
|
392
|
+
* When the in-memory memtable grows past this size, the write path
|
|
393
|
+
* (`execute`) awaits a real async flush to a new SSTable generation.
|
|
394
|
+
* Only meaningful when `writable` is true. Default: 64 MB (67108864 bytes).
|
|
395
|
+
*/
|
|
396
|
+
flushThreshold?: number;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* OpenTelemetry export options (epic #1031, issue #1040).
|
|
400
|
+
*
|
|
401
|
+
* When omitted, the `CQLITE_OTEL_*` environment variables are consulted.
|
|
402
|
+
* Telemetry stays disabled unless `enabled: true` is set (here or via env)
|
|
403
|
+
* AND the native addon was built with the `observability` Cargo feature.
|
|
404
|
+
*
|
|
405
|
+
* Observability is initialised **once per process** on the first
|
|
406
|
+
* `Database.open()`, so passing different `otel` options to a later open has
|
|
407
|
+
* no effect.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```typescript
|
|
411
|
+
* const db = await Database.open('/data', {
|
|
412
|
+
* schema: 'schema.cql',
|
|
413
|
+
* otel: { enabled: true, endpoint: 'http://collector:4317', protocol: 'grpc' },
|
|
414
|
+
* });
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
otel?: OtelOptions;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Incoming W3C `traceparent` header to parent this handle's per-call and
|
|
421
|
+
* per-stream spans under a remote trace (distributed-tracing propagation).
|
|
422
|
+
*
|
|
423
|
+
* Applied as the default parent for every `execute`, `executeNative`, and
|
|
424
|
+
* `executeStreaming` on the returned handle. Invalid/empty values are
|
|
425
|
+
* ignored. Only meaningful when telemetry is enabled and the addon was built
|
|
426
|
+
* with the `observability` feature.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* const db = await Database.open('/data', {
|
|
431
|
+
* schema: 'schema.cql',
|
|
432
|
+
* otel: { enabled: true },
|
|
433
|
+
* traceparent: '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01',
|
|
434
|
+
* });
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
traceparent?: string;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* OpenTelemetry export options for the Node.js bindings (epic #1031, issue
|
|
442
|
+
* #1040).
|
|
443
|
+
*
|
|
444
|
+
* Any field left unset falls back to the corresponding `CQLITE_OTEL_*`
|
|
445
|
+
* environment variable, then to the foundation default. Exporters are only
|
|
446
|
+
* installed when the effective config has `enabled: true` AND the native addon
|
|
447
|
+
* was built with the `observability` feature.
|
|
448
|
+
*/
|
|
449
|
+
export interface OtelOptions {
|
|
450
|
+
/**
|
|
451
|
+
* Master enable switch. Unset defers to `CQLITE_OTEL_ENABLED`, then `false`.
|
|
452
|
+
*/
|
|
453
|
+
enabled?: boolean;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* OTLP collector endpoint: a gRPC endpoint or HTTP base URL.
|
|
457
|
+
* Unset defers to `CQLITE_OTEL_ENDPOINT`, then `http://localhost:4317`.
|
|
458
|
+
*/
|
|
459
|
+
endpoint?: string;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Wire protocol: `"grpc"` (default) or `"http"`. Unrecognised values are
|
|
463
|
+
* ignored (the default/env value is kept).
|
|
464
|
+
*/
|
|
465
|
+
protocol?: string;
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* `service.name` resource attribute.
|
|
469
|
+
* Unset defers to `CQLITE_OTEL_SERVICE_NAME`, then `cqlite`.
|
|
470
|
+
*/
|
|
471
|
+
serviceName?: string;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* `service.version` resource attribute.
|
|
475
|
+
* Unset defers to `CQLITE_OTEL_SERVICE_VERSION`, then the crate version.
|
|
476
|
+
*/
|
|
477
|
+
serviceVersion?: string;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Trace-ID-ratio sampling probability in `[0.0, 1.0]` (clamped; non-finite
|
|
481
|
+
* values fall back to full sampling).
|
|
482
|
+
* Unset defers to `CQLITE_OTEL_SAMPLING_RATIO`, then `1.0`.
|
|
483
|
+
*/
|
|
484
|
+
samplingRatio?: number;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Exporter export timeout in milliseconds.
|
|
488
|
+
* Unset defers to `CQLITE_OTEL_TIMEOUT_MS`, then `10000`.
|
|
489
|
+
*/
|
|
490
|
+
timeoutMs?: number;
|
|
377
491
|
}
|
|
378
492
|
|
|
379
493
|
// ============================================================================
|
|
@@ -465,6 +579,34 @@ export interface MaintenanceReport {
|
|
|
465
579
|
pendingCompaction: boolean;
|
|
466
580
|
}
|
|
467
581
|
|
|
582
|
+
/**
|
|
583
|
+
* Report returned by `Database.refresh()`.
|
|
584
|
+
*
|
|
585
|
+
* Describes what an explicit directory refresh applied to the database's held
|
|
586
|
+
* SSTable reader set: newly present generations become queryable, removed
|
|
587
|
+
* generations stop being queried, and unchanged generations keep their warm
|
|
588
|
+
* parsed state (they are not re-parsed).
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* const report = await db.refresh();
|
|
593
|
+
* console.log(
|
|
594
|
+
* `scanned ${report.tablesScanned} tables, ` +
|
|
595
|
+
* `+${report.readersAdded}/-${report.readersRemoved} readers`
|
|
596
|
+
* );
|
|
597
|
+
* ```
|
|
598
|
+
*/
|
|
599
|
+
export interface RefreshReport {
|
|
600
|
+
/** Number of distinct logical tables present after the refresh. */
|
|
601
|
+
tablesScanned: number;
|
|
602
|
+
|
|
603
|
+
/** Number of SSTable generations newly opened and made queryable. */
|
|
604
|
+
readersAdded: number;
|
|
605
|
+
|
|
606
|
+
/** Number of SSTable generations dropped from the reader set. */
|
|
607
|
+
readersRemoved: number;
|
|
608
|
+
}
|
|
609
|
+
|
|
468
610
|
/**
|
|
469
611
|
* Configuration for streaming query execution.
|
|
470
612
|
*
|
|
@@ -649,7 +791,8 @@ export type ErrorCode =
|
|
|
649
791
|
| 'CONSTRAINT' // Constraint violations
|
|
650
792
|
| 'TRANSACTION' // Transaction errors
|
|
651
793
|
| 'PLATFORM' // Platform-specific errors (WASM)
|
|
652
|
-
| 'INTERNAL'
|
|
794
|
+
| 'INTERNAL' // Internal errors
|
|
795
|
+
| 'CANCELLED'; // Cooperative scan cancellation (issue #2264 — never 'IO')
|
|
653
796
|
|
|
654
797
|
/**
|
|
655
798
|
* Error category names for CQLite errors.
|
|
@@ -671,7 +814,8 @@ export type ErrorCategory =
|
|
|
671
814
|
| 'Constraint'
|
|
672
815
|
| 'Transaction'
|
|
673
816
|
| 'Platform'
|
|
674
|
-
| 'Internal'
|
|
817
|
+
| 'Internal'
|
|
818
|
+
| 'Cancelled';
|
|
675
819
|
|
|
676
820
|
/**
|
|
677
821
|
* CQLite error interface.
|
|
@@ -831,24 +975,45 @@ export declare class Database {
|
|
|
831
975
|
static open(dataDir: string, options?: DatabaseOptions): Promise<Database>;
|
|
832
976
|
|
|
833
977
|
/**
|
|
834
|
-
* Execute a CQL query and return results as JSON-
|
|
978
|
+
* Execute a CQL query and return results as legacy JSON-serialized values.
|
|
979
|
+
*
|
|
980
|
+
* **DEPRECATED — removed in the next major. Use {@link Database.executeNative} instead.**
|
|
981
|
+
*
|
|
982
|
+
* ## ⚠️ Lossy legacy encodings and correctness hazards
|
|
983
|
+
*
|
|
984
|
+
* `execute()` routes every value through a legacy JSON encoder. Several CQL
|
|
985
|
+
* types come back in a lossy or bespoke encoding that no caller can round-trip
|
|
986
|
+
* and that differs from the native type `executeNative()` returns:
|
|
835
987
|
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
988
|
+
* - **`blob` → base64 `string`** (not a `Buffer`).
|
|
989
|
+
* - **`timestamp` → ISO-8601 `string`** (not a `Date`).
|
|
990
|
+
* - **`varint` → `"0x{hex}"` string.** Two's-complement big-endian hex.
|
|
991
|
+
* Example: 127 -> `"0x7f"`, -1 -> `"0xff"`, 256 -> `"0x0100"`.
|
|
992
|
+
* - **`decimal` → `"decimal:{scale}:0x{hex}"` string.** Example: 1.23
|
|
993
|
+
* (scale=2, unscaled=123) -> `"decimal:2:0x7b"`.
|
|
994
|
+
* - **`date` → `number`** (days since epoch); **`time` → `number`**
|
|
995
|
+
* (nanoseconds since midnight).
|
|
839
996
|
*
|
|
840
|
-
*
|
|
997
|
+
* It is also **slower** than `executeNative()`: it converts each value to JSON
|
|
998
|
+
* off the JS main thread, then converts that JSON to JS values on-loop — a
|
|
999
|
+
* double conversion `executeNative()` avoids.
|
|
841
1000
|
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
1001
|
+
* NOTE on precision: with this napi build (BigInt support), `bigint`/`counter`
|
|
1002
|
+
* are currently returned as an exact JS `BigInt`, so a value above 2^53 is
|
|
1003
|
+
* **not** presently rounded. Do not rely on this — the encoding is legacy and
|
|
1004
|
+
* unsupported; `executeNative()` is the contract. (Older docs claimed a >2^53
|
|
1005
|
+
* rounding loss; that is not observed on the current binding — issue #1457.)
|
|
1006
|
+
*
|
|
1007
|
+
* `executeNative()` returns native types with full fidelity (`BigInt`,
|
|
1008
|
+
* `Buffer`, `Date`, `Set`, `Map`) and is the supported path.
|
|
847
1009
|
*
|
|
848
1010
|
* @param query - CQL SELECT statement to execute
|
|
849
1011
|
* @returns Promise resolving to QueryResult with rows and metadata
|
|
850
1012
|
* @throws {CqliteError} If the query fails
|
|
851
|
-
* @deprecated Since 0.4.0. Use `executeNative()`
|
|
1013
|
+
* @deprecated Since 0.4.0; removed in the next major. Use `executeNative()`
|
|
1014
|
+
* for proper type fidelity — `execute()` returns blob/decimal/varint/
|
|
1015
|
+
* timestamp/date/time in lossy legacy encodings and is slower. Calling it
|
|
1016
|
+
* emits a one-time `DeprecationWarning`.
|
|
852
1017
|
*
|
|
853
1018
|
* @example
|
|
854
1019
|
* ```typescript
|
|
@@ -882,6 +1047,18 @@ export declare class Database {
|
|
|
882
1047
|
* - Native Buffer handling for binary data
|
|
883
1048
|
* - Native Set/Map operations
|
|
884
1049
|
*
|
|
1050
|
+
* ## Performance: O(rows) work on the event-loop thread
|
|
1051
|
+
*
|
|
1052
|
+
* The result set is scanned off the event loop, but every row is materialized
|
|
1053
|
+
* into a JS object on the event-loop thread (a napi `Env` is thread-bound, so
|
|
1054
|
+
* this work cannot be moved off-loop). It is therefore O(rows) of synchronous
|
|
1055
|
+
* on-loop work: a large result set will freeze timers, HTTP handlers, and
|
|
1056
|
+
* other callbacks for the duration of the burst. Prefer
|
|
1057
|
+
* {@link Database.executeStreaming} for result sets beyond ~a few thousand
|
|
1058
|
+
* rows. Result sets larger than `CQLITE_NODE_MAX_NATIVE_ROWS` (default
|
|
1059
|
+
* 100,000) are rejected with a typed error advising `executeStreaming`
|
|
1060
|
+
* instead of freezing the loop (issue #1442).
|
|
1061
|
+
*
|
|
885
1062
|
* @param query - CQL SELECT statement to execute
|
|
886
1063
|
* @returns Promise resolving to NativeQueryResult with native typed rows
|
|
887
1064
|
* @throws {CqliteError} If the query fails
|
|
@@ -917,6 +1094,35 @@ export declare class Database {
|
|
|
917
1094
|
*/
|
|
918
1095
|
getStats(): Promise<DatabaseStats>;
|
|
919
1096
|
|
|
1097
|
+
/**
|
|
1098
|
+
* Re-discover the data directory and apply changes to the held reader set.
|
|
1099
|
+
*
|
|
1100
|
+
* A `Database` is a snapshot at `open()`: a Cassandra flush/compaction (or a
|
|
1101
|
+
* CQLite `--flush`) may add or remove SSTable generations under a warm handle,
|
|
1102
|
+
* and those changes become queryable only after an explicit `refresh()`. This
|
|
1103
|
+
* re-runs the same TOC/filename-based discovery `open()` used (no content
|
|
1104
|
+
* sniffing, no heuristics) and applies the diff:
|
|
1105
|
+
* - newly present generations become queryable,
|
|
1106
|
+
* - removed generations stop being queried,
|
|
1107
|
+
* - unchanged generations keep their warm parsed Index/Statistics/bloom state.
|
|
1108
|
+
*
|
|
1109
|
+
* In-flight queries are never affected: a scan already running completes
|
|
1110
|
+
* against the pre-refresh set; a query issued after this Promise resolves sees
|
|
1111
|
+
* the post-refresh set. The refresh is atomic and fail-closed — if any newly
|
|
1112
|
+
* discovered generation fails to open (e.g. a corrupt `Statistics.db`), the
|
|
1113
|
+
* Promise rejects and the previously held reader set is left unchanged.
|
|
1114
|
+
*
|
|
1115
|
+
* @returns Promise resolving to a RefreshReport with the applied counts
|
|
1116
|
+
* @throws {CqliteError} If the database is closed or a new generation fails to open
|
|
1117
|
+
*
|
|
1118
|
+
* @example
|
|
1119
|
+
* ```typescript
|
|
1120
|
+
* const report = await db.refresh();
|
|
1121
|
+
* console.log(`+${report.readersAdded}/-${report.readersRemoved} readers`);
|
|
1122
|
+
* ```
|
|
1123
|
+
*/
|
|
1124
|
+
refresh(): Promise<RefreshReport>;
|
|
1125
|
+
|
|
920
1126
|
/**
|
|
921
1127
|
* Close the database and release resources.
|
|
922
1128
|
*
|
|
@@ -952,6 +1158,17 @@ export declare class Database {
|
|
|
952
1158
|
* - `bufferSize`: 1024 rows in flight (~1MB)
|
|
953
1159
|
* - `chunkSize`: 10,000 rows per fetch chunk (~10MB)
|
|
954
1160
|
*
|
|
1161
|
+
* Concurrency caveat: each `next()` fetches a batch of `K = bufferSize` rows
|
|
1162
|
+
* on a libuv threadpool thread, so N concurrent streams can each occupy a
|
|
1163
|
+
* libuv threadpool thread for the duration of a batch fetch. Heavy concurrent
|
|
1164
|
+
* `fs`/`crypto` work in the same process may therefore see added latency until
|
|
1165
|
+
* the follow-up (cqlite#1901) lands, which moves streaming off the libuv pool
|
|
1166
|
+
* onto the tokio runtime.
|
|
1167
|
+
*
|
|
1168
|
+
* Error caveat: if an error occurs mid-stream, rows already read in the
|
|
1169
|
+
* in-flight batch (up to `bufferSize`) are not delivered — the iterator
|
|
1170
|
+
* rejects with the error (errors are terminal).
|
|
1171
|
+
*
|
|
955
1172
|
* @param query - CQL SELECT statement to execute
|
|
956
1173
|
* @param config - Optional StreamingConfig for buffer/chunk sizes
|
|
957
1174
|
* @returns StreamingResult async iterable (iteration triggers query execution)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cqlite/node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Node.js bindings for CQLite - read Apache Cassandra 5.0 SSTables without cluster dependencies",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"index.js",
|
|
19
|
-
"index.d.ts",
|
|
20
19
|
"lib",
|
|
21
20
|
"*.node",
|
|
22
21
|
"README.md",
|
|
@@ -27,13 +26,13 @@
|
|
|
27
26
|
"access": "public"
|
|
28
27
|
},
|
|
29
28
|
"scripts": {
|
|
30
|
-
"build": "napi build --platform --release --features write-support",
|
|
29
|
+
"build": "napi build --platform --profile release-unwind --features write-support",
|
|
31
30
|
"postbuild": "node scripts/generate-loader.mjs",
|
|
32
31
|
"build:debug": "napi build --platform --features write-support",
|
|
33
32
|
"pretest": "node scripts/generate-loader.mjs",
|
|
34
|
-
"test": "jest",
|
|
35
|
-
"test:watch": "jest --watch",
|
|
36
|
-
"test:coverage": "jest --coverage",
|
|
33
|
+
"test": "node --expose-gc ./node_modules/jest/bin/jest.js",
|
|
34
|
+
"test:watch": "node --expose-gc ./node_modules/jest/bin/jest.js --watch",
|
|
35
|
+
"test:coverage": "node --expose-gc ./node_modules/jest/bin/jest.js --coverage",
|
|
37
36
|
"test:parity": "jest parity.test.js --testTimeout=60000",
|
|
38
37
|
"typecheck": "tsc --noEmit -p examples/tsconfig.json",
|
|
39
38
|
"examples": "ts-node examples/basic-query.ts",
|