@rotorsoft/act-sqlite 1.22.2 → 1.22.4

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 CHANGED
@@ -79,13 +79,11 @@ function streamPatternToGlob(input) {
79
79
  }
80
80
  var SqliteStore = class {
81
81
  client;
82
- /**
83
- * Memoized key resolver for the optional `pii_encryption` envelope.
84
- * Initialized in the constructor when encryption is configured;
85
- * `undefined` otherwise. The resolver caches the operator's key on
86
- * first use — rotation means restarting the store with a fresh
87
- * provider.
88
- */
82
+ // Memoized key resolver for the optional `pii_encryption` envelope.
83
+ // Initialized in the constructor when encryption is configured;
84
+ // `undefined` otherwise. The resolver caches the operator's key on
85
+ // first use — rotation means restarting the store with a fresh
86
+ // provider.
89
87
  _resolve_pii_key;
90
88
  constructor(config) {
91
89
  this.client = createClient({
@@ -94,14 +92,10 @@ var SqliteStore = class {
94
92
  });
95
93
  this._resolve_pii_key = config.pii_encryption ? makeKeyResolver(config.pii_encryption) : void 0;
96
94
  }
97
- /**
98
- * Write-side pii encoder: encrypts when `pii_encryption` is configured,
99
- * stringifies for the TEXT column either way. `null` passes through so
100
- * `forget_pii` semantics survive intact (the row format skips the
101
- * column entirely on a `NULL` write).
102
- *
103
- * @internal
104
- */
95
+ // Write-side pii encoder: encrypts when `pii_encryption` is configured,
96
+ // stringifies for the TEXT column either way. `null` passes through so
97
+ // `forget_pii` semantics survive intact (the row format skips the
98
+ // column entirely on a `NULL` write).
105
99
  async _stringify_pii_for_write(pii) {
106
100
  if (pii == null) return null;
107
101
  if (this._resolve_pii_key) {
@@ -109,15 +103,11 @@ var SqliteStore = class {
109
103
  }
110
104
  return JSON.stringify(pii);
111
105
  }
112
- /**
113
- * Read-side pii decoder: parses the TEXT column, and when
114
- * `pii_encryption` is configured, transparently decrypts any value
115
- * that came back as a JSON string. Plaintext writes deserialize to
116
- * objects and pass through — which is what makes mixed-data
117
- * rollouts (some pre-encryption rows, some post-) read cleanly.
118
- *
119
- * @internal
120
- */
106
+ // Read-side pii decoder: parses the TEXT column, and when
107
+ // `pii_encryption` is configured, transparently decrypts any value
108
+ // that came back as a JSON string. Plaintext writes deserialize to
109
+ // objects and pass through — which is what makes mixed-data
110
+ // rollouts (some pre-encryption rows, some post-) read cleanly.
121
111
  async _parse_pii_from_read(raw) {
122
112
  if (raw == null) return null;
123
113
  const parsed = parse_json(raw);
@@ -253,7 +243,7 @@ var SqliteStore = class {
253
243
  await this.client.execute("DROP TABLE IF EXISTS streams");
254
244
  await this.client.execute("DROP TABLE IF EXISTS correlated");
255
245
  }
256
- /** One write transaction: any failure rolls back and throws a {@link StoreError} naming the operation. */
246
+ // One write transaction: any failure rolls back and throws a {@link StoreError} naming the operation.
257
247
  async _tx(operation, work) {
258
248
  const tx = await this.client.transaction("write");
259
249
  try {
@@ -649,32 +639,25 @@ var SqliteStore = class {
649
639
  // Cleared by ack/block/reset/unblock. See {@link Store.defer}.
650
640
  async defer(input, deferred_at) {
651
641
  const at_iso = new Date(deferred_at).toISOString();
652
- try {
653
- return await this._update(input, "SET deferred_at = ?, retry = -1", [
654
- at_iso
655
- ]);
656
- } catch (e) {
657
- throw new StoreError("defer", { cause: e });
658
- }
642
+ return this._update("defer", input, "SET deferred_at = ?, retry = -1", [
643
+ at_iso
644
+ ]);
659
645
  }
660
- /**
661
- * Runs `UPDATE streams <set>` on the streams named by `input`, in one
662
- * write transaction that rolls back on failure. An explicit list is
663
- * de-duplicated, so a repeated name counts once (matching PG's set-based
664
- * `stream = ANY(...)`), and updated one name per statement, so a long list
665
- * never meets SQLite's bound-parameter limit. `set` and `where` bind
666
- * `params` in order; libSQL `?` placeholders are positional and can't be
667
- * reused, so a value used twice is passed twice.
668
- *
669
- * @returns Count of rows updated.
670
- */
671
- async _update(input, set, params = [], where) {
646
+ // Runs `UPDATE streams <set>` on the streams named by `input`, in one
647
+ // write transaction (`_tx`) that rolls back on failure. An explicit list is
648
+ // de-duplicated, so a repeated name counts once (matching PG's set-based
649
+ // `stream = ANY(...)`), and updated one name per statement, so a long list
650
+ // never meets SQLite's bound-parameter limit. `set` and `where` bind
651
+ // `params` in order; libSQL `?` placeholders are positional and can't be
652
+ // reused, so a value used twice is passed twice.
653
+ //
654
+ // @returns Count of rows updated.
655
+ _update(operation, input, set, params = [], where) {
672
656
  const selections = Array.isArray(input) ? [...new Set(input)].map((stream) => ({
673
657
  clause: "stream = ?",
674
658
  args: [stream]
675
659
  })) : [this._filter_clause(input)];
676
- const tx = await this.client.transaction("write");
677
- try {
660
+ return this._tx(operation, async (tx) => {
678
661
  let count = 0;
679
662
  for (const { clause, args } of selections) {
680
663
  const r = await tx.execute({
@@ -683,18 +666,12 @@ var SqliteStore = class {
683
666
  });
684
667
  count += r.rowsAffected;
685
668
  }
686
- await tx.commit();
687
669
  return count;
688
- } catch (e) {
689
- await tx.rollback();
690
- throw e;
691
- }
670
+ });
692
671
  }
693
- /**
694
- * Translate a {@link StreamFilter} to a SQLite `WHERE` clause fragment
695
- * plus positional args. Returns `"1"` (always true) when empty so
696
- * callers can compose it unconditionally.
697
- */
672
+ // Translate a {@link StreamFilter} to a SQLite `WHERE` clause fragment
673
+ // plus positional args. Returns `"1"` (always true) when empty so
674
+ // callers can compose it unconditionally.
698
675
  _filter_clause(filter) {
699
676
  const conditions = [];
700
677
  const args = [];
@@ -730,6 +707,7 @@ var SqliteStore = class {
730
707
  // --- reset: transactional, accepts names or filter ---
731
708
  reset(input) {
732
709
  return this._update(
710
+ "reset",
733
711
  input,
734
712
  `SET at = -1, retry = -1, blocked = 0, error = '',
735
713
  leased_by = NULL, leased_until = NULL, deferred_at = NULL`
@@ -742,6 +720,7 @@ var SqliteStore = class {
742
720
  // unblocked streams."
743
721
  unblock(input) {
744
722
  return this._update(
723
+ "unblock",
745
724
  Array.isArray(input) ? input : { ...input, blocked: void 0 },
746
725
  `SET retry = -1, blocked = 0, error = '',
747
726
  leased_by = NULL, leased_until = NULL, deferred_at = NULL`,
@@ -869,10 +848,8 @@ var SqliteStore = class {
869
848
  limit
870
849
  );
871
850
  }
872
- /**
873
- * Cheap path — head (and optional tail) via ROW_NUMBER() over the
874
- * `(stream, version)` unique index. Parallel queries when tail set.
875
- */
851
+ // Cheap path — head (and optional tail) via ROW_NUMBER() over the
852
+ // `(stream, version)` unique index. Parallel queries when tail set.
876
853
  async _query_stats_heads_only(from_clause, where_clause, args, want_tail, limit) {
877
854
  const cols = `e.id, e.stream, e.version, e.name, e.data, e.created, e.meta`;
878
855
  const limit_clause = limit !== void 0 ? " LIMIT ?" : "";
@@ -912,11 +889,9 @@ var SqliteStore = class {
912
889
  }
913
890
  return out;
914
891
  }
915
- /**
916
- * Full-scan path — one CTE-based query with per-stream `COUNT(*)` and
917
- * `json_group_object(name, n)`. Heads (and optional tails) ride free
918
- * on the same scan.
919
- */
892
+ // Full-scan path — one CTE-based query with per-stream `COUNT(*)` and
893
+ // `json_group_object(name, n)`. Heads (and optional tails) ride free
894
+ // on the same scan.
920
895
  async _query_stats_full_scan(from_clause, where_clause, args, want_tail, want_count, want_names, limit) {
921
896
  const tail_cte = want_tail ? `, tails AS (
922
897
  SELECT * FROM (
@@ -980,6 +955,7 @@ var SqliteStore = class {
980
955
  // --- prioritize: bulk priority update with filter ---
981
956
  prioritize(filter, priority) {
982
957
  return this._update(
958
+ "prioritize",
983
959
  filter,
984
960
  "SET priority = ?",
985
961
  [priority, priority],