@blamejs/core 0.4.12 → 0.4.13

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/CHANGELOG.md CHANGED
@@ -8,6 +8,7 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.4.x
10
10
 
11
+ - **0.4.12** (2026-04-30) — b.log: multi-sink output with per-sink level filtering
11
12
  - **0.4.11** (2026-04-30) — b.cache: bytes-cap eviction, sliding TTL, tag invalidation
12
13
  - **0.4.10** (2026-04-30) — bodyParser multipart: fileFilter + per-field maxBytes/mimeTypes
13
14
  - **0.4.9** (2026-04-30) — Origin-Agent-Cluster + DNS-Prefetch-Control headers; b.auth.lockout primitive
package/lib/db-query.js CHANGED
@@ -184,6 +184,37 @@ class Query {
184
184
  return out;
185
185
  }
186
186
 
187
+ // Streaming counterpart to all(). Each row is auto-unsealed against
188
+ // the bound table's sealedFields registration before it lands in the
189
+ // operator's pipeline. For large result sets (audit exports, backup
190
+ // table dumps) this avoids materializing the full rowset in memory.
191
+ stream() {
192
+ var sql = "SELECT " + this._projection() + ' FROM "' + this._table + '"' +
193
+ this._whereClause() + this._orderLimitOffset();
194
+ var stmt = this._db.prepare(sql);
195
+ var table = this._table;
196
+ var iter;
197
+ var Readable = require("node:stream").Readable;
198
+ try { iter = stmt.iterate.apply(stmt, this._whereParams); }
199
+ catch (e) {
200
+ var r = new Readable({ objectMode: true, read: function () {} });
201
+ setImmediate(function () { r.destroy(e); });
202
+ return r;
203
+ }
204
+ return new Readable({
205
+ objectMode: true,
206
+ read: function () {
207
+ try {
208
+ var step = iter.next();
209
+ if (step.done) { this.push(null); return; }
210
+ this.push(cryptoField.unsealRow(table, step.value));
211
+ } catch (e) {
212
+ this.destroy(e);
213
+ }
214
+ },
215
+ });
216
+ }
217
+
187
218
  count() {
188
219
  var sql = 'SELECT COUNT(*) AS n FROM "' + this._table + '"' + this._whereClause();
189
220
  var stmt = this._db.prepare(sql);
package/lib/db.js CHANGED
@@ -32,6 +32,8 @@
32
32
  *
33
33
  * db.from(tableName) → Query (chainable)
34
34
  * db.prepare(sql) → SQLite Statement (raw escape hatch)
35
+ * db.stream(sql, ...params, opts?) → Readable (object-mode rows;
36
+ * opts.table enables auto-unseal)
35
37
  * db.runSql(sql) → raw SQL execution (DDL, BEGIN/COMMIT)
36
38
  * db.transaction(function (db) {…}) → wraps in BEGIN/COMMIT/ROLLBACK
37
39
  * db.hashFor(table, field, value) → derived-hash lookup helper
@@ -746,6 +748,66 @@ function prepare(sql) {
746
748
  return database.prepare(sql);
747
749
  }
748
750
 
751
+ // stream — Readable in object mode that yields rows as node:sqlite's
752
+ // iterate() produces them. Unlike all(), the engine doesn't materialize
753
+ // the result set in memory before the first row arrives, so audit
754
+ // exports / backup table dumps / large reports can process millions of
755
+ // rows without OOM pressure.
756
+ //
757
+ // Optional opts.table enables auto-unseal of sealed columns via the
758
+ // table's registered cryptoField schema. Raw / aggregate queries omit
759
+ // it. Mid-iteration prepare()-bound errors propagate as 'error' events.
760
+ function stream(sql) {
761
+ _requireInit();
762
+ var opts = null;
763
+ var params;
764
+ // Last arg may be a plain {table?} options object; everything else
765
+ // is a SQL parameter binding. node:sqlite accepts numbers, strings,
766
+ // bigints, Buffers, and null — plain objects can only be opts.
767
+ var args = Array.prototype.slice.call(arguments, 1);
768
+ if (args.length > 0) {
769
+ var last = args[args.length - 1];
770
+ var isOptsShape = last !== null && typeof last === "object" &&
771
+ !Buffer.isBuffer(last) && !Array.isArray(last) &&
772
+ typeof last.length !== "number"; // exclude TypedArray-shapes
773
+ if (isOptsShape) {
774
+ opts = last;
775
+ params = args.slice(0, -1);
776
+ } else {
777
+ params = args;
778
+ }
779
+ } else {
780
+ params = [];
781
+ }
782
+ var table = opts && typeof opts.table === "string" ? opts.table : null;
783
+ var unseal = table ? cryptoField : null;
784
+
785
+ var Readable = require("node:stream").Readable;
786
+ var stmt;
787
+ var iter;
788
+ try {
789
+ stmt = database.prepare(sql);
790
+ iter = stmt.iterate.apply(stmt, params);
791
+ } catch (e) {
792
+ var r = new Readable({ objectMode: true, read: function () {} });
793
+ setImmediate(function () { r.destroy(e); });
794
+ return r;
795
+ }
796
+ return new Readable({
797
+ objectMode: true,
798
+ read: function () {
799
+ try {
800
+ var step = iter.next();
801
+ if (step.done) { this.push(null); return; }
802
+ var row = step.value;
803
+ this.push(unseal ? unseal.unsealRow(table, row) : row);
804
+ } catch (e) {
805
+ this.destroy(e);
806
+ }
807
+ },
808
+ });
809
+ }
810
+
749
811
  function execRaw(sql) {
750
812
  _requireInit();
751
813
  return runSql(database, sql);
@@ -946,6 +1008,7 @@ module.exports = {
946
1008
  init: init,
947
1009
  from: from,
948
1010
  prepare: prepare,
1011
+ stream: stream,
949
1012
  runSql: execRaw,
950
1013
  // SQLite multi-statement helper alias matching the node:sqlite
951
1014
  // module's shape. Operator migration / seeder files that received
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",