@voltro/testing 0.65.0 → 0.66.1

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/dialect.js CHANGED
@@ -1,61 +1,81 @@
1
- import { _voltroMigrationPlansTable as e, boolean as t, bulkInsertLimitsFor as n, dropped as r, eq as i, id as a, integer as o, table as s, text as c, timestamp as l } from "@voltro/database";
2
- import { Effect as u } from "effect";
3
- import { _voltroUndoLogTable as d, applyInverses as f, synthesizeInverse as p } from "@voltro/runtime";
4
- import { afterEach as m, beforeEach as h, describe as g, expect as _, it as v } from "vitest";
5
- import { SqlClient as y } from "@effect/sql";
6
- import { applyPlan as b, applySchema as x, introspectSchema as S, planMigrations as C } from "@voltro/database/sql";
1
+ import { _voltroMigrationPlansTable as e, array as t, boolean as n, bulkInsertLimitsFor as r, dropped as i, eq as a, id as o, integer as s, json as c, registerTable as l, table as u, text as d, timestamp as f } from "@voltro/database";
2
+ import { Effect as p } from "effect";
3
+ import { _voltroUndoLogTable as m, applyInverses as h, makeSchemaRegistry as g, synthesizeInverse as _, wrapStoreWithMixinBehaviour as v } from "@voltro/runtime";
4
+ import { afterEach as y, beforeEach as b, describe as x, expect as S, it as C } from "vitest";
5
+ import { SqlClient as w } from "@effect/sql";
6
+ import { applyPlan as T, applySchema as E, introspectSchema as D, planMigrations as O } from "@voltro/database/sql";
7
7
  //#region src/dialectParity.ts
8
- var w = (e) => ({
8
+ var k = (e) => ({
9
9
  table: e,
10
10
  predicate: void 0,
11
11
  order: [],
12
12
  take: void 0,
13
13
  skip: void 0,
14
14
  projection: void 0
15
- }), T = s("voltro_parity_a", {
16
- id: a(),
17
- title: c(),
18
- count: o()
19
- }), E = s("voltro_parity_b", {
20
- id: a(),
21
- title: c()
22
- }), D = s("voltro_parity_c", {
23
- id: a(),
24
- title: c(),
25
- count: o(),
26
- flag: t().default(!1)
27
- }), O = s("voltro_parity_d", {
28
- id: a(),
29
- title: c(),
30
- at: l().nullable(),
31
- n: o().nullable()
32
- }), k = s("voltro_parity_upsert", {
33
- id: a(),
34
- teamId: c(),
35
- year: o(),
36
- hours: o().nullable()
37
- }).unique("byTeamYear", ["teamId", "year"]), A = s("voltro_parity_bulk", {
38
- id: a(),
39
- title: c(),
40
- count: o(),
41
- flag: t().default(!1)
42
- }), j = (e) => {
43
- let t = n(e);
15
+ }), A = u("voltro_parity_a", {
16
+ id: o(),
17
+ title: d(),
18
+ count: s()
19
+ }), j = u("voltro_parity_b", {
20
+ id: o(),
21
+ title: d()
22
+ }), M = u("voltro_parity_c", {
23
+ id: o(),
24
+ title: d(),
25
+ count: s(),
26
+ flag: n().default(!1)
27
+ }), N = u("voltro_parity_d", {
28
+ id: o(),
29
+ title: d(),
30
+ at: f().nullable().onUpdate("now"),
31
+ n: s().nullable()
32
+ }), P = u("voltro_parity_upsert", {
33
+ id: o(),
34
+ teamId: d(),
35
+ year: s(),
36
+ hours: s().nullable()
37
+ }).unique("byTeamYear", ["teamId", "year"]), F = u("voltro_parity_values", {
38
+ id: o(),
39
+ title: d().onUpdate(() => "automatic"),
40
+ metadata: c().nullable(),
41
+ labels: t(d()).nullable()
42
+ });
43
+ l(F);
44
+ var I = u("voltro_parity_json_names", {
45
+ id: o(),
46
+ key: c(),
47
+ value: c()
48
+ });
49
+ l(I);
50
+ var L = u("voltro_parity_composite", {
51
+ userId: d(),
52
+ orgId: d(),
53
+ role: d()
54
+ }).primaryKey(["userId", "orgId"]), R = u("voltro_parity_bulk", {
55
+ id: o(),
56
+ title: d(),
57
+ count: s(),
58
+ flag: n().default(!1)
59
+ }), z = (e) => {
60
+ let t = r(e);
44
61
  if (t === void 0) return 0;
45
- let r = Object.keys(A.fields).length;
46
- return Math.max(1, Math.min(Math.floor(t.maxBindParameters / r), t.maxRowsPerStatement ?? Infinity));
47
- }, M = (t) => {
48
- g(`dialect parity: ${t.name ?? t.dialect.id}`, () => {
62
+ let n = Object.keys(R.fields).length;
63
+ return Math.max(1, Math.min(Math.floor(t.maxBindParameters / n), t.maxRowsPerStatement ?? Infinity));
64
+ }, B = (t) => {
65
+ x(`dialect parity: ${t.name ?? t.dialect.id}`, () => {
49
66
  let n = null;
50
- h(async () => {
67
+ b(async () => {
51
68
  await t.setup(), n = await t.make(), await n.migrate([
52
- T,
53
- E,
54
- D,
55
- O,
56
69
  A,
57
- k,
58
- d
70
+ j,
71
+ M,
72
+ N,
73
+ R,
74
+ P,
75
+ L,
76
+ F,
77
+ I,
78
+ m
59
79
  ]);
60
80
  for (let e of [
61
81
  "voltro_parity_a",
@@ -63,151 +83,157 @@ var w = (e) => ({
63
83
  "voltro_parity_c",
64
84
  "voltro_parity_d",
65
85
  "voltro_parity_upsert",
86
+ "voltro_parity_values",
87
+ "voltro_parity_json_names",
66
88
  "_voltro_undo_log"
67
89
  ]) {
68
- let t = await n.store.query(w(e));
90
+ let t = await n.store.query(k(e));
69
91
  for (let r of t) await n.store.delete(e, r.id);
70
92
  }
71
- }), m(async () => {
93
+ for (let e of await n.store.query(k("voltro_parity_composite"))) await n.store.delete("voltro_parity_composite", {
94
+ userId: e.userId,
95
+ orgId: e.orgId
96
+ });
97
+ }), y(async () => {
72
98
  await n?.dispose(), await t.teardown(), n = null;
73
- }), v("rename-table: the rows move, and the plan converges", async () => {
74
- let r = "voltro_rename_src", i = "_voltro_rename_dst", o = n.run, l = async () => {
75
- await o(u.gen(function* () {
76
- let e = yield* y.SqlClient;
77
- for (let t of [i, r]) yield* u.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${t}`), () => []);
99
+ }), C("rename-table: the rows move, and the plan converges", async () => {
100
+ let r = "voltro_rename_src", i = "_voltro_rename_dst", a = n.run, s = async () => {
101
+ await a(p.gen(function* () {
102
+ let e = yield* w.SqlClient;
103
+ for (let t of [i, r]) yield* p.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${t}`), () => []);
78
104
  })).catch(() => {});
79
- }, d = () => o(u.gen(function* () {
80
- let e = yield* y.SqlClient, t = yield* S(e);
105
+ }, c = () => a(p.gen(function* () {
106
+ let e = yield* w.SqlClient, t = yield* D(e);
81
107
  return {
82
108
  ...t,
83
109
  tables: t.tables.filter((e) => e.name === r || e.name === i)
84
110
  };
85
- })), f = async () => C({
111
+ })), l = async () => O({
86
112
  declared: [m],
87
- live: await d(),
113
+ live: await c(),
88
114
  dialect: t.dialect.id
89
115
  });
90
- await l();
91
- let p = s(r, {
92
- id: a({ prefix: "rn" }),
93
- title: c()
94
- }), m = s(i, {
95
- id: a({ prefix: "rn" }),
96
- title: c()
116
+ await s();
117
+ let f = u(r, {
118
+ id: o({ prefix: "rn" }),
119
+ title: d()
120
+ }), m = u(i, {
121
+ id: o({ prefix: "rn" }),
122
+ title: d()
97
123
  }).renamedFrom(r);
98
- await n.migrate([p, e]), await n.store.insert(r, {
124
+ await n.migrate([f, e]), await n.store.insert(r, {
99
125
  id: "rn_1",
100
126
  title: "one"
101
127
  }), await n.store.insert(r, {
102
128
  id: "rn_2",
103
129
  title: "two"
104
130
  });
105
- let h = await f();
106
- _(h.operations.some((e) => e.op.kind === "rename-table"), "the marker must fold").toBe(!0), _(h.operations.filter((e) => e.blocked !== void 0), "nothing may be blocked").toEqual([]), await o(u.gen(function* () {
107
- let e = yield* y.SqlClient;
108
- return yield* b(e, h, {
131
+ let h = await l();
132
+ S(h.operations.some((e) => e.op.kind === "rename-table"), "the marker must fold").toBe(!0), S(h.operations.filter((e) => e.blocked !== void 0), "nothing may be blocked").toEqual([]), await a(p.gen(function* () {
133
+ let e = yield* w.SqlClient;
134
+ return yield* T(e, h, {
109
135
  declared: [m],
110
136
  appliedBy: "dialect-parity",
111
137
  environment: "dev",
112
138
  source: "auto-diff",
113
- replan: () => u.promise(f)
139
+ replan: () => p.promise(l)
114
140
  });
115
141
  }));
116
- let g = await n.store.query(w(i));
117
- _(g.map((e) => e.id).sort(), "every row survived the rename").toEqual(["rn_1", "rn_2"]), _((await f()).operations, `${t.dialect.id}: the plan must converge`).toEqual([]), await l();
118
- }), v("schema evolution: create → add column → add index → drop column, converging at each step", async () => {
119
- let i = "voltro_parity_evolve", l = n.run, d = async () => {
120
- await l(u.gen(function* () {
121
- let e = yield* y.SqlClient;
122
- yield* u.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${i}`), () => []);
142
+ let g = await n.store.query(k(i));
143
+ S(g.map((e) => e.id).sort(), "every row survived the rename").toEqual(["rn_1", "rn_2"]), S((await l()).operations, `${t.dialect.id}: the plan must converge`).toEqual([]), await s();
144
+ }), C("schema evolution: create → add column → add index → drop column, converging at each step", async () => {
145
+ let r = "voltro_parity_evolve", a = n.run, c = async () => {
146
+ await a(p.gen(function* () {
147
+ let e = yield* w.SqlClient;
148
+ yield* p.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${r}`), () => []);
123
149
  })).catch(() => {});
124
- }, f = () => l(u.gen(function* () {
125
- let e = yield* y.SqlClient, t = yield* S(e);
150
+ }, l = () => a(p.gen(function* () {
151
+ let e = yield* w.SqlClient, t = yield* D(e);
126
152
  return {
127
153
  ...t,
128
- tables: t.tables.filter((e) => e.name === i)
154
+ tables: t.tables.filter((e) => e.name === r)
129
155
  };
130
- })), p = async (e) => C({
156
+ })), f = async (e) => O({
131
157
  declared: e,
132
- live: await f(),
158
+ live: await l(),
133
159
  dialect: t.dialect.id
134
- }), m = async () => (await f()).tables[0]?.columns.map((e) => e.name) ?? [], h = async (e, n) => {
135
- let r = await p(e);
136
- n && _(r.operations.length, `${t.dialect.id}: nothing to apply — the step asserts nothing`).toBeGreaterThan(0), _(r.operations.filter((e) => e.blocked !== void 0), `${t.dialect.id}: nothing may be blocked`).toEqual([]), r.operations.length !== 0 && (await l(u.gen(function* () {
137
- let n = yield* y.SqlClient;
138
- return yield* b(n, r, {
160
+ }), m = async () => (await l()).tables[0]?.columns.map((e) => e.name) ?? [], h = async (e, n) => {
161
+ let i = await f(e);
162
+ n && S(i.operations.length, `${t.dialect.id}: nothing to apply — the step asserts nothing`).toBeGreaterThan(0), S(i.operations.filter((e) => e.blocked !== void 0), `${t.dialect.id}: nothing may be blocked`).toEqual([]), i.operations.length !== 0 && (await a(p.gen(function* () {
163
+ let n = yield* w.SqlClient;
164
+ return yield* T(n, i, {
139
165
  declared: e,
140
166
  appliedBy: "dialect-parity",
141
167
  environment: "dev",
142
168
  source: "auto-diff",
143
- replan: (n) => u.map(S(n), (n) => C({
169
+ replan: (n) => p.map(D(n), (n) => O({
144
170
  declared: e,
145
171
  live: {
146
172
  ...n,
147
- tables: n.tables.filter((e) => e.name === i)
173
+ tables: n.tables.filter((e) => e.name === r)
148
174
  },
149
175
  dialect: t.dialect.id
150
176
  }))
151
177
  });
152
- })), _((await p(e)).operations, `${t.dialect.id}: the plan must converge`).toEqual([]));
178
+ })), S((await f(e)).operations, `${t.dialect.id}: the plan must converge`).toEqual([]));
153
179
  };
154
- await d(), await n.migrate([e]), await h([s(i, {
155
- id: a({ prefix: "ev" }),
156
- name: c()
157
- })], !0), _(await m(), `${t.dialect.id}: v1 columns`).toEqual(["id", "name"]), await n.store.insert(i, {
180
+ await c(), await n.migrate([e]), await h([u(r, {
181
+ id: o({ prefix: "ev" }),
182
+ name: d()
183
+ })], !0), S(await m(), `${t.dialect.id}: v1 columns`).toEqual(["id", "name"]), await n.store.insert(r, {
158
184
  id: "ev_1",
159
185
  name: "one"
160
- }), await n.store.insert(i, {
186
+ }), await n.store.insert(r, {
161
187
  id: "ev_2",
162
188
  name: "two"
163
- }), await h([s(i, {
164
- id: a({ prefix: "ev" }),
165
- name: c(),
166
- qty: o().nullable()
167
- })], !0), _(await m()).toContain("qty"), await h([s(i, {
168
- id: a({ prefix: "ev" }),
169
- name: c(),
170
- qty: o().nullable()
171
- }).index(["qty"])], !0), await h([s(i, {
172
- id: a({ prefix: "ev" }),
173
- name: c(),
174
- qty: r()
175
- })], !0), _(await m(), `${t.dialect.id}: v4 columns`).toEqual(["id", "name"]);
176
- let g = await n.store.query(w(i));
177
- _(g.map((e) => e.id).sort(), `${t.dialect.id}: rows survived the evolution`).toEqual(["ev_1", "ev_2"]), await d();
178
- }), v("re-applying a create-table plan is a no-op, indexes included", async () => {
179
- let r = "voltro_parity_reapply", i = n.run, l = async () => {
180
- await i(u.gen(function* () {
181
- let e = yield* y.SqlClient;
182
- yield* u.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${r}`), () => []);
189
+ }), await h([u(r, {
190
+ id: o({ prefix: "ev" }),
191
+ name: d(),
192
+ qty: s().nullable()
193
+ })], !0), S(await m()).toContain("qty"), await h([u(r, {
194
+ id: o({ prefix: "ev" }),
195
+ name: d(),
196
+ qty: s().nullable()
197
+ }).index(["qty"])], !0), await h([u(r, {
198
+ id: o({ prefix: "ev" }),
199
+ name: d(),
200
+ qty: i()
201
+ })], !0), S(await m(), `${t.dialect.id}: v4 columns`).toEqual(["id", "name"]);
202
+ let g = await n.store.query(k(r));
203
+ S(g.map((e) => e.id).sort(), `${t.dialect.id}: rows survived the evolution`).toEqual(["ev_1", "ev_2"]), await c();
204
+ }), C("re-applying a create-table plan is a no-op, indexes included", async () => {
205
+ let r = "voltro_parity_reapply", i = n.run, a = async () => {
206
+ await i(p.gen(function* () {
207
+ let e = yield* w.SqlClient;
208
+ yield* p.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${r}`), () => []);
183
209
  })).catch(() => {});
184
- }, d = () => i(u.gen(function* () {
185
- let e = yield* y.SqlClient, t = yield* S(e);
210
+ }, c = () => i(p.gen(function* () {
211
+ let e = yield* w.SqlClient, t = yield* D(e);
186
212
  return {
187
213
  ...t,
188
214
  tables: t.tables.filter((e) => e.name === r)
189
215
  };
190
- })), f = s(r, {
191
- id: a({ prefix: "ra" }),
192
- name: c(),
193
- qty: o().nullable()
194
- }).index(["qty"]), p = async () => C({
195
- declared: [f],
196
- live: await d(),
216
+ })), l = u(r, {
217
+ id: o({ prefix: "ra" }),
218
+ name: d(),
219
+ qty: s().nullable()
220
+ }).index(["qty"]), f = async () => O({
221
+ declared: [l],
222
+ live: await c(),
197
223
  dialect: t.dialect.id
198
224
  });
199
- await l(), await n.migrate([e]);
200
- let m = await p();
201
- _(m.operations.some((e) => e.op.kind === "create-table"), `${t.dialect.id}: expected a create-table to re-apply`).toBe(!0);
202
- for (let e = 0; e < 2; e++) await i(u.gen(function* () {
203
- let e = yield* y.SqlClient;
204
- return yield* b(e, m, {
205
- declared: [f],
225
+ await a(), await n.migrate([e]);
226
+ let m = await f();
227
+ S(m.operations.some((e) => e.op.kind === "create-table"), `${t.dialect.id}: expected a create-table to re-apply`).toBe(!0);
228
+ for (let e = 0; e < 2; e++) await i(p.gen(function* () {
229
+ let e = yield* w.SqlClient;
230
+ return yield* T(e, m, {
231
+ declared: [l],
206
232
  appliedBy: "dialect-parity",
207
233
  environment: "dev",
208
234
  source: "auto-diff",
209
- replan: (e) => u.map(S(e), (e) => C({
210
- declared: [f],
235
+ replan: (e) => p.map(D(e), (e) => O({
236
+ declared: [l],
211
237
  live: {
212
238
  ...e,
213
239
  tables: e.tables.filter((e) => e.name === r)
@@ -216,71 +242,115 @@ var w = (e) => ({
216
242
  }))
217
243
  });
218
244
  }));
219
- _((await p()).operations, `${t.dialect.id}: the re-applied plan must converge`).toEqual([]), await l();
245
+ S((await f()).operations, `${t.dialect.id}: the re-applied plan must converge`).toEqual([]), await a();
220
246
  });
221
- let l = "voltro_parity_bulk", g = () => n.run(u.gen(function* () {
222
- let e = yield* y.SqlClient;
223
- yield* u.orElseSucceed(e.unsafe(`DELETE FROM ${l}`), () => []);
224
- })), x = (e, t) => Array.from({ length: e }, (e, n) => ({
247
+ let r = "voltro_parity_bulk", c = () => n.run(p.gen(function* () {
248
+ let e = yield* w.SqlClient;
249
+ yield* p.orElseSucceed(e.unsafe(`DELETE FROM ${r}`), () => []);
250
+ })), l = (e, t) => Array.from({ length: e }, (e, n) => ({
225
251
  id: `${t}_${String(n).padStart(6, "0")}`,
226
252
  title: `row ${n}`,
227
253
  count: n,
228
254
  flag: !1
229
255
  }));
230
- v("insertMany past this dialect's one-statement ceiling lands EVERY row", async () => {
231
- let e = j(t.dialect.id);
232
- _(e, `no bulk-insert limits are declared for '${t.dialect.id}' — a dialect with no entry chunks at nothing, so this scenario would pass having tested nothing`).toBeGreaterThan(0);
233
- let r = e + 5;
234
- await g();
235
- let i = await n.store.insertMany(l, x(r, "bulk"));
236
- _(i.length, `insertMany returned ${i.length} of ${r} post-images`).toBe(r), _(i[0]?.id).toBe("bulk_000000"), _(i[r - 1]?.id).toBe(`bulk_${String(r - 1).padStart(6, "0")}`);
237
- let a = await n.store.query(w(l));
238
- _(a.length, "the database holds fewer rows than insertMany reported").toBe(r), await g();
239
- }, 12e4), v("a chunked insertMany is still ALL-OR-NOTHING", async () => {
240
- let e = j(t.dialect.id) + 5;
241
- await g();
242
- let r = x(e, "atomic");
243
- r[e - 1] = {
244
- ...r[e - 1],
245
- id: r[0].id
246
- }, await _(n.store.insertMany(l, r), "a duplicate primary key must still reject the whole call").rejects.toThrow();
247
- let i = await n.store.query(w(l));
248
- _(i.length, `${t.dialect.id}: ${i.length} rows survived a FAILED insertMany — chunking introduced partial success. The chunks must run inside one transaction when the caller holds none.`).toBe(0), await g();
249
- }, 12e4), v("DDL is idempotent — re-applying the schema is a no-op", async () => {
250
- await n.migrate([T, E]);
251
- }), v("insert + query round-trips a row", async () => {
256
+ C("insertMany past this dialect's one-statement ceiling lands EVERY row", async () => {
257
+ let e = z(t.dialect.id);
258
+ S(e, `no bulk-insert limits are declared for '${t.dialect.id}' — a dialect with no entry chunks at nothing, so this scenario would pass having tested nothing`).toBeGreaterThan(0);
259
+ let i = e + 5;
260
+ await c();
261
+ let a = await n.store.insertMany(r, l(i, "bulk"));
262
+ S(a.length, `insertMany returned ${a.length} of ${i} post-images`).toBe(i), S(a[0]?.id).toBe("bulk_000000"), S(a[i - 1]?.id).toBe(`bulk_${String(i - 1).padStart(6, "0")}`);
263
+ let o = await n.store.query(k(r));
264
+ S(o.length, "the database holds fewer rows than insertMany reported").toBe(i), await c();
265
+ }, 12e4), C("a chunked insertMany is still ALL-OR-NOTHING", async () => {
266
+ let e = z(t.dialect.id) + 5;
267
+ await c();
268
+ let i = l(e, "atomic");
269
+ i[e - 1] = {
270
+ ...i[e - 1],
271
+ id: i[0].id
272
+ }, await S(n.store.insertMany(r, i), "a duplicate primary key must still reject the whole call").rejects.toThrow();
273
+ let a = await n.store.query(k(r));
274
+ S(a.length, `${t.dialect.id}: ${a.length} rows survived a FAILED insertMany — chunking introduced partial success. The chunks must run inside one transaction when the caller holds none.`).toBe(0), await c();
275
+ }, 12e4), C("DDL is idempotent — re-applying the schema is a no-op", async () => {
276
+ await n.migrate([A, j]);
277
+ }), C("insert + query round-trips a row", async () => {
252
278
  let e = await n.store.insert("voltro_parity_a", {
253
279
  id: "a1",
254
280
  title: "one",
255
281
  count: 1
256
282
  });
257
- _(e).toMatchObject({
283
+ S(e).toMatchObject({
258
284
  id: "a1",
259
285
  title: "one",
260
286
  count: 1
261
287
  });
262
- let t = await n.store.query(w("voltro_parity_a"));
263
- _(t.length).toBe(1), _(t[0]?.id).toBe("a1");
264
- }), v("update returns the post-image", async () => {
288
+ let t = await n.store.query(k("voltro_parity_a"));
289
+ S(t.length).toBe(1), S(t[0]?.id).toBe("a1");
290
+ }), C("update returns the post-image", async () => {
265
291
  await n.store.insert("voltro_parity_a", {
266
292
  id: "a2",
267
293
  title: "pre",
268
294
  count: 1
269
295
  });
270
296
  let e = await n.store.update("voltro_parity_a", "a2", { title: "post" });
271
- _(e).toMatchObject({
297
+ S(e).toMatchObject({
272
298
  id: "a2",
273
299
  title: "post"
274
300
  });
275
- }), v("delete removes the row + reports true", async () => {
301
+ }), C("delete removes the row + reports true", async () => {
276
302
  await n.store.insert("voltro_parity_a", {
277
303
  id: "a3",
278
304
  title: "x",
279
305
  count: 1
280
- }), _(await n.store.delete("voltro_parity_a", "a3")).toBe(!0);
281
- let e = await n.store.query(w("voltro_parity_a"));
282
- _(e.length).toBe(0);
283
- }), v("undo: the _voltro_undo_log TEXT changes column round-trips a JSON ChangeSet", async () => {
306
+ }), S(await n.store.delete("voltro_parity_a", "a3")).toBe(!0);
307
+ let e = await n.store.query(k("voltro_parity_a"));
308
+ S(e.length).toBe(0);
309
+ }), C("a composite key addresses the row, and only that row", async () => {
310
+ await n.store.insert("voltro_parity_composite", {
311
+ userId: "u1",
312
+ orgId: "o1",
313
+ role: "admin"
314
+ }), await n.store.insert("voltro_parity_composite", {
315
+ userId: "u1",
316
+ orgId: "o2",
317
+ role: "viewer"
318
+ });
319
+ let e = await n.store.update("voltro_parity_composite", {
320
+ userId: "u1",
321
+ orgId: "o2"
322
+ }, { role: "member" });
323
+ S(e).toMatchObject({
324
+ userId: "u1",
325
+ orgId: "o2",
326
+ role: "member"
327
+ });
328
+ let t = await n.store.query(k("voltro_parity_composite")), r = new Map(t.map((e) => [e.orgId, e.role]));
329
+ S(r.get("o1")).toBe("admin"), S(r.get("o2")).toBe("member");
330
+ }), C("a composite key that matches nothing is `null` / `false`, not an error", async () => {
331
+ S(await n.store.update("voltro_parity_composite", {
332
+ userId: "nobody",
333
+ orgId: "nowhere"
334
+ }, { role: "x" })).toBeNull(), S(await n.store.delete("voltro_parity_composite", {
335
+ userId: "nobody",
336
+ orgId: "nowhere"
337
+ })).toBe(!1);
338
+ }), C("a composite key deletes exactly the row it names", async () => {
339
+ await n.store.insert("voltro_parity_composite", {
340
+ userId: "u2",
341
+ orgId: "o1",
342
+ role: "admin"
343
+ }), await n.store.insert("voltro_parity_composite", {
344
+ userId: "u2",
345
+ orgId: "o2",
346
+ role: "viewer"
347
+ }), S(await n.store.delete("voltro_parity_composite", {
348
+ userId: "u2",
349
+ orgId: "o1"
350
+ })).toBe(!0);
351
+ let e = (await n.store.query(k("voltro_parity_composite"))).filter((e) => e.userId === "u2").map((e) => e.orgId);
352
+ S(e).toEqual(["o2"]);
353
+ }), C("undo: the _voltro_undo_log TEXT changes column round-trips a JSON ChangeSet", async () => {
284
354
  let e = [{
285
355
  table: "voltro_parity_c",
286
356
  op: "update",
@@ -310,9 +380,9 @@ var w = (e) => ({
310
380
  undone: !1,
311
381
  createdAt: /* @__PURE__ */ new Date()
312
382
  });
313
- let t = await n.store.query(w("_voltro_undo_log"));
314
- _(t.length).toBe(1), _(JSON.parse(t[0].changes)).toEqual(e);
315
- }), v("undo: reverts an INSERT (inverse delete) on this dialect", async () => {
383
+ let t = await n.store.query(k("_voltro_undo_log"));
384
+ S(t.length).toBe(1), S(JSON.parse(t[0].changes)).toEqual(e);
385
+ }), C("undo: reverts an INSERT (inverse delete) on this dialect", async () => {
316
386
  let e = {
317
387
  invocationId: "inv1",
318
388
  subject: null,
@@ -327,10 +397,10 @@ var w = (e) => ({
327
397
  })
328
398
  }]
329
399
  };
330
- await f(n.store, p(e));
331
- let t = await n.store.query(w("voltro_parity_c"));
332
- _(t.find((e) => e.id === "c2")).toBeUndefined();
333
- }), v("undo: reverts an UPDATE including the BOOLEAN, restoring the captured value FAITHFULLY", async () => {
400
+ await h(n.store, _(e));
401
+ let t = await n.store.query(k("voltro_parity_c"));
402
+ S(t.find((e) => e.id === "c2")).toBeUndefined();
403
+ }), C("undo: reverts an UPDATE including the BOOLEAN, restoring the captured value FAITHFULLY", async () => {
334
404
  await n.store.insert("voltro_parity_c", {
335
405
  id: "c3",
336
406
  title: "t",
@@ -338,13 +408,13 @@ var w = (e) => ({
338
408
  flag: !0
339
409
  });
340
410
  let e = (await n.store.query({
341
- ...w("voltro_parity_c"),
342
- predicate: i("id", "c3")
411
+ ...k("voltro_parity_c"),
412
+ predicate: a("id", "c3")
343
413
  }))[0], t = await n.store.update("voltro_parity_c", "c3", {
344
414
  count: 2,
345
415
  flag: !1
346
416
  });
347
- _(t.flag).not.toEqual(e.flag);
417
+ S(t.flag).not.toEqual(e.flag);
348
418
  let r = {
349
419
  invocationId: "inv2",
350
420
  subject: null,
@@ -356,13 +426,13 @@ var w = (e) => ({
356
426
  next: t
357
427
  }]
358
428
  };
359
- await f(n.store, p(r));
360
- let a = (await n.store.query({
361
- ...w("voltro_parity_c"),
362
- predicate: i("id", "c3")
429
+ await h(n.store, _(r));
430
+ let i = (await n.store.query({
431
+ ...k("voltro_parity_c"),
432
+ predicate: a("id", "c3")
363
433
  }))[0];
364
- _(a.flag).toEqual(e.flag), _(a.count).toEqual(e.count);
365
- }), v("undo: reverts a DELETE (inverse re-insert) on this dialect", async () => {
434
+ S(i.flag).toEqual(e.flag), S(i.count).toEqual(e.count);
435
+ }), C("undo: reverts a DELETE (inverse re-insert) on this dialect", async () => {
366
436
  let e = await n.store.insert("voltro_parity_c", {
367
437
  id: "c4",
368
438
  title: "gone",
@@ -380,24 +450,24 @@ var w = (e) => ({
380
450
  prev: e
381
451
  }]
382
452
  };
383
- await f(n.store, p(t));
453
+ await h(n.store, _(t));
384
454
  let r = (await n.store.query({
385
- ...w("voltro_parity_c"),
386
- predicate: i("id", "c4")
455
+ ...k("voltro_parity_c"),
456
+ predicate: a("id", "c4")
387
457
  }))[0];
388
- _(r.id).toBe("c4"), _(r.title).toBe("gone"), _(r.flag).toEqual(e.flag);
389
- }), v("onChange fires insert + update + delete events", async () => {
458
+ S(r.id).toBe("c4"), S(r.title).toBe("gone"), S(r.flag).toEqual(e.flag);
459
+ }), C("onChange fires insert + update + delete events", async () => {
390
460
  let e = [], t = n.store.onChange((t) => e.push(t.op));
391
461
  await n.store.insert("voltro_parity_a", {
392
462
  id: "a4",
393
463
  title: "a",
394
464
  count: 1
395
- }), await n.store.update("voltro_parity_a", "a4", { title: "b" }), await n.store.delete("voltro_parity_a", "a4"), t(), _(e).toEqual([
465
+ }), await n.store.update("voltro_parity_a", "a4", { title: "b" }), await n.store.delete("voltro_parity_a", "a4"), t(), S(e).toEqual([
396
466
  "insert",
397
467
  "update",
398
468
  "delete"
399
469
  ]);
400
- }), v("binding more than 10 change listeners emits no MaxListeners warning", async () => {
470
+ }), C("binding more than 10 change listeners emits no MaxListeners warning", async () => {
401
471
  let e = [], t = (t) => {
402
472
  e.push(t.name);
403
473
  };
@@ -405,19 +475,19 @@ var w = (e) => ({
405
475
  let r = Array.from({ length: 32 }, () => n.store.onChange(() => {}));
406
476
  await new Promise((e) => setImmediate(e));
407
477
  for (let e of r) e();
408
- process.off("warning", t), _(e.filter((e) => e === "MaxListenersExceededWarning"), "the change bus still warns at 11 listeners — `raiseChangeListenerCeiling` is not wired into this dialect’s store").toEqual([]);
409
- }), v("transactional rolls back on throw + drops queued events", async () => {
478
+ process.off("warning", t), S(e.filter((e) => e === "MaxListenersExceededWarning"), "the change bus still warns at 11 listeners — `raiseChangeListenerCeiling` is not wired into this dialect’s store").toEqual([]);
479
+ }), C("transactional rolls back on throw + drops queued events", async () => {
410
480
  let e = [], t = n.store.onChange((t) => e.push(t.op));
411
- await _(n.store.transactional(async (e) => {
481
+ await S(n.store.transactional(async (e) => {
412
482
  throw await e.insert("voltro_parity_a", {
413
483
  id: "rollback",
414
484
  title: "r",
415
485
  count: 0
416
486
  }), Error("intentional rollback");
417
- })).rejects.toThrow("intentional rollback"), t(), _(e).toEqual([]);
418
- let r = await n.store.query(w("voltro_parity_a"));
419
- _(r.length).toBe(0);
420
- }), v("transactional commit drains queued events in order", async () => {
487
+ })).rejects.toThrow("intentional rollback"), t(), S(e).toEqual([]);
488
+ let r = await n.store.query(k("voltro_parity_a"));
489
+ S(r.length).toBe(0);
490
+ }), C("transactional commit drains queued events in order", async () => {
421
491
  let e = [], t = n.store.onChange((t) => e.push(t.op));
422
492
  await n.store.transactional(async (e) => {
423
493
  await e.insert("voltro_parity_a", {
@@ -429,8 +499,8 @@ var w = (e) => ({
429
499
  title: "b",
430
500
  count: 2
431
501
  });
432
- }), t(), _(e).toEqual(["insert", "insert"]);
433
- }), v("upsert inserts a new row, then updates on conflict — no duplicate", async () => {
502
+ }), t(), S(e).toEqual(["insert", "insert"]);
503
+ }), C("upsert inserts a new row, then updates on conflict — no duplicate", async () => {
434
504
  await n.store.upsert("voltro_parity_a", {
435
505
  id: "u1",
436
506
  title: "first",
@@ -443,13 +513,370 @@ var w = (e) => ({
443
513
  conflictColumns: ["id"],
444
514
  update: ["title", "count"]
445
515
  });
446
- let e = await n.store.query(w("voltro_parity_a"));
447
- _(e.length).toBe(1), _(e[0]).toMatchObject({
516
+ let e = await n.store.query(k("voltro_parity_a"));
517
+ S(e.length).toBe(1), S(e[0]).toMatchObject({
448
518
  id: "u1",
449
519
  title: "second",
450
520
  count: 2
451
521
  });
452
- }), v("upsert on a NON-primary-key unique constraint updates that row", async () => {
522
+ }), x.each(["direct", "transactional"])("JSON patch and column onUpdate (%s)", (e) => {
523
+ let t = (t) => e === "transactional" ? n.store.transactional(t) : t(n.store), r = [
524
+ {
525
+ name: "shallow object merge retains unrelated keys and nulls",
526
+ before: {
527
+ keep: 1,
528
+ child: { old: !0 }
529
+ },
530
+ path: "metadata",
531
+ value: {
532
+ child: { new: !0 },
533
+ added: null
534
+ },
535
+ after: {
536
+ keep: 1,
537
+ child: { new: !0 },
538
+ added: null
539
+ }
540
+ },
541
+ {
542
+ name: "array replacement",
543
+ before: { keep: 1 },
544
+ path: "metadata",
545
+ value: [
546
+ 1,
547
+ null,
548
+ !1
549
+ ],
550
+ after: [
551
+ 1,
552
+ null,
553
+ !1
554
+ ]
555
+ },
556
+ {
557
+ name: "empty object replaces an array",
558
+ before: ["old"],
559
+ path: "metadata",
560
+ value: {},
561
+ after: {}
562
+ },
563
+ {
564
+ name: "object from SQL NULL",
565
+ before: null,
566
+ path: "metadata",
567
+ value: { a: !1 },
568
+ after: { a: !1 }
569
+ },
570
+ {
571
+ name: "Unicode keys and values survive storage and patching",
572
+ before: {
573
+ 雪: { keep: "Ελληνικά" },
574
+ Grüße: "👋"
575
+ },
576
+ path: "metadata.雪.changed",
577
+ value: "こんにちは 🌍",
578
+ after: {
579
+ 雪: {
580
+ keep: "Ελληνικά",
581
+ changed: "こんにちは 🌍"
582
+ },
583
+ Grüße: "👋"
584
+ }
585
+ },
586
+ {
587
+ name: "missing deep parents",
588
+ before: { keep: 1 },
589
+ path: "metadata.a.b.c",
590
+ value: "deep",
591
+ after: {
592
+ keep: 1,
593
+ a: { b: { c: "deep" } }
594
+ }
595
+ },
596
+ {
597
+ name: "scalar parent becomes an object",
598
+ before: {
599
+ a: 1,
600
+ keep: !0
601
+ },
602
+ path: "metadata.a.b",
603
+ value: 0,
604
+ after: {
605
+ a: { b: 0 },
606
+ keep: !0
607
+ }
608
+ },
609
+ {
610
+ name: "numeric segments are object keys, not array indices",
611
+ before: { a: [{ old: !0 }] },
612
+ path: "metadata.a.0.b",
613
+ value: !1,
614
+ after: { a: { 0: { b: !1 } } }
615
+ },
616
+ {
617
+ name: "nested siblings survive",
618
+ before: { a: {
619
+ keep: !0,
620
+ b: {
621
+ old: 1,
622
+ c: "before"
623
+ }
624
+ } },
625
+ path: "metadata.a.b.c",
626
+ value: "after",
627
+ after: { a: {
628
+ keep: !0,
629
+ b: {
630
+ old: 1,
631
+ c: "after"
632
+ }
633
+ } }
634
+ },
635
+ {
636
+ name: "literal top-level keys with punctuation",
637
+ before: { keep: !0 },
638
+ path: "metadata",
639
+ value: {
640
+ "a.b": null,
641
+ "a\"b": 0,
642
+ "a\\b": !1
643
+ },
644
+ after: {
645
+ keep: !0,
646
+ "a.b": null,
647
+ "a\"b": 0,
648
+ "a\\b": !1
649
+ }
650
+ },
651
+ {
652
+ name: "escaped nested keys preserve existing siblings and value types",
653
+ before: {
654
+ "a\"b": {
655
+ keep: [null, !0],
656
+ "c\\d": { old: !0 }
657
+ },
658
+ text: "kept",
659
+ false: !1,
660
+ zero: 0,
661
+ nil: null
662
+ },
663
+ path: "metadata.a\"b.c\\d.changed",
664
+ value: !1,
665
+ after: {
666
+ "a\"b": {
667
+ keep: [null, !0],
668
+ "c\\d": {
669
+ old: !0,
670
+ changed: !1
671
+ }
672
+ },
673
+ text: "kept",
674
+ false: !1,
675
+ zero: 0,
676
+ nil: null
677
+ }
678
+ },
679
+ {
680
+ name: "escaped merge retains unrelated escaped siblings",
681
+ before: {
682
+ "c\\d": [!0, null],
683
+ "literal\\n": !1,
684
+ "line\nkey": 0,
685
+ "a\"b": { old: !0 }
686
+ },
687
+ path: "metadata",
688
+ value: {
689
+ "a\"b": { new: !0 },
690
+ "new\\key": null
691
+ },
692
+ after: {
693
+ "c\\d": [!0, null],
694
+ "literal\\n": !1,
695
+ "line\nkey": 0,
696
+ "a\"b": { new: !0 },
697
+ "new\\key": null
698
+ }
699
+ },
700
+ ...[
701
+ "a\"b",
702
+ "c\\d",
703
+ "x\ny",
704
+ "tab key",
705
+ "literal\\n",
706
+ "slash\\\"quote",
707
+ "multiple\\\\end",
708
+ "literal\\u0061"
709
+ ].map((e) => ({
710
+ name: `escaped parent ${JSON.stringify(e)} is decoded exactly once`,
711
+ before: { [e]: { keep: !0 } },
712
+ path: `metadata.${e}.changed`,
713
+ value: !1,
714
+ after: { [e]: {
715
+ keep: !0,
716
+ changed: !1
717
+ } }
718
+ })),
719
+ ...[
720
+ null,
721
+ !1,
722
+ 0,
723
+ "",
724
+ "O'Brien'); DROP TABLE nowhere; --",
725
+ ["a", null],
726
+ { a: !0 }
727
+ ].map((e) => ({
728
+ name: `nested ${JSON.stringify(e)}`,
729
+ before: {
730
+ keep: 1,
731
+ value: "old"
732
+ },
733
+ path: "metadata.value",
734
+ value: e,
735
+ after: {
736
+ keep: 1,
737
+ value: e
738
+ }
739
+ }))
740
+ ];
741
+ C.each(r)("$name with companion fields in the same write", async ({ before: e, path: n, value: r, after: i }) => {
742
+ await t(async (t) => {
743
+ await t.insert("voltro_parity_values", {
744
+ id: "patch",
745
+ title: "before",
746
+ metadata: e,
747
+ labels: ["old"]
748
+ });
749
+ let a = await t.patchJson("voltro_parity_values", "patch", n, r, {
750
+ title: "after",
751
+ labels: []
752
+ });
753
+ S(a).toMatchObject({
754
+ id: "patch",
755
+ title: "after"
756
+ }), S(await t.query(k("voltro_parity_values"))).toEqual([{
757
+ id: "patch",
758
+ title: "after",
759
+ metadata: i,
760
+ labels: []
761
+ }]);
762
+ });
763
+ }), C("refuses companion primary-key or JSON-column replacement before writing", async () => {
764
+ await t(async (e) => {
765
+ let t = {
766
+ id: "refuse",
767
+ title: "keep",
768
+ metadata: { keep: !0 },
769
+ labels: []
770
+ };
771
+ await e.insert("voltro_parity_values", t);
772
+ for (let t of [{ id: "renamed" }, { metadata: {} }]) await S(e.patchJson("voltro_parity_values", "refuse", "metadata.value", 1, t)).rejects.toThrow("cannot rewrite");
773
+ S(await e.query(k("voltro_parity_values"))).toEqual([t]), S(await e.patchJson("voltro_parity_values", "missing", "metadata.value", 1, { title: "absent" })).toBeNull();
774
+ });
775
+ }), C("does not confuse JSON columns named key/value with iterator columns", async () => {
776
+ await t(async (e) => {
777
+ await e.insert(I.tableName, {
778
+ id: "names",
779
+ key: { "a\"b": { keep: !0 } },
780
+ value: { "c\\d": { keep: !1 } }
781
+ }), await e.patchJson(I.tableName, "names", "key.a\"b.changed", !1), await e.patchJson(I.tableName, "names", "value.c\\d.changed", !0), S(await e.query(k(I.tableName))).toEqual([{
782
+ id: "names",
783
+ key: { "a\"b": {
784
+ keep: !0,
785
+ changed: !1
786
+ } },
787
+ value: { "c\\d": {
788
+ keep: !1,
789
+ changed: !0
790
+ } }
791
+ }]);
792
+ });
793
+ }), C("executes application onUpdate across keyed, bulk, upsert and JSON writes", async () => {
794
+ let t = g([{
795
+ tableName: N.tableName,
796
+ fields: N.fields
797
+ }, {
798
+ tableName: F.tableName,
799
+ fields: F.fields
800
+ }]), r = v(n.store, {
801
+ subject: {
802
+ type: "anonymous",
803
+ id: null,
804
+ tenantId: null
805
+ },
806
+ schemaRegistry: t
807
+ }), i = async (e) => {
808
+ let t = /* @__PURE__ */ new Date("2026-01-01T00:00:00.000Z"), n = Date.now();
809
+ for (let n of [
810
+ "keyed",
811
+ "bulk",
812
+ "upsert",
813
+ "callback"
814
+ ]) await e.insert("voltro_parity_d", {
815
+ id: n,
816
+ title: "before",
817
+ at: t,
818
+ n: 9
819
+ }), n === "keyed" ? await e.update("voltro_parity_d", n, { title: "edited" }) : n === "bulk" ? await e.updateMany("voltro_parity_d", { title: "edited" }, { where: a("id", n) }) : await e.upsert("voltro_parity_d", {
820
+ id: n,
821
+ title: "edited"
822
+ }, {
823
+ conflictColumns: ["id"],
824
+ update: n === "callback" ? () => ({ title: "edited" }) : ["title"]
825
+ });
826
+ let r = await e.query(k("voltro_parity_d"));
827
+ S(r).toHaveLength(4);
828
+ for (let e of r) {
829
+ S(e).toMatchObject({
830
+ title: "edited",
831
+ n: 9
832
+ });
833
+ let t = e.at instanceof Date ? e.at.getTime() : new Date(String(e.at)).getTime();
834
+ S(t).toBeGreaterThanOrEqual(n), S(t).toBeLessThanOrEqual(Date.now());
835
+ }
836
+ await e.insert("voltro_parity_values", {
837
+ id: "automatic",
838
+ title: "original",
839
+ metadata: { keep: !0 },
840
+ labels: []
841
+ }), await e.patchJson("voltro_parity_values", "automatic", "metadata.child.value", !1), S(await e.query(k("voltro_parity_values"))).toEqual([{
842
+ id: "automatic",
843
+ title: "automatic",
844
+ metadata: {
845
+ keep: !0,
846
+ child: { value: !1 }
847
+ },
848
+ labels: []
849
+ }]), S(await e.upsert("voltro_parity_d", {
850
+ id: "new",
851
+ title: "insert"
852
+ }, {
853
+ conflictColumns: ["id"],
854
+ update: []
855
+ })).toMatchObject({ at: null });
856
+ };
857
+ e === "transactional" ? await r.transactional(i) : await i(r);
858
+ });
859
+ }), C("JSON patch companion failure rolls back the JSON write too", async () => {
860
+ let e = {
861
+ id: "atomic-json",
862
+ title: "keep",
863
+ metadata: { keep: !0 },
864
+ labels: []
865
+ };
866
+ await n.store.insert("voltro_parity_values", e), await S(n.store.patchJson("voltro_parity_values", e.id, "metadata.changed", !0, { title: null })).rejects.toThrow(), S(await n.store.query(k("voltro_parity_values"))).toEqual([e]);
867
+ }), C("concurrent JSON patches preserve every sibling and the companion write", async () => {
868
+ await n.store.insert("voltro_parity_values", {
869
+ id: "concurrent-json",
870
+ title: "before",
871
+ metadata: {},
872
+ labels: []
873
+ }), await Promise.all(Array.from({ length: 8 }, (e, t) => n.store.transactional((e) => e.patchJson("voltro_parity_values", "concurrent-json", `metadata.key${t}`, t, { title: "after" })))), S(await n.store.query(k("voltro_parity_values"))).toEqual([{
874
+ id: "concurrent-json",
875
+ title: "after",
876
+ metadata: Object.fromEntries(Array.from({ length: 8 }, (e, t) => [`key${t}`, t])),
877
+ labels: []
878
+ }]);
879
+ }), C("upsert on a NON-primary-key unique constraint updates that row", async () => {
453
880
  await n.store.upsert("voltro_parity_upsert", {
454
881
  id: "up_first",
455
882
  teamId: "t-1",
@@ -464,14 +891,293 @@ var w = (e) => ({
464
891
  conflictColumns: ["teamId", "year"],
465
892
  update: ["hours"]
466
893
  });
467
- let e = await n.store.query(w("voltro_parity_upsert"));
468
- _(e.length, "the second upsert inserted a duplicate instead of updating").toBe(1), _(e[0]).toMatchObject({
894
+ let e = await n.store.query(k("voltro_parity_upsert"));
895
+ S(e.length, "the second upsert inserted a duplicate instead of updating").toBe(1), S(e[0]).toMatchObject({
469
896
  id: "up_first",
470
897
  teamId: "t-1",
471
898
  year: 2026,
472
899
  hours: 111
473
900
  });
474
- }), v("and a DIFFERENT row is still not silently overwritten", async () => {
901
+ }), x.each(["direct", "transactional"])("upsert updateValues (%s)", (e) => {
902
+ let t = (t) => e === "transactional" ? n.store.transactional(t) : t(n.store);
903
+ C("keeps INSERT defaults and writes omitted columns only on conflict", async () => {
904
+ let e = /* @__PURE__ */ new Date("2026-09-05T10:20:30.000Z"), r = {
905
+ conflictColumns: ["id"],
906
+ update: [],
907
+ updateValues: {
908
+ at: e,
909
+ n: 42
910
+ }
911
+ };
912
+ await t(async (t) => {
913
+ let n = await t.upsert("voltro_parity_d", {
914
+ id: "constant",
915
+ title: "Lobby"
916
+ }, r);
917
+ S(n).toMatchObject({
918
+ id: "constant",
919
+ title: "Lobby",
920
+ at: null,
921
+ n: null
922
+ });
923
+ let i = await t.upsert("voltro_parity_d", {
924
+ id: "constant",
925
+ title: "Do not overwrite"
926
+ }, r);
927
+ S(i).toMatchObject({
928
+ id: "constant",
929
+ title: "Lobby",
930
+ n: 42
931
+ }), S(new Date(String(i.at)).toISOString()).toBe(e.toISOString());
932
+ });
933
+ let [i] = await n.store.query(k("voltro_parity_d"));
934
+ S(i).toMatchObject({
935
+ id: "constant",
936
+ title: "Lobby",
937
+ n: 42
938
+ }), S(new Date(String(i.at)).toISOString()).toBe(e.toISOString());
939
+ }), C.each([
940
+ "omitted",
941
+ "empty",
942
+ "columns",
943
+ "callback"
944
+ ])("overrides the %s projection, retaining row identity", async (e) => {
945
+ await t(async (t) => {
946
+ await t.insert("voltro_parity_upsert", {
947
+ id: "original",
948
+ teamId: "t1",
949
+ year: 2026,
950
+ hours: 1
951
+ });
952
+ let n = e === "callback" ? () => ({ hours: 3 }) : e === "columns" ? ["hours"] : e === "empty" ? [] : void 0, r = await t.upsert("voltro_parity_upsert", {
953
+ id: "unused-new-id",
954
+ teamId: "t1",
955
+ year: 2026,
956
+ hours: 2
957
+ }, {
958
+ conflictColumns: ["teamId", "year"],
959
+ ...n === void 0 ? {} : { update: n },
960
+ updateValues: { hours: 42 }
961
+ });
962
+ S(r).toMatchObject({
963
+ id: "original",
964
+ teamId: "t1",
965
+ year: 2026,
966
+ hours: 42
967
+ });
968
+ }), S(await n.store.query(k("voltro_parity_upsert"))).toEqual([S.objectContaining({
969
+ id: "original",
970
+ teamId: "t1",
971
+ year: 2026,
972
+ hours: 42
973
+ })]);
974
+ }), C("binds explicit NULL to timestamp/int columns and omits undefined assignments", async () => {
975
+ await t(async (e) => {
976
+ await e.insert("voltro_parity_d", {
977
+ id: "nulls",
978
+ title: "original",
979
+ at: /* @__PURE__ */ new Date("2026-01-01"),
980
+ n: 9
981
+ });
982
+ let t = {
983
+ id: "nulls",
984
+ title: "input",
985
+ at: /* @__PURE__ */ new Date("2026-02-01"),
986
+ n: 2
987
+ }, n = await e.upsert("voltro_parity_d", t, {
988
+ conflictColumns: ["id"],
989
+ update: ["title"],
990
+ updateValues: {
991
+ title: "",
992
+ at: null,
993
+ n: void 0
994
+ }
995
+ });
996
+ S(n).toMatchObject({
997
+ id: "nulls",
998
+ title: "",
999
+ at: null,
1000
+ n: 9
1001
+ }), S(await e.upsert("voltro_parity_d", t, {
1002
+ conflictColumns: ["id"],
1003
+ update: [],
1004
+ updateValues: { n: null }
1005
+ })).toMatchObject({
1006
+ id: "nulls",
1007
+ title: "",
1008
+ at: null,
1009
+ n: null
1010
+ });
1011
+ });
1012
+ }), C("binds false and zero without treating them as omitted", async () => {
1013
+ await t(async (e) => {
1014
+ let t = {
1015
+ id: "falsy",
1016
+ title: "keep",
1017
+ count: 9,
1018
+ flag: !0
1019
+ };
1020
+ await e.insert("voltro_parity_c", t), await e.upsert("voltro_parity_c", t, {
1021
+ conflictColumns: ["id"],
1022
+ update: [],
1023
+ updateValues: {
1024
+ flag: !1,
1025
+ count: 0
1026
+ }
1027
+ });
1028
+ let n = await e.query(k("voltro_parity_c"));
1029
+ S(n).toEqual([S.objectContaining({
1030
+ id: "falsy",
1031
+ title: "keep",
1032
+ count: 0
1033
+ })]), S([!1, 0]).toContain(n[0].flag);
1034
+ });
1035
+ }), C("encodes JSON/array assignments and binds SQL-looking strings as data", async () => {
1036
+ await t(async (e) => {
1037
+ let t = {
1038
+ id: "structured",
1039
+ title: "original",
1040
+ metadata: { preserve: !0 },
1041
+ labels: ["original"]
1042
+ }, n = {
1043
+ title: "O'Brien'); DROP TABLE nowhere; --",
1044
+ metadata: { nested: [
1045
+ !1,
1046
+ 0,
1047
+ null,
1048
+ "a'b"
1049
+ ] },
1050
+ labels: [
1051
+ "a",
1052
+ "b'",
1053
+ "c,d"
1054
+ ]
1055
+ }, r = {
1056
+ conflictColumns: ["id"],
1057
+ update: [],
1058
+ updateValues: n
1059
+ };
1060
+ await e.upsert("voltro_parity_values", t, r), S(await e.query(k("voltro_parity_values"))).toEqual([t]), await e.upsert("voltro_parity_values", t, r), S(await e.query(k("voltro_parity_values"))).toEqual([{
1061
+ id: "structured",
1062
+ ...n
1063
+ }]), await e.upsert("voltro_parity_values", t, {
1064
+ ...r,
1065
+ updateValues: {
1066
+ metadata: null,
1067
+ labels: []
1068
+ }
1069
+ }), S(await e.query(k("voltro_parity_values"))).toEqual([{
1070
+ id: "structured",
1071
+ title: n.title,
1072
+ metadata: null,
1073
+ labels: []
1074
+ }]);
1075
+ });
1076
+ }), C("keeps structured raw-driver values working through all write verbs", async () => {
1077
+ await t(async (e) => {
1078
+ let t = {
1079
+ title: "before",
1080
+ metadata: { before: [1] },
1081
+ labels: ["before"]
1082
+ }, n = {
1083
+ title: "after",
1084
+ metadata: { after: [null, !1] },
1085
+ labels: ["after"]
1086
+ };
1087
+ await e.insert("voltro_parity_values", {
1088
+ id: "single",
1089
+ ...t
1090
+ }), await e.insertMany("voltro_parity_values", [{
1091
+ id: "bulk",
1092
+ ...t
1093
+ }, {
1094
+ id: "callback",
1095
+ ...t
1096
+ }]), await e.update("voltro_parity_values", "single", n), await e.updateMany("voltro_parity_values", n, { where: a("id", "bulk") }), await e.upsert("voltro_parity_values", {
1097
+ id: "callback",
1098
+ ...t
1099
+ }, {
1100
+ conflictColumns: ["id"],
1101
+ update: () => n
1102
+ }), await e.insertIgnore("voltro_parity_values", {
1103
+ id: "single",
1104
+ ...t
1105
+ }, { conflictColumns: ["id"] }), await e.insertIgnore("voltro_parity_values", {
1106
+ id: "ignore-new",
1107
+ ...n
1108
+ }, { conflictColumns: ["id"] });
1109
+ let r = await e.query(k("voltro_parity_values"));
1110
+ S([...r].sort((e, t) => String(e.id).localeCompare(String(t.id)))).toEqual([
1111
+ {
1112
+ id: "bulk",
1113
+ ...n
1114
+ },
1115
+ {
1116
+ id: "callback",
1117
+ ...n
1118
+ },
1119
+ {
1120
+ id: "ignore-new",
1121
+ ...n
1122
+ },
1123
+ {
1124
+ id: "single",
1125
+ ...n
1126
+ }
1127
+ ]);
1128
+ });
1129
+ }), C.each([
1130
+ "id",
1131
+ "teamId",
1132
+ "year"
1133
+ ])("refuses updateValues.%s before either branch writes", async (e) => {
1134
+ await t(async (t) => {
1135
+ let n = {
1136
+ id: "identity",
1137
+ teamId: "t1",
1138
+ year: 2026,
1139
+ hours: 1
1140
+ }, r = {
1141
+ conflictColumns: ["teamId", "year"],
1142
+ update: [],
1143
+ updateValues: { [e]: "different" }
1144
+ };
1145
+ await S(t.upsert("voltro_parity_upsert", n, r)).rejects.toThrow("identity"), S(await t.query(k("voltro_parity_upsert"))).toEqual([]), await t.insert("voltro_parity_upsert", n), await S(t.upsert("voltro_parity_upsert", n, r)).rejects.toThrow("identity"), S(await t.query(k("voltro_parity_upsert"))).toEqual([S.objectContaining(n)]);
1146
+ });
1147
+ });
1148
+ }), C("upsert updateValues rolls back row changes and discards transaction events", async () => {
1149
+ await n.store.insert("voltro_parity_a", {
1150
+ id: "rollback-values",
1151
+ title: "keep",
1152
+ count: 1
1153
+ });
1154
+ let e = [], t = n.store.onChange((t) => {
1155
+ e.push(t);
1156
+ });
1157
+ try {
1158
+ await S(n.store.transactional(async (e) => {
1159
+ let t = await e.upsert("voltro_parity_a", {
1160
+ id: "rollback-values",
1161
+ title: "incoming",
1162
+ count: 2
1163
+ }, {
1164
+ conflictColumns: ["id"],
1165
+ update: [],
1166
+ updateValues: { count: 42 }
1167
+ });
1168
+ throw S(t).toMatchObject({
1169
+ title: "keep",
1170
+ count: 42
1171
+ }), Error("rollback values");
1172
+ })).rejects.toThrow("rollback values"), S(await n.store.query(k("voltro_parity_a"))).toEqual([S.objectContaining({
1173
+ id: "rollback-values",
1174
+ title: "keep",
1175
+ count: 1
1176
+ })]), S(e).toEqual([]);
1177
+ } finally {
1178
+ t();
1179
+ }
1180
+ }), C("and a DIFFERENT row is still not silently overwritten", async () => {
475
1181
  await n.store.upsert("voltro_parity_upsert", {
476
1182
  id: "up_a",
477
1183
  teamId: "t-1",
@@ -486,16 +1192,16 @@ var w = (e) => ({
486
1192
  conflictColumns: ["teamId", "year"],
487
1193
  update: ["hours"]
488
1194
  });
489
- let e = await n.store.query(w("voltro_parity_upsert"));
490
- _(e.length).toBe(2), _([...e].map((e) => e.hours).sort()).toEqual([1, 2]);
491
- }), v("insert + update bind an explicit NULL into a datetime2/int column", async () => {
1195
+ let e = await n.store.query(k("voltro_parity_upsert"));
1196
+ S(e.length).toBe(2), S([...e].map((e) => e.hours).sort()).toEqual([1, 2]);
1197
+ }), C("insert + update bind an explicit NULL into a datetime2/int column", async () => {
492
1198
  let e = await n.store.insert("voltro_parity_d", {
493
1199
  id: "nd1",
494
1200
  title: "nulls",
495
1201
  at: null,
496
1202
  n: null
497
1203
  });
498
- _(e).toMatchObject({
1204
+ S(e).toMatchObject({
499
1205
  id: "nd1",
500
1206
  title: "nulls",
501
1207
  at: null,
@@ -510,12 +1216,12 @@ var w = (e) => ({
510
1216
  at: null,
511
1217
  n: null
512
1218
  });
513
- _(t).toMatchObject({
1219
+ S(t).toMatchObject({
514
1220
  id: "nd2",
515
1221
  at: null,
516
1222
  n: null
517
1223
  });
518
- }), v("updateMany updates only the rows matching the predicate + returns the count", async () => {
1224
+ }), C("updateMany updates only the rows matching the predicate + returns the count", async () => {
519
1225
  await n.store.insert("voltro_parity_a", {
520
1226
  id: "m1",
521
1227
  title: "x",
@@ -534,17 +1240,17 @@ var w = (e) => ({
534
1240
  op: "eq",
535
1241
  value: 5
536
1242
  } });
537
- _(e).toBe(2);
1243
+ S(e).toBe(2);
538
1244
  let t = await n.store.query({
539
- ...w("voltro_parity_a"),
1245
+ ...k("voltro_parity_a"),
540
1246
  predicate: {
541
1247
  column: "title",
542
1248
  op: "eq",
543
1249
  value: "hit"
544
1250
  }
545
1251
  });
546
- _(t.length).toBe(2);
547
- }), v("updateMany with an AND predicate is an atomic compare-and-set (the wakeup-claim pattern)", async () => {
1252
+ S(t.length).toBe(2);
1253
+ }), C("updateMany with an AND predicate is an atomic compare-and-set (the wakeup-claim pattern)", async () => {
548
1254
  await n.store.insert("voltro_parity_a", {
549
1255
  id: "cas",
550
1256
  title: "pending",
@@ -559,10 +1265,10 @@ var w = (e) => ({
559
1265
  op: "eq",
560
1266
  value: e
561
1267
  }] }), t = await n.store.updateMany("voltro_parity_a", { title: "claimed" }, { where: e("pending") });
562
- _(t).toBe(1);
1268
+ S(t).toBe(1);
563
1269
  let r = await n.store.updateMany("voltro_parity_a", { title: "claimed-again" }, { where: e("pending") });
564
- _(r).toBe(0);
565
- }), v("deleteMany removes only the rows matching the predicate + returns the count", async () => {
1270
+ S(r).toBe(0);
1271
+ }), C("deleteMany removes only the rows matching the predicate + returns the count", async () => {
566
1272
  await n.store.insert("voltro_parity_a", {
567
1273
  id: "d1",
568
1274
  title: "x",
@@ -581,10 +1287,10 @@ var w = (e) => ({
581
1287
  op: "eq",
582
1288
  value: 5
583
1289
  } });
584
- _(e).toBe(2);
585
- let t = await n.store.query(w("voltro_parity_a"));
586
- _(t.map((e) => e.id)).toEqual(["d3"]);
587
- }), v("deleteMany emits one delete ChangeEvent per removed row (old-image)", async () => {
1290
+ S(e).toBe(2);
1291
+ let t = await n.store.query(k("voltro_parity_a"));
1292
+ S(t.map((e) => e.id)).toEqual(["d3"]);
1293
+ }), C("deleteMany emits one delete ChangeEvent per removed row (old-image)", async () => {
588
1294
  await n.store.insert("voltro_parity_a", {
589
1295
  id: "e1",
590
1296
  title: "gone",
@@ -606,10 +1312,10 @@ var w = (e) => ({
606
1312
  op: "eq",
607
1313
  value: "gone"
608
1314
  } });
609
- t(), _(r).toBe(2);
1315
+ t(), S(r).toBe(2);
610
1316
  let i = e.filter((e) => e.op === "delete");
611
- _(i).toHaveLength(2), _(i.map((e) => e.id).sort()).toEqual(["e1", "e2"]);
612
- }), v("deleteMany with no match returns 0 and removes nothing", async () => {
1317
+ S(i).toHaveLength(2), S(i.map((e) => e.id).sort()).toEqual(["e1", "e2"]);
1318
+ }), C("deleteMany with no match returns 0 and removes nothing", async () => {
613
1319
  await n.store.insert("voltro_parity_a", {
614
1320
  id: "k1",
615
1321
  title: "keep",
@@ -620,14 +1326,14 @@ var w = (e) => ({
620
1326
  op: "eq",
621
1327
  value: "absent"
622
1328
  } });
623
- _(e).toBe(0);
624
- let t = await n.store.query(w("voltro_parity_a"));
625
- _(t.length).toBe(1);
626
- }), v("retryFilter recognises the dialect's own transient codes", () => {
1329
+ S(e).toBe(0);
1330
+ let t = await n.store.query(k("voltro_parity_a"));
1331
+ S(t.length).toBe(1);
1332
+ }), C("retryFilter recognises the dialect's own transient codes", () => {
627
1333
  let e = t.dialect.retryFilter(/* @__PURE__ */ Error("garbage"));
628
- _(["retry", "noRetry"]).toContain(e);
1334
+ S(["retry", "noRetry"]).toContain(e);
629
1335
  });
630
1336
  });
631
1337
  };
632
1338
  //#endregion
633
- export { x as applySchema, M as runDialectParity };
1339
+ export { E as applySchema, B as runDialectParity };