@voltro/sql-mssql 0.86.0 → 0.88.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.
@@ -1,6 +1,6 @@
1
1
  import { Effect as e } from "effect";
2
2
  import { SqlClient as t } from "effect/sql/SqlClient";
3
- //#region src/replicationAdapter.ts
3
+ // src/replicationAdapter.ts
4
4
  var n = (e) => e.__mssqlReplicationFriend ?? null, r = (e, t) => e === t ? 0 : e < t ? -1 : 1, i = () => ({
5
5
  async capturePrimaryPosition(r) {
6
6
  let i = n(r);
@@ -31,5 +31,4 @@ var n = (e) => e.__mssqlReplicationFriend ?? null, r = (e, t) => e === t ? 0 : e
31
31
  return r(t, e) >= 0 ? "caught-up" : "behind";
32
32
  }
33
33
  });
34
- //#endregion
35
34
  export { i as mssqlReplicationAdapter };
package/dist/retry.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MSSQL_TRANSIENT_NUMBERS as e, causeBranches as t } from "@voltro/database";
2
- //#region src/retry.ts
2
+ // src/retry.ts
3
3
  var n = e, r = (e) => {
4
4
  let t = e;
5
5
  for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
@@ -16,5 +16,4 @@ var n = e, r = (e) => {
16
16
  let t = r(e);
17
17
  return t !== void 0 && a.has(t);
18
18
  }), s = (e) => i(e) ? "retry" : "noRetry";
19
- //#endregion
20
19
  export { o as isDuplicateKeyMssqlFailure, i as isRetryableMssqlFailure, s as mssqlRetryFilter };
@@ -1,6 +1,6 @@
1
1
  import { Effect as e } from "effect";
2
2
  import { sqlError as t } from "@voltro/database";
3
- //#region src/rowResultProjection.ts
3
+ // src/rowResultProjection.ts
4
4
  var n = (n, r) => e.gen(function* () {
5
5
  let e = yield* n`
6
6
  SELECT name, system_type_id FROM sys.columns
@@ -12,5 +12,4 @@ var n = (n, r) => e.gen(function* () {
12
12
  let r = e.literal(`[${t.name.replaceAll("]", "]]")}]`), i = n ? e`${e(n)}.${r}` : r;
13
13
  return t.system_type_id === 106 || t.system_type_id === 108 ? e`CONVERT(varchar(80), ${i}) AS ${r}` : i;
14
14
  }));
15
- //#endregion
16
15
  export { r as mssqlRowResultProjection, n as readMssqlPhysicalColumns };
package/dist/sqlLayer.js CHANGED
@@ -4,7 +4,7 @@ import { MssqlClient as n } from "@effect/sql-mssql";
4
4
  import { TYPES as r } from "tedious";
5
5
  import { Config as i, Duration as a, Redacted as o } from "effect";
6
6
  import { DEFAULT_ACQUIRE_TIMEOUT_MS as s, SHARED_TRANSACTION_SERVICE as c } from "@voltro/database";
7
- //#region src/sqlLayer.ts
7
+ // src/sqlLayer.ts
8
8
  var l = {
9
9
  ...n.defaultParameterTypes,
10
10
  null: r.NVarChar,
@@ -74,5 +74,4 @@ var l = {
74
74
  ...t
75
75
  };
76
76
  }, m = (e) => d(p(e));
77
- //#endregion
78
77
  export { n as MssqlClient, p as connectionFromConfig, d as makeMssqlSqlLayer, m as makeMssqlSqlLayerFromConfig, u as resolveAcquireTimeoutMs, f as sslFromUrlQuery };
package/dist/store.js CHANGED
@@ -2,53 +2,53 @@ import { writeOutput as e } from "./writeOutput.js";
2
2
  import { isDuplicateKeyMssqlFailure as t, isRetryableMssqlFailure as n } from "./retry.js";
3
3
  import { startChangeTrackingCdc as r } from "./changeTrackingCdc.js";
4
4
  import { CDC_OFFSETS_TABLE as i } from "./cdcOffsetsTable.js";
5
- import { Effect as a, Layer as o, ManagedRuntime as s, Option as c } from "effect";
6
- import { EagerCardinalityError as l, attachEagerLoads as u, attributionFields as d, bulkInsertLimitsFor as f, chunkRowsForInsert as p, compileEagerJson as m, compileJsonPatch as h, compilePredicate as g, compileRawFragment as _, compileSelect as v, decodeRowsFromSchema as y, emitCommittedChanges as b, encodeRowForSchema as x, externalChangeEvent as S, hasEagerLoads as C, isTableReactive as w, jsonPatchAssignments as T, makeEagerFallbackReporter as E, makeTransactionAbortTracker as D, observeDbOp as O, onTransaction as k, qualifyTable as A, quoteIdent as j, raiseChangeListenerCeiling as M, recordsTable as N, requireTable as P, rowKeyColumns as F, runSavepoint as I, runStoreTransaction as L, runWriteRecorders as R, stampGeneratedId as z, stampGeneratedIds as B, upsertUpdatePatch as V, upsertUpdateValues as H, withCapturedAttribution as U } from "@voltro/database";
7
- import { EventEmitter as W } from "node:events";
8
- import { createLogger as G } from "@voltro/logger";
9
- import { SqlClient as K } from "effect/sql/SqlClient";
10
- //#region src/store.ts
11
- var q = G({ scope: "voltro:mssql" }), J = async (e) => {
5
+ import { Array as a, Effect as o, Layer as s, ManagedRuntime as c, Option as l } from "effect";
6
+ import { EagerCardinalityError as u, attachEagerLoads as d, attributionFields as f, bulkInsertLimitsFor as p, chunkRowsForInsert as m, compileEagerJson as h, compileJsonPatch as g, compilePredicate as _, compileRawFragment as v, compileSelect as y, decodeRowsFromSchema as b, decodeSelectRows as x, emitCommittedChanges as S, encodeRowForSchema as C, externalChangeEvent as w, hasEagerLoads as T, isTableReactive as E, jsonPatchAssignments as D, makeEagerFallbackReporter as O, makeTransactionAbortTracker as k, observeDbOp as A, onTransaction as j, qualifyTable as M, quoteIdent as N, raiseChangeListenerCeiling as P, recordsTable as F, requireTable as I, rowKeyColumns as L, runSavepoint as R, runStoreTransaction as z, runWriteRecorders as B, stampGeneratedId as V, stampGeneratedIds as H, upsertUpdatePatch as U, upsertUpdateValues as W, withCapturedAttribution as G, writeImagesObserved as K } from "@voltro/database";
7
+ import { EventEmitter as q } from "node:events";
8
+ import { createLogger as J } from "@voltro/logger";
9
+ import { SqlClient as Y } from "effect/sql/SqlClient";
10
+ // src/store.ts
11
+ var X = J({ scope: "voltro:mssql" }), Z = async (e) => {
12
12
  let t = e.changeStrategy ?? "inline", n = t;
13
- t === "cdc" && !e.cdcConfig && (q.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
14
- let r = e.tracerLayer ? o.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = s.make(r), a = new Y(await i.runPromise(K), i, n);
13
+ t === "cdc" && !e.cdcConfig && (X.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
14
+ let r = e.tracerLayer ? s.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = c.make(r), a = new Q(await i.runPromise(Y), i, n);
15
15
  return n === "cdc" && e.cdcConfig && await a.startCdcConsumer(e.cdcConfig), a;
16
- }, Y = class o {
16
+ }, Q = class s {
17
17
  sql;
18
18
  runtime;
19
19
  changeStrategy;
20
20
  namespace;
21
21
  emitter;
22
22
  inflightTxns = 0;
23
- reportEagerFallback = E(q);
23
+ reportEagerFallback = O(X);
24
24
  cdcHandle = null;
25
25
  cdcCheckpointTimer = null;
26
26
  cdcPendingVersion = null;
27
27
  cdcReplicaId = "";
28
28
  cdcStreamName = "default";
29
29
  constructor(e, t, n = "inline", r = null, i) {
30
- this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new W(), M(this.emitter);
30
+ this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new q(), P(this.emitter);
31
31
  }
32
32
  get inlineEmit() {
33
33
  return this.changeStrategy === "inline";
34
34
  }
35
35
  withNamespace(e) {
36
- return e === this.namespace ? this : new o(this.sql, this.runtime, this.changeStrategy, e, this.emitter);
36
+ return e === this.namespace ? this : new s(this.sql, this.runtime, this.changeStrategy, e, this.emitter);
37
37
  }
38
38
  nsT(e) {
39
- return A(this.namespace, e);
39
+ return M(this.namespace, e);
40
40
  }
41
41
  __mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
42
42
  async executeQuery(e, t) {
43
- let n = v(e, this.sql, this.namespace), r = t ? a.provideService(n, this.sql.transactionService, t) : n, i = await O("mssql", "select", () => this.runtime.runPromise(r));
44
- return y(i, e.table, "mssql");
43
+ let n = y(e, this.sql, this.namespace), r = t ? o.provideService(n, this.sql.transactionService, t) : n, i = await A("mssql", "select", () => this.runtime.runPromise(r));
44
+ return x(i, e, "mssql");
45
45
  }
46
46
  decodeWritten(e, t) {
47
- return y([t], e, "mssql")[0] ?? t;
47
+ return b([t], e, "mssql")[0] ?? t;
48
48
  }
49
- async executeInsert(t, n, r, i, o) {
50
- n = z(t, n);
51
- let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(x(n, t)).returning(s`INSERTED.* INTO ${e}`)}`), l = r ? a.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
49
+ async executeInsert(t, n, r, i, a) {
50
+ n = V(t, n);
51
+ let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(C(n, t)).returning(s`INSERTED.* INTO ${e}`)}`), l = r ? o.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
52
52
  if (!u) throw Error(`MssqlStore.insert: row not returned post-insert in '${t}'`);
53
53
  let d = this.decodeWritten(t, u);
54
54
  return await this.routeEvent({
@@ -56,10 +56,10 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
56
56
  op: "insert",
57
57
  old: null,
58
58
  new: d
59
- }, i, r, o), d;
59
+ }, i, r, a), d;
60
60
  }
61
- async executeUpdate(t, n, r, i, o, s) {
62
- let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(x(r, t)).returning(c`INSERTED.* INTO ${e}`)} WHERE ${c.and(F(n).map(([e, t]) => c`${c(e)} = ${t}`))}`), u = i ? a.provideService(l, this.sql.transactionService, i) : l, d = (await this.runtime.runPromise(u))[0];
61
+ async executeUpdate(t, n, r, i, a, s) {
62
+ let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(C(r, t)).returning(c`INSERTED.* INTO ${e}`)} WHERE ${c.and(L(n).map(([e, t]) => c`${c(e)} = ${t}`))}`), u = i ? o.provideService(l, this.sql.transactionService, i) : l, d = (await this.runtime.runPromise(u))[0];
63
63
  if (!d) return null;
64
64
  let f = this.decodeWritten(t, d);
65
65
  return await this.routeEvent({
@@ -67,41 +67,45 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
67
67
  op: "update",
68
68
  old: null,
69
69
  new: f
70
- }, o, i, s), f;
71
- }
72
- async executeInsertMany(t, n, r, i, o) {
73
- if (n = B(t, n), n.length === 0) return [];
74
- let s = this.sql, c = p(n, f("mssql")), l = (n) => e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(n.map((e) => x(e, t))).returning(s`INSERTED.* INTO ${e}`)}`), u;
75
- if (c.length === 1) {
76
- let e = l(c[0]), t = r ? a.provideService(e, this.sql.transactionService, r) : e;
77
- u = await this.runtime.runPromise(t);
70
+ }, a, i, s), f;
71
+ }
72
+ async executeInsertMany(t, n, r, i, s, c) {
73
+ if (n = H(t, n), n.length === 0) return [];
74
+ let l = this.sql, u = m(n, p("mssql")), d = c?.returning === "none", f = d && !K(t), h = (n) => {
75
+ let r = l.insert(a.map(n, (e) => C(e, t)));
76
+ return f ? o.as(l`INSERT INTO ${l(this.nsT(t))} ${r}`, []) : e(l, this.nsT(t), (e) => l`INSERT INTO ${l(this.nsT(t))} ${r.returning(l`INSERTED.* INTO ${e}`)}`);
77
+ }, g;
78
+ if (u.length === 1) {
79
+ let e = h(u[0]), t = r ? o.provideService(e, this.sql.transactionService, r) : e;
80
+ g = await this.runtime.runPromise(t);
78
81
  } else if (r) {
79
82
  let e = [];
80
- for (let t of c) e.push(...await this.runtime.runPromise(a.provideService(l(t), this.sql.transactionService, r)));
81
- u = e;
82
- } else u = await this.runtime.runPromise(s.withTransaction(a.map(a.forEach(c, l, { concurrency: 1 }), (e) => e.flat())));
83
- let d = n.map((e) => e.id), m = y(u, t, "mssql"), h = new Map(m.map((e) => [e.id, e])), g = d.map((e) => h.get(e)).filter((e) => e !== void 0), _ = g.length === u.length ? g : m;
84
- for (let e of _) await this.routeEvent({
83
+ for (let t of u) e.push(...await this.runtime.runPromise(o.provideService(h(t), this.sql.transactionService, r)));
84
+ g = e;
85
+ } else g = await this.runtime.runPromise(l.withTransaction(o.map(o.forEach(u, h, { concurrency: 1 }), (e) => e.flat())));
86
+ if (f) return [];
87
+ let _ = n.map((e) => e.id), v = b(g, t, "mssql"), y = new Map(v.map((e) => [e.id, e])), x = _.map((e) => y.get(e)).filter((e) => e !== void 0), S = x.length === g.length ? x : v;
88
+ for (let e of S) await this.routeEvent({
85
89
  table: t,
86
90
  op: "insert",
87
91
  old: null,
88
92
  new: e
89
- }, i, r, o);
90
- return _;
93
+ }, i, r, s);
94
+ return d ? [] : S;
91
95
  }
92
- async executePatchJson(t, n, r, i, o, s, c, l) {
93
- let u = this.sql, d = x(T(n, r, l), t), f = u.csv([h(u, "mssql", r, i), ...Object.entries(d).map(([e, t]) => u`${u(e)} = ${t}`)]), p = e(u, this.nsT(t), (e) => u`UPDATE ${u(this.nsT(t))} SET ${f} OUTPUT INSERTED.* INTO ${e} WHERE ${u.and(F(n).map(([e, t]) => u`${u(e)} = ${t}`))}`), m = o ? a.provideService(p, this.sql.transactionService, o) : p, g = (await this.runtime.runPromise(m))[0];
94
- if (!g) return null;
95
- let _ = this.decodeWritten(t, g);
96
+ async executePatchJson(t, n, r, i, a, s, c, l) {
97
+ let u = this.sql, d = C(D(n, r, l), t), f = u.csv([g(u, "mssql", r, i), ...Object.entries(d).map(([e, t]) => u`${u(e)} = ${t}`)]), p = e(u, this.nsT(t), (e) => u`UPDATE ${u(this.nsT(t))} SET ${f} OUTPUT INSERTED.* INTO ${e} WHERE ${u.and(L(n).map(([e, t]) => u`${u(e)} = ${t}`))}`), m = a ? o.provideService(p, this.sql.transactionService, a) : p, h = (await this.runtime.runPromise(m))[0];
98
+ if (!h) return null;
99
+ let _ = this.decodeWritten(t, h);
96
100
  return await this.routeEvent({
97
101
  table: t,
98
102
  op: "update",
99
103
  old: null,
100
104
  new: _
101
- }, s, o, c), _;
105
+ }, s, a, c), _;
102
106
  }
103
- async executeDelete(t, n, r, i, o) {
104
- let s = this.sql, c = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${s.and(F(n).map(([e, t]) => s`${s(e)} = ${t}`))}`), l = r ? a.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
107
+ async executeDelete(t, n, r, i, a) {
108
+ let s = this.sql, c = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${s.and(L(n).map(([e, t]) => s`${s(e)} = ${t}`))}`), l = r ? o.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
105
109
  if (!u) return !1;
106
110
  let d = this.decodeWritten(t, u);
107
111
  return await this.routeEvent({
@@ -109,21 +113,21 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
109
113
  op: "delete",
110
114
  old: d,
111
115
  new: null
112
- }, i, r, o), !0;
116
+ }, i, r, a), !0;
113
117
  }
114
118
  async appendInTxn(e, t, n) {
115
- let r = this.sql, i = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(x(t, e))}`;
116
- await this.runtime.runPromise(n ? a.provideService(i, this.sql.transactionService, n) : i);
119
+ let r = this.sql, i = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(C(t, e))}`;
120
+ await this.runtime.runPromise(n ? o.provideService(i, this.sql.transactionService, n) : i);
117
121
  }
118
122
  async maxInTxn(e, t, n, r) {
119
- let i = this.sql, o = Object.entries(n).map(([e, t]) => i`${i(e)} = ${t}`), s = i`SELECT MAX(${i(t)}) AS ${i("m")} FROM ${i(this.nsT(e))} WHERE ${i.and(o)}`, c = (await this.runtime.runPromise(r ? a.provideService(s, this.sql.transactionService, r) : s))[0]?.m;
123
+ let i = this.sql, a = Object.entries(n).map(([e, t]) => i`${i(e)} = ${t}`), s = i`SELECT MAX(${i(t)}) AS ${i("m")} FROM ${i(this.nsT(e))} WHERE ${i.and(a)}`, c = (await this.runtime.runPromise(r ? o.provideService(s, this.sql.transactionService, r) : s))[0]?.m;
120
124
  return c == null ? null : Number(c);
121
125
  }
122
126
  async routeEvent(e, t, n = null, r) {
123
127
  e = {
124
- ...d(r),
128
+ ...f(r),
125
129
  ...e
126
- }, N(e.table) && await R({
130
+ }, F(e.table) && await B({
127
131
  append: (e, t) => this.appendInTxn(e, t, n),
128
132
  maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
129
133
  }, {
@@ -133,7 +137,10 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
133
137
  prev: e.old,
134
138
  traceId: e.traceId,
135
139
  subjectId: e.subjectId
136
- }), w(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
140
+ }), E(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
141
+ }
142
+ integrityQuery(e) {
143
+ return this.query(e);
137
144
  }
138
145
  query(e) {
139
146
  return this.runWithEager(e, null);
@@ -142,17 +149,17 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
142
149
  return this.rawOn(e, null);
143
150
  }
144
151
  rawOn(e, t) {
145
- let n = _(e, this.sql), r = t ? a.provideService(n, this.sql.transactionService, t) : n;
146
- return O("mssql", "raw", () => this.runtime.runPromise(r));
152
+ let n = v(e, this.sql), r = t ? o.provideService(n, this.sql.transactionService, t) : n;
153
+ return A("mssql", "raw", () => this.runtime.runPromise(r));
147
154
  }
148
155
  async runWithEager(e, t) {
149
- if (!C(e)) return this.executeQuery(e, t);
150
- let n = this.namespace === null ? m(e, this.sql, "mssql") : null;
156
+ if (!T(e)) return this.executeQuery(e, t);
157
+ let n = this.namespace === null ? h(e, this.sql, "mssql") : null;
151
158
  if (n !== null) try {
152
- let e = t ? a.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, r = await O("mssql", "select", () => this.runtime.runPromise(e));
159
+ let e = t ? o.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, r = await A("mssql", "select", () => this.runtime.runPromise(e));
153
160
  return n.decode(r);
154
161
  } catch (t) {
155
- if (t instanceof l) throw t;
162
+ if (t instanceof u) throw t;
156
163
  this.reportEagerFallback({
157
164
  dialect: "mssql",
158
165
  table: e.table,
@@ -166,27 +173,27 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
166
173
  reason: "not-compilable"
167
174
  });
168
175
  let r = await this.executeQuery(e, t);
169
- return u(r, e.eager, e.sourceTable ?? P(e.table), (e) => this.executeQuery(e, t));
176
+ return d(r, e.eager, e.sourceTable ?? I(e.table), (e) => this.executeQuery(e, t));
170
177
  }
171
178
  getInternalRunWithEager() {
172
179
  return this.runWithEager.bind(this);
173
180
  }
174
181
  localWrite(e, t, n) {
175
- let r = (e) => N(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
176
- return O("mssql", e, () => U(r));
182
+ let r = (e) => F(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
183
+ return A("mssql", e, () => G(r));
177
184
  }
178
185
  async writeWithRecorders(e, t) {
179
- let n = [], r = this.sql, i = await this.runtime.runPromise(r.withTransaction(a.flatMap(a.serviceOption(this.sql.transactionService), (r) => c.isNone(r) ? a.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : a.tryPromise({
186
+ let n = [], r = this.sql, i = await this.runtime.runPromise(r.withTransaction(o.flatMap(o.serviceOption(this.sql.transactionService), (r) => l.isNone(r) ? o.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : o.tryPromise({
180
187
  try: () => e(t, r.value, n),
181
188
  catch: (e) => e
182
189
  }))));
183
- return b(n, (e) => this.emitChange(e)), i;
190
+ return S(n, (e) => this.emitChange(e)), i;
184
191
  }
185
192
  insert(e, t) {
186
193
  return this.localWrite("insert", e, (n, r, i) => this.executeInsert(e, t, r, i, n));
187
194
  }
188
- insertMany(e, t) {
189
- return this.localWrite("insert", e, (n, r, i) => this.executeInsertMany(e, t, r, i, n));
195
+ insertMany(e, t, n) {
196
+ return this.localWrite("insert", e, (r, i, a) => this.executeInsertMany(e, t, i, a, r, n));
190
197
  }
191
198
  patchJson(e, t, n, r, i) {
192
199
  return this.localWrite("update", e, (a, o, s) => this.executePatchJson(e, t, n, r, o, s, a, i));
@@ -203,24 +210,32 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
203
210
  deleteMany(e, t) {
204
211
  return this.executeDeleteMany(e, t, null, null);
205
212
  }
206
- async executeUpdateMany(t, n, r, i, o, s) {
207
- let c = this.sql, l = g(r.where, c, this.namespace), u = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(x(n, t))} OUTPUT INSERTED.* INTO ${e} WHERE ${l}`), d = i ? a.provideService(u, this.sql.transactionService, i) : u, f = await O("mssql", "update", () => this.runtime.runPromise(d));
208
- for (let e of y(f, t, "mssql")) await this.routeEvent({
213
+ async executeUpdateMany(t, n, r, i, a, s) {
214
+ let c = this.sql, l = _(r.where, c, this.namespace), u = c.update(C(n, t));
215
+ if (!K(t)) return this.countWritten(c`UPDATE ${c(this.nsT(t))} SET ${u} WHERE ${l}`, "update", i);
216
+ let d = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${u} OUTPUT INSERTED.* INTO ${e} WHERE ${l}`), f = i ? o.provideService(d, this.sql.transactionService, i) : d, p = await A("mssql", "update", () => this.runtime.runPromise(f));
217
+ for (let e of b(p, t, "mssql")) await this.routeEvent({
209
218
  table: t,
210
219
  op: "update",
211
220
  old: null,
212
221
  new: e
213
- }, o, i, s);
214
- return f.length;
215
- }
216
- async executeDeleteMany(t, n, r, i, o) {
217
- let s = this.sql, c = g(n.where, s, this.namespace), l = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${c}`), u = r ? a.provideService(l, this.sql.transactionService, r) : l, d = await O("mssql", "delete", () => this.runtime.runPromise(u));
218
- for (let e of y(d, t, "mssql")) await this.routeEvent({
222
+ }, a, i, s);
223
+ return p.length;
224
+ }
225
+ async countWritten(e, t, n) {
226
+ let r = (0, this.sql)`${e}; SELECT @@ROWCOUNT AS n`, i = n ? o.provideService(r, this.sql.transactionService, n) : r, [a] = await A("mssql", t, () => this.runtime.runPromise(i));
227
+ return Number(a?.n ?? 0);
228
+ }
229
+ async executeDeleteMany(t, n, r, i, a) {
230
+ let s = this.sql, c = _(n.where, s, this.namespace);
231
+ if (!K(t)) return this.countWritten(s`DELETE FROM ${s(this.nsT(t))} WHERE ${c}`, "delete", r);
232
+ let l = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${c}`), u = r ? o.provideService(l, this.sql.transactionService, r) : l, d = await A("mssql", "delete", () => this.runtime.runPromise(u));
233
+ for (let e of b(d, t, "mssql")) await this.routeEvent({
219
234
  table: t,
220
235
  op: "delete",
221
236
  old: e,
222
237
  new: null
223
- }, i, r, o);
238
+ }, i, r, a);
224
239
  return d.length;
225
240
  }
226
241
  upsert(e, t, n) {
@@ -233,24 +248,24 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
233
248
  return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
234
249
  }
235
250
  async executeUpsert(e, n, r, i, a, o) {
236
- if (H(r), n = z(e, n), typeof r.update != "function" && r.conflictColumns.length > 0) return this.mergeUpsert(e, n, {
251
+ if (W(r), n = V(e, n), typeof r.update != "function" && r.conflictColumns.length > 0) return this.mergeUpsert(e, n, {
237
252
  conflictColumns: r.conflictColumns,
238
253
  ...r.update === void 0 ? {} : { update: r.update },
239
254
  ...r.updateValues === void 0 ? {} : { updateValues: r.updateValues }
240
255
  }, i, a, o);
241
256
  let s = await this.findByConflict(e, n, r.conflictColumns, i);
242
- if (s) return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, s[e]])), V(n, s, r), i, a, o) ?? s;
257
+ if (s) return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, s[e]])), U(n, s, r), i, a, o) ?? s;
243
258
  try {
244
259
  return await this.executeInsert(e, n, i, a, o);
245
260
  } catch (s) {
246
261
  if (!t(s)) throw s;
247
262
  let c = await this.findByConflict(e, n, r.conflictColumns, i);
248
263
  if (!c) throw s;
249
- return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, c[e]])), V(n, c, r), i, a, o) ?? c;
264
+ return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, c[e]])), U(n, c, r), i, a, o) ?? c;
250
265
  }
251
266
  }
252
- async mergeUpsert(t, n, r, i, o, s) {
253
- let c = this.sql, l = Object.keys(n), u = Array.isArray(r.update) ? r.update.filter((e) => l.includes(e)) : l.filter((e) => e !== "id" && !r.conflictColumns.includes(e)), d = x(n, t), f = l.map((e) => c`${d[e]}`), p = l.map((e) => c`${c(e)}`), m = r.conflictColumns.map((e) => c`tgt.${c(e)} = src.${c(e)}`), h = l.map((e) => c`${c(e)}`), g = l.map((e) => c`src.${c(e)}`), _ = H(r), v = x(_, t), y = [...u.filter((e) => !Object.hasOwn(_, e)).map((e) => c`tgt.${c(e)} = src.${c(e)}`), ...Object.entries(v).map(([e, t]) => c`tgt.${c(e)} = ${t}`)];
267
+ async mergeUpsert(t, n, r, i, a, s) {
268
+ let c = this.sql, l = Object.keys(n), u = Array.isArray(r.update) ? r.update.filter((e) => l.includes(e)) : l.filter((e) => e !== "id" && !r.conflictColumns.includes(e)), d = C(n, t), f = l.map((e) => c`${d[e]}`), p = l.map((e) => c`${c(e)}`), m = r.conflictColumns.map((e) => c`tgt.${c(e)} = src.${c(e)}`), h = l.map((e) => c`${c(e)}`), g = l.map((e) => c`src.${c(e)}`), _ = W(r), v = C(_, t), y = [...u.filter((e) => !Object.hasOwn(_, e)).map((e) => c`tgt.${c(e)} = src.${c(e)}`), ...Object.entries(v).map(([e, t]) => c`tgt.${c(e)} = ${t}`)];
254
269
  y.length === 0 && y.push(c`tgt.${c(r.conflictColumns[0])} = src.${c(r.conflictColumns[0])}`);
255
270
  let b = e(c, this.nsT(t), (e) => c`
256
271
  MERGE ${c(this.nsT(t))} WITH (HOLDLOCK) AS tgt
@@ -258,18 +273,18 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
258
273
  ON ${c.and(m)}
259
274
  WHEN MATCHED THEN UPDATE SET ${c.csv(y)}
260
275
  WHEN NOT MATCHED THEN INSERT (${c.csv(h)}) VALUES (${c.csv(g)})
261
- OUTPUT $action AS ${c("__action")}, INSERTED.* INTO ${e};`, !0), S = i ? a.provideService(b, this.sql.transactionService, i) : b, C = (await this.runtime.runPromise(S))[0];
262
- if (!C) throw Error(`MssqlStore.upsert: MERGE returned no row for '${t}'`);
263
- let w = C.__action, { __action: T, ...E } = C, D = this.decodeWritten(t, E);
276
+ OUTPUT $action AS ${c("__action")}, INSERTED.* INTO ${e};`, !0), x = i ? o.provideService(b, this.sql.transactionService, i) : b, S = (await this.runtime.runPromise(x))[0];
277
+ if (!S) throw Error(`MssqlStore.upsert: MERGE returned no row for '${t}'`);
278
+ let w = S.__action, { __action: T, ...E } = S, D = this.decodeWritten(t, E);
264
279
  return await this.routeEvent({
265
280
  table: t,
266
281
  op: w === "INSERT" ? "insert" : "update",
267
282
  old: null,
268
283
  new: D
269
- }, o, i, s), D;
284
+ }, a, i, s), D;
270
285
  }
271
286
  async executeInsertIgnore(e, n, r, i, a, o) {
272
- n = z(e, n);
287
+ n = V(e, n);
273
288
  let s = await this.findByConflict(e, n, r.conflictColumns, i);
274
289
  if (s) return {
275
290
  row: s,
@@ -292,7 +307,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
292
307
  }
293
308
  async findByConflict(e, t, n, r) {
294
309
  if (n.length === 0) return;
295
- let i = this.sql, o = n.map((e) => i`${i(e)} = ${t[e]}`), s = i`SELECT TOP 1 * FROM ${i(this.nsT(e))} WHERE ${i.and(o)}`, c = r ? a.provideService(s, this.sql.transactionService, r) : s, l = (await this.runtime.runPromise(c))[0];
310
+ let i = this.sql, a = n.map((e) => i`${i(e)} = ${t[e]}`), s = i`SELECT TOP 1 * FROM ${i(this.nsT(e))} WHERE ${i.and(a)}`, c = r ? o.provideService(s, this.sql.transactionService, r) : s, l = (await this.runtime.runPromise(c))[0];
296
311
  return l ? this.decodeWritten(e, l) : void 0;
297
312
  }
298
313
  emitChange(e) {
@@ -302,7 +317,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
302
317
  if (this.cdcHandle) return;
303
318
  this.cdcReplicaId = e.replicaId;
304
319
  let t = e.includeTables ?? [];
305
- t.length === 0 && q.warn("cdc: no reactive tables to tail; Change Tracking reader idle. Set includeTables to enable.");
320
+ t.length === 0 && X.warn("cdc: no reactive tables to tail; Change Tracking reader idle. Set includeTables to enable.");
306
321
  let n = await this.readCdcOffset(e.replicaId);
307
322
  this.cdcHandle = await r({
308
323
  run: this.__mssqlReplicationFriend.runEffect,
@@ -312,9 +327,9 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
312
327
  onVersion: (e) => {
313
328
  this.cdcPendingVersion = e;
314
329
  },
315
- onError: (e) => q.warn("cdc: consumer error", {}, e),
330
+ onError: (e) => X.warn("cdc: consumer error", {}, e),
316
331
  onResync: () => {
317
- q.warn("cdc: resynced to current CT version after retention gap — subscriptions self-heal on the next change");
332
+ X.warn("cdc: resynced to current CT version after retention gap — subscriptions self-heal on the next change");
318
333
  }
319
334
  }), this.cdcCheckpointTimer = setInterval(() => {
320
335
  this.flushCdcOffset();
@@ -325,12 +340,12 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
325
340
  let t = this.sql, n = (await this.runtime.runPromise(t`
326
341
  SELECT TOP 1 ${t("ctVersion")} FROM ${t(i)}
327
342
  WHERE ${t("id")} = ${e}`))[0]?.ctVersion;
328
- return n ? (q.info("cdc: resuming from persisted CT version", {
343
+ return n ? (X.info("cdc: resuming from persisted CT version", {
329
344
  replicaId: e,
330
345
  version: n
331
346
  }), n) : null;
332
347
  } catch (t) {
333
- return q.warn("cdc: no readable offset; starting at current CT version", { replicaId: e }, t), null;
348
+ return X.warn("cdc: no readable offset; starting at current CT version", { replicaId: e }, t), null;
334
349
  }
335
350
  }
336
351
  async flushCdcOffset() {
@@ -350,7 +365,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
350
365
  update: ["ctVersion", "updatedAt"]
351
366
  }, null, null);
352
367
  } catch (t) {
353
- this.cdcPendingVersion = e, q.warn("cdc: checkpoint write failed", {}, t);
368
+ this.cdcPendingVersion = e, X.warn("cdc: checkpoint write failed", {}, t);
354
369
  }
355
370
  }
356
371
  }
@@ -405,16 +420,16 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
405
420
  }
406
421
  async emptyTablesOn(e, t) {
407
422
  if (e.length === 0) return;
408
- let n = this.sql, r = (e) => this.nsT(e), i = (e, t) => n.unsafe(`ALTER TABLE ${j(r(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), o = a.acquireUseRelease(a.forEach(e, (e) => i(e, !1), { discard: !0 }), () => a.forEach(e, (e) => n`DELETE FROM ${n(r(e))}`, { discard: !0 }), () => a.orDie(a.ignore(a.forEach(e, (e) => i(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(o) : a.provideService(o, this.sql.transactionService, t);
423
+ let n = this.sql, r = (e) => this.nsT(e), i = (e, t) => n.unsafe(`ALTER TABLE ${N(r(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), a = o.acquireUseRelease(o.forEach(e, (e) => i(e, !1), { discard: !0 }), () => o.forEach(e, (e) => n`DELETE FROM ${n(r(e))}`, { discard: !0 }), () => o.orDie(o.ignore(o.forEach(e, (e) => i(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(a) : o.provideService(a, this.sql.transactionService, t);
409
424
  await this.runtime.runPromise(s);
410
425
  }
411
426
  async transactional(e) {
412
427
  this.inflightTxns++;
413
428
  try {
414
- return await L({
429
+ return await z({
415
430
  ...this.txnSpec("MssqlStore.transactional"),
416
431
  work: e,
417
- makeView: (e, t) => new X(this, e, t)
432
+ makeView: (e, t) => new $(this, e, t)
418
433
  });
419
434
  } finally {
420
435
  this.inflightTxns--;
@@ -449,7 +464,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
449
464
  return this.changeStrategy === "cdc" ? "fleet" : "local";
450
465
  }
451
466
  injectExternalChange(e) {
452
- w(e.table) && this.emitter.emit("change", S(e));
467
+ E(e.table) && this.emitter.emit("change", w(e));
453
468
  }
454
469
  run(e) {
455
470
  return this.runtime.runPromise(e);
@@ -462,7 +477,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
462
477
  if (this.inflightTxns > 0) {
463
478
  let t = Date.now() + e;
464
479
  for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
465
- this.inflightTxns > 0 && q.warn("close: grace period expired with in-flight transactions", {
480
+ this.inflightTxns > 0 && X.warn("close: grace period expired with in-flight transactions", {
466
481
  gracePeriodMs: e,
467
482
  inflight: this.inflightTxns
468
483
  });
@@ -472,27 +487,32 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
472
487
  async ping() {
473
488
  await this.runtime.runPromise(this.sql`SELECT 1`);
474
489
  }
475
- }, X = class {
490
+ }, $ = class {
476
491
  parent;
477
492
  txn;
478
493
  attr;
479
494
  events = [];
480
- aborts = D((e) => n(e));
495
+ aborts = k((e) => n(e));
481
496
  committed = !1;
482
497
  constructor(e, t, n = void 0) {
483
498
  this.parent = e, this.txn = t, this.attr = n;
484
499
  }
485
- savepoint(e) {
486
- return I({
487
- tracker: this.aborts,
488
- name: `voltro_sp_${++this.savepointCounter}`,
489
- spelling: "mssql",
490
- exec: (e) => this.parent.run(a.provideService(K.pipe(a.flatMap((t) => t.unsafe(e))), this.parent.transactionService, this.txn))
491
- }, e);
500
+ async savepoint(e) {
501
+ let t = this.events.length;
502
+ try {
503
+ return await R({
504
+ tracker: this.aborts,
505
+ name: `voltro_sp_${++this.savepointCounter}`,
506
+ spelling: "mssql",
507
+ exec: (e) => this.parent.run(o.provideService(Y.pipe(o.flatMap((t) => t.unsafe(e))), this.parent.transactionService, this.txn))
508
+ }, e);
509
+ } catch (e) {
510
+ throw this.events.length = t, e;
511
+ }
492
512
  }
493
513
  savepointCounter = 0;
494
514
  run(e) {
495
- return this.aborts.track(() => this.parent.run(k(e, this.parent.transactionService, this.txn)));
515
+ return this.aborts.track(() => this.parent.run(j(e, this.parent.transactionService, this.txn)));
496
516
  }
497
517
  abortedBy() {
498
518
  return this.aborts.abortedBy();
@@ -500,6 +520,9 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
500
520
  raw(e, t) {
501
521
  return this.aborts.track(() => this.parent.rawOn(e, this.txn));
502
522
  }
523
+ integrityQuery(e) {
524
+ return this.query(e);
525
+ }
503
526
  query(e) {
504
527
  return this.aborts.track(() => this.parent.getInternalRunWithEager()(e, this.txn));
505
528
  }
@@ -509,8 +532,8 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
509
532
  insert(e, t) {
510
533
  return this.aborts.track(() => this.parent.getInternalExecuteInsert()(e, t, this.txn, this.events, this.attr));
511
534
  }
512
- insertMany(e, t) {
513
- return this.aborts.track(() => this.parent.getInternalExecuteInsertMany()(e, t, this.txn, this.events, this.attr));
535
+ insertMany(e, t, n) {
536
+ return this.aborts.track(() => this.parent.getInternalExecuteInsertMany()(e, t, this.txn, this.events, this.attr, n));
514
537
  }
515
538
  patchJson(e, t, n, r, i) {
516
539
  return this.aborts.track(() => this.parent.getInternalExecutePatchJson()(e, t, n, r, this.txn, this.events, this.attr, i));
@@ -546,8 +569,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
546
569
  throw Error("MssqlTransactionalView.injectExternalChange: not supported inside a transaction.");
547
570
  }
548
571
  commitEvents() {
549
- this.committed || (this.committed = !0, b(this.events, (e) => this.parent.emitChange(e)), this.events.length = 0);
572
+ this.committed || (this.committed = !0, S(this.events, (e) => this.parent.emitChange(e)), this.events.length = 0);
550
573
  }
551
574
  };
552
- //#endregion
553
- export { Y as MssqlStore, J as makeMssqlStore };
575
+ export { Q as MssqlStore, Z as makeMssqlStore };
@@ -1,6 +1,6 @@
1
1
  import { mssqlRowResultProjection as e, readMssqlPhysicalColumns as t } from "./rowResultProjection.js";
2
2
  import { Effect as n } from "effect";
3
- //#region src/writeOutput.ts
3
+ // src/writeOutput.ts
4
4
  var r = (r, i, a, o = !1) => n.uninterruptible(n.gen(function* () {
5
5
  let n = r.literal("[#voltro_write_output]"), s = yield* t(r, i), c = r.join(", ", !1)(s.map((e) => {
6
6
  let t = r.literal(`[${e.name.replaceAll("]", "]]")}]`);
@@ -14,5 +14,4 @@ var r = (r, i, a, o = !1) => n.uninterruptible(n.gen(function* () {
14
14
  DROP TABLE ${n};
15
15
  `;
16
16
  }));
17
- //#endregion
18
17
  export { r as writeOutput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/sql-mssql",
3
- "version": "0.86.0",
3
+ "version": "0.88.0",
4
4
  "description": "SQL Server (mssql) dialect adapter for Voltro's cross-dialect DataStore (OUTPUT-clause returning, OFFSET/FETCH paging, inline reactivity).",
5
5
  "keywords": [
6
6
  "voltro",
@@ -33,13 +33,13 @@
33
33
  "node": ">=24.0.0"
34
34
  },
35
35
  "dependencies": {
36
- "@effect/sql-mssql": "4.0.1",
37
- "@voltro/database": "0.86.0",
38
- "@voltro/logger": "0.86.0",
39
- "tedious": "20.3.3"
36
+ "@effect/sql-mssql": "4.1.0",
37
+ "@voltro/database": "0.88.0",
38
+ "@voltro/logger": "0.88.0",
39
+ "tedious": "20.3.8"
40
40
  },
41
41
  "peerDependencies": {
42
- "effect": "4.0.1"
42
+ "effect": "4.1.0"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"