@voltro/sql-sqlite 0.84.0 → 0.85.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/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ChangeEvent } from '@voltro/database';
2
2
  import { ChangeStrategy } from '@voltro/database';
3
- import { ConfigError } from 'effect';
4
- import { ConfigError as ConfigError_2 } from 'effect/ConfigError';
3
+ import { Config } from 'effect';
5
4
  import { ConnectionConfig } from '@voltro/database';
6
5
  import { Context } from 'effect';
7
6
  import { DataStore } from '@voltro/database';
@@ -17,13 +16,13 @@ import { RawSqlFragment } from '@voltro/database/sql';
17
16
  import { RetryDecision } from '@voltro/database';
18
17
  import { Row } from '@voltro/database';
19
18
  import { RowKey } from '@voltro/database';
20
- import { SqlClient } from '@effect/sql';
21
- import { SqlClient as SqlClient_2 } from '@effect/sql/SqlClient';
19
+ import { SqlClient } from 'effect/sql';
20
+ import { SqlClient as SqlClient_2 } from 'effect/sql/SqlClient';
22
21
  import { SqlDialect } from '@voltro/database';
23
- import { SqlError } from '@effect/sql';
24
- import { SqlError as SqlError_2 } from '@effect/sql/SqlError';
22
+ import { SqlError } from 'effect/sql';
23
+ import { SqlError as SqlError_2 } from 'effect/sql/SqlError';
25
24
  import { SqliteClient } from '@effect/sql-sqlite-node';
26
- import { TransactionConnection } from '@effect/sql/SqlClient';
25
+ import { TransactionConnection } from 'effect/sql/SqlClient';
27
26
  import { UpsertOptions } from '@voltro/database';
28
27
  import { WriteAttribution } from '@voltro/database';
29
28
 
@@ -62,7 +61,7 @@ export declare const sqliteRetryFilter: (err: unknown) => RetryDecision;
62
61
  * to the error channel — matching the cross-dialect `sqlLayer` shape in
63
62
  * `@voltro/database`).
64
63
  */
65
- declare type SqliteSqlLayer = Layer.Layer<SqliteClient.SqliteClient | SqlClient_2, ConfigError_2 | SqlError_2>;
64
+ declare type SqliteSqlLayer = Layer.Layer<SqliteClient.SqliteClient | SqlClient_2, Config.ConfigError | SqlError_2>;
66
65
 
67
66
  export declare class SqliteStore implements DataStore {
68
67
  private readonly sql;
@@ -199,7 +198,7 @@ export declare class SqliteStore implements DataStore {
199
198
  * Retry uses the injected `isRetryable` predicate — sqlite's
200
199
  * `SQLITE_BUSY` / `SQLITE_LOCKED`, or (Turso dialect) the MVCC
201
200
  * `"Write-write conflict"` from `BEGIN CONCURRENT`. A conflict can
202
- * surface from the COMMIT, which `@effect/sql` runs as `Effect.orDie`
201
+ * surface from the COMMIT, which `effect/sql` runs as `Effect.orDie`
203
202
  * → it arrives as a DEFECT, not a typed failure, and `Effect.retry`
204
203
  * does not retry defects. So we promote a retryable defect back to a
205
204
  * typed failure before the schedule sees it (and re-die on a genuine
@@ -243,6 +242,9 @@ export declare class SqliteStore implements DataStore {
243
242
  * defect-promotion in particular lived HERE and only here for a release, which
244
243
  * is why it is no longer a per-store decision. See `transactionOutcome.ts`.
245
244
  */
245
+ /** The key under which this client's transactions provide their pinned
246
+ * connection (per client in Effect 4). Views reach it through the parent. */
247
+ get transactionService(): Context.Service<TransactionConnection, TransactionConnection.Service>;
246
248
  private txnSpec;
247
249
  onChange(listener: (event: ChangeEvent) => void): () => void;
248
250
  /** Cross-instance reactivity seam — emit an externally-sourced event to
@@ -257,7 +259,7 @@ export declare class SqliteStore implements DataStore {
257
259
  }
258
260
 
259
261
  export declare interface SqliteStoreOptions {
260
- readonly sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError | SqlError.SqlError, never>;
262
+ readonly sqlLayer: Layer.Layer<SqlClient.SqlClient, Config.ConfigError | SqlError.SqlError, never>;
261
263
  readonly tracerLayer?: Layer.Layer<never, never, never>;
262
264
  /** Accepted for cross-dialect symmetry; ignored (always in-process). */
263
265
  readonly changeStrategy?: ChangeStrategy;
@@ -285,6 +287,6 @@ export declare interface SqliteStoreOptions {
285
287
  readonly fullText?: 'fts5' | 'like';
286
288
  }
287
289
 
288
- declare type TxnContext = Context.Tag.Service<typeof TransactionConnection>;
290
+ declare type TxnContext = TransactionConnection.Service;
289
291
 
290
292
  export { }
package/dist/index.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import { SqliteClient as e } from "@effect/sql-sqlite-node";
2
2
  import { Config as t, Context as n, Effect as r, Layer as i, ManagedRuntime as a, Option as o } from "effect";
3
- import { EagerCardinalityError as s, SQLITE_TRANSIENT_CODES as c, attachEagerLoads as l, attributionFields as u, bulkInsertLimitsFor as d, causeBranches as f, chunkRowsForInsert as p, coercePredicateForSqlite as m, compileEagerJson as h, compileJsonPatch as g, compilePredicate as _, compileRawFragment as v, compileRowProjection as y, compileSelect as b, decodeRowsFromSchema as x, encodeRowForSchema as S, externalChangeEvent as C, hasEagerLoads as ee, isTableReactive as w, jsonPatchAssignments as te, makeEagerFallbackReporter as T, makeTransactionAbortTracker as E, observeDbOp as D, qualifyTable as O, quoteIdent as k, raiseChangeListenerCeiling as A, recordsTable as j, requireTable as M, rowKeyColumns as N, runSavepoint as ne, runStoreTransaction as re, runWriteRecorders as ie, stampGeneratedId as P, stampGeneratedIds as F, upsertUpdatePatch as I, upsertUpdateValues as L, withCapturedAttribution as R } from "@voltro/database";
3
+ import { EagerCardinalityError as s, SHARED_TRANSACTION_SERVICE as c, SQLITE_TRANSIENT_CODES as l, attachEagerLoads as u, attributionFields as d, bulkInsertLimitsFor as f, causeBranches as p, chunkRowsForInsert as m, coercePredicateForSqlite as h, compileEagerJson as g, compileJsonPatch as _, compilePredicate as v, compileRawFragment as y, compileRowProjection as b, compileSelect as x, decodeRowsFromSchema as S, encodeRowForSchema as ee, externalChangeEvent as te, hasEagerLoads as C, isTableReactive as w, jsonPatchAssignments as T, makeEagerFallbackReporter as E, makeTransactionAbortTracker as D, observeDbOp as O, onTransaction as ne, qualifyTable as re, quoteIdent as ie, raiseChangeListenerCeiling as ae, recordsTable as k, requireTable as oe, rowKeyColumns as A, runSavepoint as j, runStoreTransaction as M, runWriteRecorders as N, stampGeneratedId as P, stampGeneratedIds as F, upsertUpdatePatch as I, upsertUpdateValues as L, withCapturedAttribution as R } from "@voltro/database";
4
4
  import { EventEmitter as z } from "node:events";
5
5
  import { createLogger as B } from "@voltro/logger";
6
- import { SqlClient as V, TransactionConnection as H } from "@effect/sql/SqlClient";
6
+ import { SqlClient as V } from "effect/sql/SqlClient";
7
7
  //#region src/sqlLayer.ts
8
- var U = (r) => e.layerConfig({
8
+ var H = (r) => e.layerConfig({
9
+ transactionService: t.succeed(c),
9
10
  filename: t.succeed(r.filename),
11
+ prepareCacheSize: t.succeed(0),
12
+ transactionMode: t.succeed("deferred"),
10
13
  ...r.readonly === void 0 ? {} : { readonly: t.succeed(r.readonly) }
11
- }).pipe(i.tap((t) => n.get(t, e.SqliteClient)`PRAGMA foreign_keys = ON`)), W = (e) => {
14
+ }).pipe(i.tap((t) => n.get(t, e.SqliteClient)`PRAGMA foreign_keys = ON`)), U = (e) => {
12
15
  if (e.url) {
13
16
  if (e.url === ":memory:") return { filename: ":memory:" };
14
17
  if (e.url.startsWith("file:")) return { filename: e.url.slice(5) };
@@ -16,32 +19,33 @@ var U = (r) => e.layerConfig({
16
19
  }
17
20
  if (e.database) return { filename: e.database };
18
21
  throw Error("@voltro/sql-sqlite: no filename supplied. Set DB_URL=file:./db.sqlite or DB_DATABASE=path/to/db.sqlite.");
19
- }, G = (e) => U(W(e)), K = c, q = (e) => {
22
+ }, W = (e) => H(U(e)), G = l, K = (e) => {
20
23
  let t = e;
21
24
  for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
22
- let e = t.code;
23
- if (typeof e == "string") return e;
25
+ let { code: e, errcode: n } = t;
26
+ if (typeof n == "number") return String(n);
27
+ if (typeof e == "string" && e !== "ERR_SQLITE_ERROR") return e;
24
28
  if (typeof e == "number") return String(e);
25
29
  t = t.cause;
26
30
  }
27
- }, J = (e) => f(e).some((e) => {
28
- let t = q(e);
29
- return t !== void 0 && K.has(t);
30
- }), Y = (e) => J(e) ? "retry" : "noRetry", X = B({ scope: "voltro:sqlite" }), Z = async (e) => {
31
+ }, q = (e) => p(e).some((e) => {
32
+ let t = K(e);
33
+ return t !== void 0 && G.has(t);
34
+ }), J = (e) => q(e) ? "retry" : "noRetry", Y = B({ scope: "voltro:sqlite" }), X = async (e) => {
31
35
  let t = e.tracerLayer ? i.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, n = a.make(t);
32
- return new se(await n.runPromise(V), n, null, void 0, e.isRetryable ?? J, e.systemName ?? "sqlite", e.wrapTransaction, e.fullText ?? "fts5");
33
- }, ae = (e) => e, Q = (e) => m(e), oe = (e) => e.predicate === void 0 || e.predicate === null ? e : {
36
+ return new le(await n.runPromise(V), n, null, void 0, e.isRetryable ?? q, e.systemName ?? "sqlite", e.wrapTransaction, e.fullText ?? "fts5");
37
+ }, se = (e) => e, Z = (e) => h(e), ce = (e) => e.predicate === void 0 || e.predicate === null ? e : {
34
38
  ...e,
35
- predicate: Q(e.predicate)
36
- }, $ = (e, t) => {
37
- let n = S(e, t, [
39
+ predicate: Z(e.predicate)
40
+ }, Q = (e, t) => {
41
+ let n = ee(e, t, [
38
42
  "json",
39
43
  "array",
40
44
  "decimal"
41
45
  ]), r = {};
42
46
  for (let [e, t] of Object.entries(n)) r[e] = t instanceof Date ? t.toISOString() : typeof t == "boolean" ? +!!t : t;
43
47
  return r;
44
- }, se = class e {
48
+ }, le = class e {
45
49
  sql;
46
50
  runtime;
47
51
  namespace;
@@ -52,8 +56,8 @@ var U = (r) => e.layerConfig({
52
56
  emitter;
53
57
  inflightTxns = 0;
54
58
  reportEagerFallback;
55
- constructor(e, t, n = null, r, i = J, a = "sqlite", o = ae, s = "fts5") {
56
- this.sql = e, this.runtime = t, this.namespace = n, this.isRetryable = i, this.systemName = a, this.wrapTransaction = o, this.fullText = s, this.emitter = r ?? new z(), A(this.emitter), this.reportEagerFallback = T(X);
59
+ constructor(e, t, n = null, r, i = q, a = "sqlite", o = se, s = "fts5") {
60
+ this.sql = e, this.runtime = t, this.namespace = n, this.isRetryable = i, this.systemName = a, this.wrapTransaction = o, this.fullText = s, this.emitter = r ?? new z(), ae(this.emitter), this.reportEagerFallback = E(Y);
57
61
  }
58
62
  withNamespace(t) {
59
63
  return t === this.namespace ? this : new e(this.sql, this.runtime, t, this.emitter, this.isRetryable, this.systemName, this.wrapTransaction, this.fullText);
@@ -68,23 +72,23 @@ var U = (r) => e.layerConfig({
68
72
  } : e;
69
73
  }
70
74
  nsT(e) {
71
- return O(this.namespace, e);
75
+ return re(this.namespace, e);
72
76
  }
73
77
  async attachNamespace(e, t) {
74
78
  let n = this.sql, r = t ?? `${e}.db`;
75
79
  await this.runtime.runPromise(n`ATTACH DATABASE ${r} AS ${n(e)}`);
76
80
  }
77
81
  async executeQuery(e, t, n) {
78
- let i = b(oe(this.withFullTextMode(e)), this.sql, this.namespace), a = t ? r.provideService(i, H, t) : i, o = await D(this.systemName, "select", () => this.runtime.runPromise(a));
79
- return x(o, e.table, "sqlite", e);
82
+ let i = x(ce(this.withFullTextMode(e)), this.sql, this.namespace), a = t ? r.provideService(i, this.sql.transactionService, t) : i, o = await O(this.systemName, "select", () => this.runtime.runPromise(a));
83
+ return S(o, e.table, "sqlite", e);
80
84
  }
81
85
  keyWhere(e, t) {
82
- let n = this.sql, r = $(Object.fromEntries(N(t)), e);
86
+ let n = this.sql, r = Q(Object.fromEntries(A(t)), e);
83
87
  return n.and(Object.entries(r).map(([e, t]) => n`${n(e)} = ${t}`));
84
88
  }
85
89
  async executeInsert(e, t, n, i, a) {
86
90
  t = P(e, t);
87
- let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert($(t, e))} RETURNING ${y(e, o)}`, c = n ? r.provideService(s, H, n) : s, l = await this.runtime.runPromise(c), u = x(l, e, "sqlite")[0];
91
+ let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(Q(t, e))} RETURNING ${b(e, o)}`, c = n ? r.provideService(s, this.sql.transactionService, n) : s, l = await this.runtime.runPromise(c), u = S(l, e, "sqlite")[0];
88
92
  if (!u) throw Error(`SqliteStore.insert: no row returned for table '${e}'`);
89
93
  return await this.routeEvent({
90
94
  table: e,
@@ -94,7 +98,7 @@ var U = (r) => e.layerConfig({
94
98
  }, i, n, a), u;
95
99
  }
96
100
  async executeUpdate(e, t, n, i, a, o) {
97
- let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update($(n, e))} WHERE ${this.keyWhere(e, t)} RETURNING ${y(e, s)}`, l = i ? r.provideService(c, H, i) : c, u = await this.runtime.runPromise(l), d = x(u, e, "sqlite")[0];
101
+ let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(Q(n, e))} WHERE ${this.keyWhere(e, t)} RETURNING ${b(e, s)}`, l = i ? r.provideService(c, this.sql.transactionService, i) : c, u = await this.runtime.runPromise(l), d = S(u, e, "sqlite")[0];
98
102
  return d ? (await this.routeEvent({
99
103
  table: e,
100
104
  op: "update",
@@ -104,26 +108,26 @@ var U = (r) => e.layerConfig({
104
108
  }
105
109
  async executeInsertMany(e, t, n, i, a) {
106
110
  if (t = F(e, t), t.length === 0) return [];
107
- let o = this.sql, s = t.map((t) => $(t, e)), c = p(s, d("sqlite")), l = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t)} RETURNING ${y(e, o)}`, u;
111
+ let o = this.sql, s = t.map((t) => Q(t, e)), c = m(s, f("sqlite")), l = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t)} RETURNING ${b(e, o)}`, u;
108
112
  if (c.length === 1) {
109
- let e = l(c[0]), t = n ? r.provideService(e, H, n) : e;
113
+ let e = l(c[0]), t = n ? r.provideService(e, this.sql.transactionService, n) : e;
110
114
  u = await this.runtime.runPromise(t);
111
115
  } else if (n) {
112
116
  let e = [];
113
- for (let t of c) e.push(...await this.runtime.runPromise(r.provideService(l(t), H, n)));
117
+ for (let t of c) e.push(...await this.runtime.runPromise(r.provideService(l(t), this.sql.transactionService, n)));
114
118
  u = e;
115
119
  } else u = await this.runtime.runPromise(o.withTransaction(r.map(r.forEach(c, l, { concurrency: 1 }), (e) => e.flat())));
116
- let f = x(u, e, "sqlite");
117
- for (let t of f) await this.routeEvent({
120
+ let d = S(u, e, "sqlite");
121
+ for (let t of d) await this.routeEvent({
118
122
  table: e,
119
123
  op: "insert",
120
124
  old: null,
121
125
  new: t
122
126
  }, i, n, a);
123
- return f;
127
+ return d;
124
128
  }
125
129
  async executePatchJson(e, t, n, i, a, o, s, c) {
126
- let l = this.sql, u = $(te(t, n, c), e), d = l.csv([g(l, "sqlite", n, i, l`${l(this.nsT(e))}.${l(n.split(".")[0])}`), ...Object.entries(u).map(([e, t]) => l`${l(e)} = ${t}`)]), f = l`UPDATE ${l(this.nsT(e))} SET ${d} WHERE ${this.keyWhere(e, t)} RETURNING ${y(e, l)}`, p = a ? r.provideService(f, H, a) : f, m = await this.runtime.runPromise(p), h = x(m, e, "sqlite")[0];
130
+ let l = this.sql, u = Q(T(t, n, c), e), d = l.csv([_(l, "sqlite", n, i, l`${l(this.nsT(e))}.${l(n.split(".")[0])}`), ...Object.entries(u).map(([e, t]) => l`${l(e)} = ${t}`)]), f = l`UPDATE ${l(this.nsT(e))} SET ${d} WHERE ${this.keyWhere(e, t)} RETURNING ${b(e, l)}`, p = a ? r.provideService(f, this.sql.transactionService, a) : f, m = await this.runtime.runPromise(p), h = S(m, e, "sqlite")[0];
127
131
  return h ? (await this.routeEvent({
128
132
  table: e,
129
133
  op: "update",
@@ -132,7 +136,7 @@ var U = (r) => e.layerConfig({
132
136
  }, o, a, s), h) : null;
133
137
  }
134
138
  async executeDelete(e, t, n, i, a) {
135
- let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} WHERE ${this.keyWhere(e, t)} RETURNING ${y(e, o)}`, c = n ? r.provideService(s, H, n) : s, l = await this.runtime.runPromise(c), u = x(l, e, "sqlite")[0];
139
+ let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} WHERE ${this.keyWhere(e, t)} RETURNING ${b(e, o)}`, c = n ? r.provideService(s, this.sql.transactionService, n) : s, l = await this.runtime.runPromise(c), u = S(l, e, "sqlite")[0];
136
140
  return u ? (await this.routeEvent({
137
141
  table: e,
138
142
  op: "delete",
@@ -141,18 +145,18 @@ var U = (r) => e.layerConfig({
141
145
  }, i, n, a), !0) : !1;
142
146
  }
143
147
  async appendInTxn(e, t, n) {
144
- let i = this.sql, a = i`INSERT INTO ${i(this.nsT(e))} ${i.insert($(t, e))}`;
145
- await this.runtime.runPromise(n ? r.provideService(a, H, n) : a);
148
+ let i = this.sql, a = i`INSERT INTO ${i(this.nsT(e))} ${i.insert(Q(t, e))}`;
149
+ await this.runtime.runPromise(n ? r.provideService(a, this.sql.transactionService, n) : a);
146
150
  }
147
151
  async maxInTxn(e, t, n, i) {
148
- let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? r.provideService(s, H, i) : s))[0]?.m;
152
+ let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? r.provideService(s, this.sql.transactionService, i) : s))[0]?.m;
149
153
  return c == null ? null : Number(c);
150
154
  }
151
155
  async routeEvent(e, t, n = null, r) {
152
156
  e = {
153
- ...u(r),
157
+ ...d(r),
154
158
  ...e
155
- }, j(e.table) && await ie({
159
+ }, k(e.table) && await N({
156
160
  append: (e, t) => this.appendInTxn(e, t, n),
157
161
  maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
158
162
  }, {
@@ -174,19 +178,19 @@ var U = (r) => e.layerConfig({
174
178
  }
175
179
  return this.executeInsert(e, t, i, a, o);
176
180
  }
177
- let c = this.sql, l = n.conflictColumns.map((e) => c`${c(e)}`), u = Object.keys(t).filter((e) => t[e] !== void 0), d = n.update === void 0 ? u.filter((e) => e !== "id" && !n.conflictColumns.includes(e)) : n.update, f = $(s, e), p = [...d.filter((e) => !Object.hasOwn(s, e)).map((e) => c`${c(e)} = excluded.${c(e)}`), ...Object.entries(f).map(([e, t]) => c`${c(e)} = ${t}`)], m = p.length > 0 ? c.csv(p) : c`${c(n.conflictColumns[0])} = excluded.${c(n.conflictColumns[0])}`, h = c`INSERT INTO ${c(this.nsT(e))} ${c.insert($(t, e))} ON CONFLICT (${c.csv(l)}) DO UPDATE SET ${m} RETURNING ${y(e, c)}`, g = i ? r.provideService(h, H, i) : h, _ = await this.runtime.runPromise(g), v = x(_, e, "sqlite")[0];
181
+ let c = this.sql, l = n.conflictColumns.map((e) => c`${c(e)}`), u = Object.keys(t).filter((e) => t[e] !== void 0), d = n.update === void 0 ? u.filter((e) => e !== "id" && !n.conflictColumns.includes(e)) : n.update, f = Q(s, e), p = [...d.filter((e) => !Object.hasOwn(s, e)).map((e) => c`${c(e)} = excluded.${c(e)}`), ...Object.entries(f).map(([e, t]) => c`${c(e)} = ${t}`)], m = p.length > 0 ? c.csv(p) : c`${c(n.conflictColumns[0])} = excluded.${c(n.conflictColumns[0])}`, h = c`INSERT INTO ${c(this.nsT(e))} ${c.insert(Q(t, e))} ON CONFLICT (${c.csv(l)}) DO UPDATE SET ${m} RETURNING ${b(e, c)}`, g = i ? r.provideService(h, this.sql.transactionService, i) : h, _ = await this.runtime.runPromise(g), v = S(_, e, "sqlite")[0];
178
182
  if (!v) throw Error(`SqliteStore.upsert: no row returned for table '${e}'`);
179
- let b = t.id !== void 0 && t.id === v.id ? "insert" : "update";
183
+ let y = t.id !== void 0 && t.id === v.id ? "insert" : "update";
180
184
  return await this.routeEvent({
181
185
  table: e,
182
- op: b,
186
+ op: y,
183
187
  old: null,
184
188
  new: v
185
189
  }, a, i, o), v;
186
190
  }
187
191
  async executeInsertIgnore(e, t, n, i, a, o) {
188
192
  t = P(e, t);
189
- let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(this.nsT(e))} ${s.insert($(t, e))} ON CONFLICT (${s.csv(c)}) DO NOTHING RETURNING ${y(e, s)}`, u = i ? r.provideService(l, H, i) : l, d = await this.runtime.runPromise(u), f = x(d, e, "sqlite")[0];
193
+ let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(this.nsT(e))} ${s.insert(Q(t, e))} ON CONFLICT (${s.csv(c)}) DO NOTHING RETURNING ${b(e, s)}`, u = i ? r.provideService(l, this.sql.transactionService, i) : l, d = await this.runtime.runPromise(u), f = S(d, e, "sqlite")[0];
190
194
  if (f) return await this.routeEvent({
191
195
  table: e,
192
196
  op: "insert",
@@ -205,8 +209,8 @@ var U = (r) => e.layerConfig({
205
209
  }
206
210
  async findByConflict(e, t, n, i) {
207
211
  if (n.length === 0) return;
208
- let a = this.sql, o = $(Object.fromEntries(n.map((e) => [e, t[e]])), e), s = n.map((e) => a`${a(e)} = ${o[e]}`), c = a`SELECT ${y(e, a)} FROM ${a(this.nsT(e))} WHERE ${a.and(s)} LIMIT 1`, l = i ? r.provideService(c, H, i) : c, u = await this.runtime.runPromise(l);
209
- return x(u, e, "sqlite")[0];
212
+ let a = this.sql, o = Q(Object.fromEntries(n.map((e) => [e, t[e]])), e), s = n.map((e) => a`${a(e)} = ${o[e]}`), c = a`SELECT ${b(e, a)} FROM ${a(this.nsT(e))} WHERE ${a.and(s)} LIMIT 1`, l = i ? r.provideService(c, this.sql.transactionService, i) : c, u = await this.runtime.runPromise(l);
213
+ return S(u, e, "sqlite")[0];
210
214
  }
211
215
  query(e) {
212
216
  return this.runWithEager(e, null);
@@ -215,14 +219,14 @@ var U = (r) => e.layerConfig({
215
219
  return this.rawOn(e, null);
216
220
  }
217
221
  rawOn(e, t) {
218
- let n = v(e, this.sql), i = t ? r.provideService(n, H, t) : n;
219
- return D(this.systemName, "raw", () => this.runtime.runPromise(i));
222
+ let n = y(e, this.sql), i = t ? r.provideService(n, this.sql.transactionService, t) : n;
223
+ return O(this.systemName, "raw", () => this.runtime.runPromise(i));
220
224
  }
221
225
  async runWithEager(e, t) {
222
- if (!ee(e)) return this.executeQuery(e, t);
223
- let n = this.namespace === null ? h(e, this.sql, "sqlite") : null;
226
+ if (!C(e)) return this.executeQuery(e, t);
227
+ let n = this.namespace === null ? g(e, this.sql, "sqlite") : null;
224
228
  if (n !== null) try {
225
- let e = t ? r.provideService(n.fragment, H, t) : n.fragment, i = await D(this.systemName, "select", () => this.runtime.runPromise(e));
229
+ let e = t ? r.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, i = await O(this.systemName, "select", () => this.runtime.runPromise(e));
226
230
  return n.decode(i);
227
231
  } catch (t) {
228
232
  if (t instanceof s) throw t;
@@ -239,17 +243,17 @@ var U = (r) => e.layerConfig({
239
243
  reason: "not-compilable"
240
244
  });
241
245
  let i = await this.executeQuery(e, t);
242
- return l(i, e.eager, e.sourceTable ?? M(e.table), (e) => this.executeQuery(e, t));
246
+ return u(i, e.eager, e.sourceTable ?? oe(e.table), (e) => this.executeQuery(e, t));
243
247
  }
244
248
  getInternalRunWithEager() {
245
249
  return (e, t) => this.runWithEager(e, t);
246
250
  }
247
251
  localWrite(e, t, n) {
248
- let r = (e) => j(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
249
- return D(this.systemName, e, () => R(r));
252
+ let r = (e) => k(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
253
+ return O(this.systemName, e, () => R(r));
250
254
  }
251
255
  async writeWithRecorders(e, t) {
252
- let n = [], i = this.sql, a = await this.runtime.runPromise(i.withTransaction(r.flatMap(r.serviceOption(H), (i) => o.isNone(i) ? r.fail(/* @__PURE__ */ Error("SqliteStore.write: TransactionConnection missing.")) : r.tryPromise({
256
+ let n = [], i = this.sql, a = await this.runtime.runPromise(i.withTransaction(r.flatMap(r.serviceOption(this.sql.transactionService), (i) => o.isNone(i) ? r.fail(/* @__PURE__ */ Error("SqliteStore.write: TransactionConnection missing.")) : r.tryPromise({
253
257
  try: () => e(t, i.value, n),
254
258
  catch: (e) => e
255
259
  }))));
@@ -278,8 +282,8 @@ var U = (r) => e.layerConfig({
278
282
  return this.executeDeleteMany(e, t, null, null);
279
283
  }
280
284
  async executeUpdateMany(e, t, n, i, a, o) {
281
- let s = this.sql, c = _(Q(n.where), s, this.namespace, e), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update($(t, e))} WHERE ${c} RETURNING ${y(e, s)}`, u = i ? r.provideService(l, H, i) : l, d = await D(this.systemName, "update", () => this.runtime.runPromise(u));
282
- for (let t of x(d, e, "sqlite")) await this.routeEvent({
285
+ let s = this.sql, c = v(Z(n.where), s, this.namespace, e), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update(Q(t, e))} WHERE ${c} RETURNING ${b(e, s)}`, u = i ? r.provideService(l, this.sql.transactionService, i) : l, d = await O(this.systemName, "update", () => this.runtime.runPromise(u));
286
+ for (let t of S(d, e, "sqlite")) await this.routeEvent({
283
287
  table: e,
284
288
  op: "update",
285
289
  old: null,
@@ -288,8 +292,8 @@ var U = (r) => e.layerConfig({
288
292
  return d.length;
289
293
  }
290
294
  async executeDeleteMany(e, t, n, i, a) {
291
- let o = this.sql, s = _(Q(t.where), o, this.namespace, e), c = o`DELETE FROM ${o(this.nsT(e))} WHERE ${s} RETURNING ${y(e, o)}`, l = n ? r.provideService(c, H, n) : c, u = await D(this.systemName, "delete", () => this.runtime.runPromise(l));
292
- for (let t of x(u, e, "sqlite")) await this.routeEvent({
295
+ let o = this.sql, s = v(Z(t.where), o, this.namespace, e), c = o`DELETE FROM ${o(this.nsT(e))} WHERE ${s} RETURNING ${b(e, o)}`, l = n ? r.provideService(c, this.sql.transactionService, n) : c, u = await O(this.systemName, "delete", () => this.runtime.runPromise(l));
296
+ for (let t of S(u, e, "sqlite")) await this.routeEvent({
293
297
  table: e,
294
298
  op: "delete",
295
299
  old: t,
@@ -347,7 +351,7 @@ var U = (r) => e.layerConfig({
347
351
  let t = this.sql, n = new Set(e), r = await this.runtime.runPromise(t`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`), i = [];
348
352
  for (let e of r) {
349
353
  if (n.has(e.name)) continue;
350
- let r = await this.runtime.runPromise(t`${t.unsafe(`PRAGMA foreign_key_list(${k(e.name, "sqlite")})`)}`).catch(() => []);
354
+ let r = await this.runtime.runPromise(t`${t.unsafe(`PRAGMA foreign_key_list(${ie(e.name, "sqlite")})`)}`).catch(() => []);
351
355
  for (let t of r) n.has(t.table) && i.push({
352
356
  from: e.name,
353
357
  column: t.from,
@@ -358,7 +362,7 @@ var U = (r) => e.layerConfig({
358
362
  }
359
363
  async emptyTablesOn(e, t) {
360
364
  if (e.length === 0) return;
361
- let n = this.sql, i = (e) => this.nsT(e), a = r.acquireUseRelease(n.unsafe("PRAGMA defer_foreign_keys = ON"), () => r.forEach(e, (e) => n`DELETE FROM ${n(i(e))}`, { discard: !0 }), () => r.orDie(r.ignore(n.unsafe("PRAGMA defer_foreign_keys = OFF")))), o = t === null ? n.withTransaction(a) : r.provideService(a, H, t);
365
+ let n = this.sql, i = (e) => this.nsT(e), a = r.acquireUseRelease(n.unsafe("PRAGMA defer_foreign_keys = ON"), () => r.forEach(e, (e) => n`DELETE FROM ${n(i(e))}`, { discard: !0 }), () => r.orDie(r.ignore(n.unsafe("PRAGMA defer_foreign_keys = OFF")))), o = t === null ? n.withTransaction(a) : r.provideService(a, this.sql.transactionService, t);
362
366
  await this.runtime.runPromise(o);
363
367
  }
364
368
  transactionEndingFailure(e) {
@@ -367,20 +371,24 @@ var U = (r) => e.layerConfig({
367
371
  async transactional(e) {
368
372
  this.inflightTxns++;
369
373
  try {
370
- return await re({
374
+ return await M({
371
375
  ...this.txnSpec("SqliteStore.transactional"),
372
376
  work: e,
373
- makeView: (e, t) => new ce(this, e, t)
377
+ makeView: (e, t) => new $(this, e, t)
374
378
  });
375
379
  } finally {
376
380
  this.inflightTxns--;
377
381
  }
378
382
  }
383
+ get transactionService() {
384
+ return this.sql.transactionService;
385
+ }
379
386
  txnSpec(e) {
380
387
  return {
381
388
  label: e,
382
389
  dialect: this.systemName === "turso" ? "turso" : "sqlite",
383
390
  withTransaction: (e) => this.sql.withTransaction(e),
391
+ transactionService: this.sql.transactionService,
384
392
  runPromiseExit: (e) => this.runtime.runPromiseExit(e),
385
393
  isRetryable: this.isRetryable,
386
394
  wrapProgram: (e) => this.wrapTransaction(e),
@@ -399,7 +407,7 @@ var U = (r) => e.layerConfig({
399
407
  };
400
408
  }
401
409
  injectExternalChange(e) {
402
- w(e.table) && this.emitter.emit("change", C(e));
410
+ w(e.table) && this.emitter.emit("change", te(e));
403
411
  }
404
412
  run(e) {
405
413
  return this.runtime.runPromise(e);
@@ -408,7 +416,7 @@ var U = (r) => e.layerConfig({
408
416
  if (this.inflightTxns > 0) {
409
417
  let t = Date.now() + e;
410
418
  for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
411
- this.inflightTxns > 0 && X.warn("close: grace period expired with in-flight transactions", {
419
+ this.inflightTxns > 0 && Y.warn("close: grace period expired with in-flight transactions", {
412
420
  gracePeriodMs: e,
413
421
  inflight: this.inflightTxns
414
422
  });
@@ -418,27 +426,27 @@ var U = (r) => e.layerConfig({
418
426
  async ping() {
419
427
  await this.runtime.runPromise(this.sql`SELECT 1`);
420
428
  }
421
- }, ce = class {
429
+ }, $ = class {
422
430
  parent;
423
431
  txn;
424
432
  attr;
425
433
  events = [];
426
- aborts = E((e) => this.parent.transactionEndingFailure(e));
434
+ aborts = D((e) => this.parent.transactionEndingFailure(e));
427
435
  committed = !1;
428
436
  constructor(e, t, n = void 0) {
429
437
  this.parent = e, this.txn = t, this.attr = n;
430
438
  }
431
439
  savepoint(e) {
432
- return ne({
440
+ return j({
433
441
  tracker: this.aborts,
434
442
  name: `voltro_sp_${++this.savepointCounter}`,
435
443
  spelling: "standard",
436
- exec: (e) => this.parent.run(r.provideService(V.pipe(r.flatMap((t) => t.unsafe(e))), H, this.txn))
444
+ exec: (e) => this.parent.run(r.provideService(V.pipe(r.flatMap((t) => t.unsafe(e))), this.parent.transactionService, this.txn))
437
445
  }, e);
438
446
  }
439
447
  savepointCounter = 0;
440
448
  run(e) {
441
- return this.aborts.track(() => this.parent.run(r.provideService(e, H, this.txn)));
449
+ return this.aborts.track(() => this.parent.run(ne(e, this.parent.transactionService, this.txn)));
442
450
  }
443
451
  abortedBy() {
444
452
  return this.aborts.abortedBy();
@@ -498,12 +506,12 @@ var U = (r) => e.layerConfig({
498
506
  this.events.length = 0;
499
507
  }
500
508
  }
501
- }, le = {
509
+ }, ue = {
502
510
  id: "sqlite",
503
- makeSqlLayer: (e) => G(e),
504
- makeStore: (e) => Z(e),
511
+ makeSqlLayer: (e) => W(e),
512
+ makeStore: (e) => X(e),
505
513
  compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
506
- retryFilter: Y
514
+ retryFilter: J
507
515
  };
508
516
  //#endregion
509
- export { e as SqliteClient, W as connectionFromConfig, U as makeSqliteSqlLayer, G as makeSqliteSqlLayerFromConfig, Z as makeSqliteStore, le as sqliteDialect, Y as sqliteRetryFilter };
517
+ export { e as SqliteClient, U as connectionFromConfig, H as makeSqliteSqlLayer, W as makeSqliteSqlLayerFromConfig, X as makeSqliteStore, ue as sqliteDialect, J as sqliteRetryFilter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/sql-sqlite",
3
- "version": "0.84.0",
3
+ "version": "0.85.0",
4
4
  "description": "SQLite dialect adapter for Voltro's cross-dialect DataStore (single-process; in-process change events).",
5
5
  "keywords": [
6
6
  "voltro",
@@ -33,13 +33,12 @@
33
33
  "node": ">=24.0.0"
34
34
  },
35
35
  "dependencies": {
36
- "@effect/sql": "^0.52.1",
37
- "@effect/sql-sqlite-node": "^0.53.0",
38
- "@voltro/database": "0.84.0",
39
- "@voltro/logger": "0.84.0"
36
+ "@effect/sql-sqlite-node": "4.0.1",
37
+ "@voltro/database": "0.85.0",
38
+ "@voltro/logger": "0.85.0"
40
39
  },
41
40
  "peerDependencies": {
42
- "effect": "^3.22.2"
41
+ "effect": "4.0.1"
43
42
  },
44
43
  "publishConfig": {
45
44
  "access": "public"