@rotorsoft/act-sqlite 1.22.3 → 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.
@@ -126,37 +126,12 @@ export declare function streamPatternToGlob(input: string): string;
126
126
  */
127
127
  export declare class SqliteStore implements Store {
128
128
  private client;
129
- /**
130
- * Memoized key resolver for the optional `pii_encryption` envelope.
131
- * Initialized in the constructor when encryption is configured;
132
- * `undefined` otherwise. The resolver caches the operator's key on
133
- * first use — rotation means restarting the store with a fresh
134
- * provider.
135
- */
136
129
  private readonly _resolve_pii_key;
137
130
  constructor(config: SqliteConfig);
138
- /**
139
- * Write-side pii encoder: encrypts when `pii_encryption` is configured,
140
- * stringifies for the TEXT column either way. `null` passes through so
141
- * `forget_pii` semantics survive intact (the row format skips the
142
- * column entirely on a `NULL` write).
143
- *
144
- * @internal
145
- */
146
131
  private _stringify_pii_for_write;
147
- /**
148
- * Read-side pii decoder: parses the TEXT column, and when
149
- * `pii_encryption` is configured, transparently decrypts any value
150
- * that came back as a JSON string. Plaintext writes deserialize to
151
- * objects and pass through — which is what makes mixed-data
152
- * rollouts (some pre-encryption rows, some post-) read cleanly.
153
- *
154
- * @internal
155
- */
156
132
  private _parse_pii_from_read;
157
133
  seed(): Promise<void>;
158
134
  drop(): Promise<void>;
159
- /** One write transaction: any failure rolls back and throws a {@link StoreError} naming the operation. */
160
135
  private _tx;
161
136
  dispose(): Promise<void>;
162
137
  commit<E extends Schemas>(stream: string, msgs: Message<E, keyof E>[], meta: EventMeta, expectedVersion?: number): Promise<Committed<E, keyof E>[]>;
@@ -170,23 +145,7 @@ export declare class SqliteStore implements Store {
170
145
  ack(leases: Lease[]): Promise<Lease[]>;
171
146
  block(leases: BlockedLease[]): Promise<BlockedLease[]>;
172
147
  defer(input: string[] | StreamFilter, deferred_at: number): Promise<number>;
173
- /**
174
- * Runs `UPDATE streams <set>` on the streams named by `input`, in one
175
- * write transaction (`_tx`) that rolls back on failure. An explicit list is
176
- * de-duplicated, so a repeated name counts once (matching PG's set-based
177
- * `stream = ANY(...)`), and updated one name per statement, so a long list
178
- * never meets SQLite's bound-parameter limit. `set` and `where` bind
179
- * `params` in order; libSQL `?` placeholders are positional and can't be
180
- * reused, so a value used twice is passed twice.
181
- *
182
- * @returns Count of rows updated.
183
- */
184
148
  private _update;
185
- /**
186
- * Translate a {@link StreamFilter} to a SQLite `WHERE` clause fragment
187
- * plus positional args. Returns `"1"` (always true) when empty so
188
- * callers can compose it unconditionally.
189
- */
190
149
  private _filter_clause;
191
150
  reset(input: string[] | StreamFilter): Promise<number>;
192
151
  unblock(input: string[] | StreamFilter): Promise<number>;
@@ -216,16 +175,7 @@ export declare class SqliteStore implements Store {
216
175
  * since SQLite has no native array type.
217
176
  */
218
177
  query_stats<E extends Schemas>(input: string[] | Pick<StreamFilter, "stream" | "stream_exact">, options?: QueryStatsOptions<E>): Promise<Map<string, StreamStats<E>>>;
219
- /**
220
- * Cheap path — head (and optional tail) via ROW_NUMBER() over the
221
- * `(stream, version)` unique index. Parallel queries when tail set.
222
- */
223
178
  private _query_stats_heads_only;
224
- /**
225
- * Full-scan path — one CTE-based query with per-stream `COUNT(*)` and
226
- * `json_group_object(name, n)`. Heads (and optional tails) ride free
227
- * on the same scan.
228
- */
229
179
  private _query_stats_full_scan;
230
180
  prioritize(filter: StreamFilter, priority: number): Promise<number>;
231
181
  truncate(targets: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -97,13 +97,11 @@ function streamPatternToGlob(input) {
97
97
  }
98
98
  var SqliteStore = class {
99
99
  client;
100
- /**
101
- * Memoized key resolver for the optional `pii_encryption` envelope.
102
- * Initialized in the constructor when encryption is configured;
103
- * `undefined` otherwise. The resolver caches the operator's key on
104
- * first use — rotation means restarting the store with a fresh
105
- * provider.
106
- */
100
+ // Memoized key resolver for the optional `pii_encryption` envelope.
101
+ // Initialized in the constructor when encryption is configured;
102
+ // `undefined` otherwise. The resolver caches the operator's key on
103
+ // first use — rotation means restarting the store with a fresh
104
+ // provider.
107
105
  _resolve_pii_key;
108
106
  constructor(config) {
109
107
  this.client = (0, import_client.createClient)({
@@ -112,14 +110,10 @@ var SqliteStore = class {
112
110
  });
113
111
  this._resolve_pii_key = config.pii_encryption ? (0, import_act_crypto.makeKeyResolver)(config.pii_encryption) : void 0;
114
112
  }
115
- /**
116
- * Write-side pii encoder: encrypts when `pii_encryption` is configured,
117
- * stringifies for the TEXT column either way. `null` passes through so
118
- * `forget_pii` semantics survive intact (the row format skips the
119
- * column entirely on a `NULL` write).
120
- *
121
- * @internal
122
- */
113
+ // Write-side pii encoder: encrypts when `pii_encryption` is configured,
114
+ // stringifies for the TEXT column either way. `null` passes through so
115
+ // `forget_pii` semantics survive intact (the row format skips the
116
+ // column entirely on a `NULL` write).
123
117
  async _stringify_pii_for_write(pii) {
124
118
  if (pii == null) return null;
125
119
  if (this._resolve_pii_key) {
@@ -127,15 +121,11 @@ var SqliteStore = class {
127
121
  }
128
122
  return JSON.stringify(pii);
129
123
  }
130
- /**
131
- * Read-side pii decoder: parses the TEXT column, and when
132
- * `pii_encryption` is configured, transparently decrypts any value
133
- * that came back as a JSON string. Plaintext writes deserialize to
134
- * objects and pass through — which is what makes mixed-data
135
- * rollouts (some pre-encryption rows, some post-) read cleanly.
136
- *
137
- * @internal
138
- */
124
+ // Read-side pii decoder: parses the TEXT column, and when
125
+ // `pii_encryption` is configured, transparently decrypts any value
126
+ // that came back as a JSON string. Plaintext writes deserialize to
127
+ // objects and pass through — which is what makes mixed-data
128
+ // rollouts (some pre-encryption rows, some post-) read cleanly.
139
129
  async _parse_pii_from_read(raw) {
140
130
  if (raw == null) return null;
141
131
  const parsed = parse_json(raw);
@@ -271,7 +261,7 @@ var SqliteStore = class {
271
261
  await this.client.execute("DROP TABLE IF EXISTS streams");
272
262
  await this.client.execute("DROP TABLE IF EXISTS correlated");
273
263
  }
274
- /** One write transaction: any failure rolls back and throws a {@link StoreError} naming the operation. */
264
+ // One write transaction: any failure rolls back and throws a {@link StoreError} naming the operation.
275
265
  async _tx(operation, work) {
276
266
  const tx = await this.client.transaction("write");
277
267
  try {
@@ -671,17 +661,15 @@ var SqliteStore = class {
671
661
  at_iso
672
662
  ]);
673
663
  }
674
- /**
675
- * Runs `UPDATE streams <set>` on the streams named by `input`, in one
676
- * write transaction (`_tx`) that rolls back on failure. An explicit list is
677
- * de-duplicated, so a repeated name counts once (matching PG's set-based
678
- * `stream = ANY(...)`), and updated one name per statement, so a long list
679
- * never meets SQLite's bound-parameter limit. `set` and `where` bind
680
- * `params` in order; libSQL `?` placeholders are positional and can't be
681
- * reused, so a value used twice is passed twice.
682
- *
683
- * @returns Count of rows updated.
684
- */
664
+ // Runs `UPDATE streams <set>` on the streams named by `input`, in one
665
+ // write transaction (`_tx`) that rolls back on failure. An explicit list is
666
+ // de-duplicated, so a repeated name counts once (matching PG's set-based
667
+ // `stream = ANY(...)`), and updated one name per statement, so a long list
668
+ // never meets SQLite's bound-parameter limit. `set` and `where` bind
669
+ // `params` in order; libSQL `?` placeholders are positional and can't be
670
+ // reused, so a value used twice is passed twice.
671
+ //
672
+ // @returns Count of rows updated.
685
673
  _update(operation, input, set, params = [], where) {
686
674
  const selections = Array.isArray(input) ? [...new Set(input)].map((stream) => ({
687
675
  clause: "stream = ?",
@@ -699,11 +687,9 @@ var SqliteStore = class {
699
687
  return count;
700
688
  });
701
689
  }
702
- /**
703
- * Translate a {@link StreamFilter} to a SQLite `WHERE` clause fragment
704
- * plus positional args. Returns `"1"` (always true) when empty so
705
- * callers can compose it unconditionally.
706
- */
690
+ // Translate a {@link StreamFilter} to a SQLite `WHERE` clause fragment
691
+ // plus positional args. Returns `"1"` (always true) when empty so
692
+ // callers can compose it unconditionally.
707
693
  _filter_clause(filter) {
708
694
  const conditions = [];
709
695
  const args = [];
@@ -880,10 +866,8 @@ var SqliteStore = class {
880
866
  limit
881
867
  );
882
868
  }
883
- /**
884
- * Cheap path — head (and optional tail) via ROW_NUMBER() over the
885
- * `(stream, version)` unique index. Parallel queries when tail set.
886
- */
869
+ // Cheap path — head (and optional tail) via ROW_NUMBER() over the
870
+ // `(stream, version)` unique index. Parallel queries when tail set.
887
871
  async _query_stats_heads_only(from_clause, where_clause, args, want_tail, limit) {
888
872
  const cols = `e.id, e.stream, e.version, e.name, e.data, e.created, e.meta`;
889
873
  const limit_clause = limit !== void 0 ? " LIMIT ?" : "";
@@ -923,11 +907,9 @@ var SqliteStore = class {
923
907
  }
924
908
  return out;
925
909
  }
926
- /**
927
- * Full-scan path — one CTE-based query with per-stream `COUNT(*)` and
928
- * `json_group_object(name, n)`. Heads (and optional tails) ride free
929
- * on the same scan.
930
- */
910
+ // Full-scan path — one CTE-based query with per-stream `COUNT(*)` and
911
+ // `json_group_object(name, n)`. Heads (and optional tails) ride free
912
+ // on the same scan.
931
913
  async _query_stats_full_scan(from_clause, where_clause, args, want_tail, want_count, want_names, limit) {
932
914
  const tail_cte = want_tail ? `, tails AS (
933
915
  SELECT * FROM (