@voltro/testing 0.85.0 → 0.86.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/CHANGELOG.md +666 -0
- package/THIRD-PARTY-NOTICES.md +5 -33
- package/dist/client.js +73 -98
- package/dist/dialect.js +244 -145
- package/dist/factory.js +65 -0
- package/dist/fixtureRow.js +30 -0
- package/dist/formBindingHarness.js +46 -0
- package/dist/hydrateFixtureRows.js +22 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +19 -933
- package/dist/invoke.js +44 -0
- package/dist/mockClock.js +78 -0
- package/dist/mockLLM.js +19 -0
- package/dist/mockWebhooks.js +26 -0
- package/dist/platform.js +1 -5
- package/dist/reachable.js +27 -0
- package/dist/serviceApiMock.js +53 -0
- package/dist/subject.js +11 -0
- package/dist/subscribeContext.js +16 -0
- package/dist/testApps.js +111 -0
- package/dist/testContext.js +248 -0
- package/dist/testEventBus.js +73 -0
- package/dist/testRequest.js +119 -0
- package/dist/workflowRunner.js +85 -0
- package/package.json +9 -9
package/dist/dialect.js
CHANGED
|
@@ -2,79 +2,80 @@ import { _voltroMigrationPlansTable as e, array as t, boolean as n, bulkInsertLi
|
|
|
2
2
|
import { Effect as b } from "effect";
|
|
3
3
|
import { _voltroUndoLogTable as x, applyInverses as S, makeSchemaRegistry as C, synthesizeInverse as w, wrapStoreWithMixinBehaviour as T } from "@voltro/runtime";
|
|
4
4
|
import { afterEach as E, beforeEach as D, describe as O, expect as k, it as A } from "vitest";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { randomUUID as j } from "node:crypto";
|
|
6
|
+
import { SqlClient as M } from "effect/sql";
|
|
7
|
+
import { applyPlan as N, applySchema as P, declaredSnapshot as F, fingerprintSchema as I, introspectSchema as L, planMigrations as R } from "@voltro/database/sql";
|
|
7
8
|
//#region src/dialectParity.ts
|
|
8
|
-
var
|
|
9
|
+
var z = (e) => ({
|
|
9
10
|
table: e,
|
|
10
11
|
predicate: void 0,
|
|
11
12
|
order: [],
|
|
12
13
|
take: void 0,
|
|
13
14
|
skip: void 0,
|
|
14
15
|
projection: void 0
|
|
15
|
-
}),
|
|
16
|
+
}), B = h("voltro_parity_a", {
|
|
16
17
|
id: c(),
|
|
17
18
|
title: g(),
|
|
18
19
|
count: l()
|
|
19
|
-
}),
|
|
20
|
+
}), V = h("voltro_parity_b", {
|
|
20
21
|
id: c(),
|
|
21
22
|
title: g()
|
|
22
|
-
}),
|
|
23
|
+
}), H = h("voltro_parity_c", {
|
|
23
24
|
id: c(),
|
|
24
25
|
title: g(),
|
|
25
26
|
count: l(),
|
|
26
27
|
flag: n().default(!1)
|
|
27
|
-
}),
|
|
28
|
+
}), U = h("voltro_parity_d", {
|
|
28
29
|
id: c(),
|
|
29
30
|
title: g(),
|
|
30
31
|
at: _().nullable().onUpdate("now"),
|
|
31
32
|
n: l().nullable()
|
|
32
|
-
}),
|
|
33
|
+
}), W = h("voltro_parity_upsert", {
|
|
33
34
|
id: c(),
|
|
34
35
|
teamId: g(),
|
|
35
36
|
year: l(),
|
|
36
37
|
hours: l().nullable()
|
|
37
|
-
}).unique("byTeamYear", ["teamId", "year"]),
|
|
38
|
+
}).unique("byTeamYear", ["teamId", "year"]), G = h("voltro_parity_values", {
|
|
38
39
|
id: c(),
|
|
39
40
|
title: g().onUpdate(() => "automatic"),
|
|
40
41
|
metadata: u().nullable(),
|
|
41
42
|
labels: t(g()).nullable()
|
|
42
43
|
});
|
|
43
|
-
f(
|
|
44
|
-
var
|
|
44
|
+
f(G);
|
|
45
|
+
var K = h("voltro_parity_json_names", {
|
|
45
46
|
id: c(),
|
|
46
47
|
key: u(),
|
|
47
48
|
value: u()
|
|
48
49
|
});
|
|
49
|
-
f(
|
|
50
|
-
var
|
|
50
|
+
f(K);
|
|
51
|
+
var q = h("voltro_parity_composite", {
|
|
51
52
|
userId: g(),
|
|
52
53
|
orgId: g(),
|
|
53
54
|
role: g()
|
|
54
|
-
}).primaryKey(["userId", "orgId"]),
|
|
55
|
+
}).primaryKey(["userId", "orgId"]), J = h("voltro_parity_bulk", {
|
|
55
56
|
id: c(),
|
|
56
57
|
title: g(),
|
|
57
58
|
count: l(),
|
|
58
59
|
flag: n().default(!1)
|
|
59
|
-
}),
|
|
60
|
+
}), Y = (e) => {
|
|
60
61
|
let t = r(e);
|
|
61
62
|
if (t === void 0) return 0;
|
|
62
|
-
let n = Object.keys(
|
|
63
|
+
let n = Object.keys(J.fields).length;
|
|
63
64
|
return Math.max(1, Math.min(Math.floor(t.maxBindParameters / n), t.maxRowsPerStatement ?? Infinity));
|
|
64
|
-
},
|
|
65
|
+
}, X = (n) => {
|
|
65
66
|
O(`dialect parity: ${n.name ?? n.dialect.id}`, () => {
|
|
66
67
|
let r = null;
|
|
67
68
|
D(async () => {
|
|
68
69
|
await n.setup(), r = await n.make(), await r.migrate([
|
|
69
|
-
z,
|
|
70
70
|
B,
|
|
71
71
|
V,
|
|
72
72
|
H,
|
|
73
|
-
q,
|
|
74
73
|
U,
|
|
75
|
-
|
|
74
|
+
J,
|
|
76
75
|
W,
|
|
76
|
+
q,
|
|
77
77
|
G,
|
|
78
|
+
K,
|
|
78
79
|
x
|
|
79
80
|
]);
|
|
80
81
|
for (let e of [
|
|
@@ -87,28 +88,132 @@ var K = h("voltro_parity_composite", {
|
|
|
87
88
|
"voltro_parity_json_names",
|
|
88
89
|
"_voltro_undo_log"
|
|
89
90
|
]) {
|
|
90
|
-
let t = await r.store.query(
|
|
91
|
+
let t = await r.store.query(z(e));
|
|
91
92
|
for (let n of t) await r.store.delete(e, n.id);
|
|
92
93
|
}
|
|
93
|
-
for (let e of await r.store.query(
|
|
94
|
+
for (let e of await r.store.query(z("voltro_parity_composite"))) await r.store.delete("voltro_parity_composite", {
|
|
94
95
|
userId: e.userId,
|
|
95
96
|
orgId: e.orgId
|
|
96
97
|
});
|
|
97
98
|
}), E(async () => {
|
|
98
99
|
v("voltro_parity_evolve"), await r?.dispose(), await n.teardown(), r = null;
|
|
100
|
+
}), O.each(["direct", "transactional"])("numeric and audit write contracts (%s)", (e) => {
|
|
101
|
+
let t = (t, n) => e === "transactional" ? t.transactional(n) : n(t), n = (e) => r.run(b.gen(function* () {
|
|
102
|
+
yield* (yield* M.SqlClient).unsafe(`DROP TABLE IF EXISTS ${e}`);
|
|
103
|
+
}));
|
|
104
|
+
A("returns numeric ids consistently and accepts them for tenant-scoped keyed writes", async () => {
|
|
105
|
+
let e = `voltro_numeric_${j().replaceAll("-", "").slice(0, 12)}`, i = h(e, {
|
|
106
|
+
id: c({ scheme: "numeric" }),
|
|
107
|
+
tenantId: g().maxLength(100),
|
|
108
|
+
title: g().maxLength(100),
|
|
109
|
+
metadata: u()
|
|
110
|
+
}).nonReactive();
|
|
111
|
+
f(i);
|
|
112
|
+
try {
|
|
113
|
+
await r.migrate([i]);
|
|
114
|
+
let n = C([{
|
|
115
|
+
tableName: i.tableName,
|
|
116
|
+
fields: i.fields,
|
|
117
|
+
appliedMixins: [{ id: "voltro/tenant" }]
|
|
118
|
+
}]), a = (e) => T(r.store, {
|
|
119
|
+
subject: {
|
|
120
|
+
type: "user",
|
|
121
|
+
id: "numeric_writer",
|
|
122
|
+
tenantId: e
|
|
123
|
+
},
|
|
124
|
+
schemaRegistry: n
|
|
125
|
+
});
|
|
126
|
+
await t(a("owner"), async (t) => {
|
|
127
|
+
for (let n of [
|
|
128
|
+
"update",
|
|
129
|
+
"patchJson",
|
|
130
|
+
"delete"
|
|
131
|
+
]) {
|
|
132
|
+
let r = await t.insert(e, {
|
|
133
|
+
title: n,
|
|
134
|
+
metadata: {}
|
|
135
|
+
});
|
|
136
|
+
k(typeof r.id).toBe("number"), k(Number.isSafeInteger(r.id)).toBe(!0), n === "update" ? k(await t.update(e, r.id, { title: "edited" })).toMatchObject({
|
|
137
|
+
id: r.id,
|
|
138
|
+
title: "edited"
|
|
139
|
+
}) : n === "patchJson" ? k(await t.patchJson(e, r.id, "metadata.seen", !0)).toMatchObject({
|
|
140
|
+
id: r.id,
|
|
141
|
+
metadata: { seen: !0 }
|
|
142
|
+
}) : k(await t.delete(e, r.id)).toBe(!0);
|
|
143
|
+
}
|
|
144
|
+
let n = await t.query(z(e));
|
|
145
|
+
k(n).toHaveLength(2), k(n.every((e) => typeof e.id == "number")).toBe(!0);
|
|
146
|
+
});
|
|
147
|
+
let [o] = await r.store.query(z(e));
|
|
148
|
+
await k(a("other").update(e, o.id, { title: "stolen" })).rejects.toMatchObject({ _tag: "TenantRowNotFound" });
|
|
149
|
+
} finally {
|
|
150
|
+
v(e), await n(e);
|
|
151
|
+
}
|
|
152
|
+
}), A("preserves creation stamps during default audited upserts and still stamps updates", async () => {
|
|
153
|
+
let e = `voltro_audit_${j().replaceAll("-", "").slice(0, 12)}`, i = h(e, {
|
|
154
|
+
id: c({ prefix: "audit" }),
|
|
155
|
+
externalId: g().maxLength(100).unique(),
|
|
156
|
+
value: g(),
|
|
157
|
+
createdAt: _(),
|
|
158
|
+
createdBy: g().nullable(),
|
|
159
|
+
updatedAt: _(),
|
|
160
|
+
updatedBy: g().nullable()
|
|
161
|
+
}).nonReactive();
|
|
162
|
+
f(i);
|
|
163
|
+
try {
|
|
164
|
+
await r.migrate([i]);
|
|
165
|
+
let n = C([{
|
|
166
|
+
tableName: i.tableName,
|
|
167
|
+
fields: i.fields,
|
|
168
|
+
appliedMixins: [{ id: "voltro/audit" }]
|
|
169
|
+
}]), a = T(r.store, {
|
|
170
|
+
subject: {
|
|
171
|
+
type: "user",
|
|
172
|
+
id: "editor",
|
|
173
|
+
tenantId: "audit_scope"
|
|
174
|
+
},
|
|
175
|
+
schemaRegistry: n
|
|
176
|
+
}), o = /* @__PURE__ */ new Date("2026-01-01T00:00:00Z");
|
|
177
|
+
await t(a, async (t) => {
|
|
178
|
+
for (let n of ["upsert", "upsertWithOutcome"]) {
|
|
179
|
+
await t.insert(e, {
|
|
180
|
+
externalId: n,
|
|
181
|
+
value: "before",
|
|
182
|
+
createdAt: o,
|
|
183
|
+
createdBy: "creator",
|
|
184
|
+
updatedAt: o
|
|
185
|
+
});
|
|
186
|
+
let r = n === "upsert" ? await t.upsert(e, {
|
|
187
|
+
externalId: n,
|
|
188
|
+
value: "after"
|
|
189
|
+
}, { conflictColumns: ["externalId"] }) : (await t.upsertWithOutcome(e, {
|
|
190
|
+
externalId: n,
|
|
191
|
+
value: "after"
|
|
192
|
+
}, { conflictColumns: ["externalId"] })).row;
|
|
193
|
+
k(r).toMatchObject({
|
|
194
|
+
value: "after",
|
|
195
|
+
createdBy: "creator",
|
|
196
|
+
updatedBy: "editor"
|
|
197
|
+
}), k(new Date(String(r.createdAt)).toISOString()).toBe(o.toISOString()), k(new Date(String(r.updatedAt)).getTime()).toBeGreaterThan(o.getTime());
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
} finally {
|
|
201
|
+
v(e), await n(e);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
99
204
|
}), A("rename-table: the rows move, and the plan converges", async () => {
|
|
100
205
|
let t = "voltro_rename_src", i = "_voltro_rename_dst", a = r.run, o = async () => {
|
|
101
206
|
await a(b.gen(function* () {
|
|
102
|
-
let e = yield*
|
|
207
|
+
let e = yield* M.SqlClient;
|
|
103
208
|
for (let n of [i, t]) yield* b.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${n}`), () => []);
|
|
104
209
|
})).catch(() => {});
|
|
105
210
|
}, s = () => a(b.gen(function* () {
|
|
106
|
-
let e = yield*
|
|
211
|
+
let e = yield* M.SqlClient, n = yield* L(e);
|
|
107
212
|
return {
|
|
108
213
|
...n,
|
|
109
214
|
tables: n.tables.filter((e) => e.name === t || e.name === i)
|
|
110
215
|
};
|
|
111
|
-
})), l = async () =>
|
|
216
|
+
})), l = async () => R({
|
|
112
217
|
declared: [d],
|
|
113
218
|
live: await s(),
|
|
114
219
|
dialect: n.dialect.id
|
|
@@ -130,8 +235,8 @@ var K = h("voltro_parity_composite", {
|
|
|
130
235
|
});
|
|
131
236
|
let f = await l();
|
|
132
237
|
k(f.operations.some((e) => e.op.kind === "rename-table"), "the marker must fold").toBe(!0), k(f.operations.filter((e) => e.blocked !== void 0), "nothing may be blocked").toEqual([]), await a(b.gen(function* () {
|
|
133
|
-
let e = yield*
|
|
134
|
-
return yield*
|
|
238
|
+
let e = yield* M.SqlClient;
|
|
239
|
+
return yield* N(e, f, {
|
|
135
240
|
declared: [d],
|
|
136
241
|
appliedBy: "dialect-parity",
|
|
137
242
|
environment: "dev",
|
|
@@ -139,42 +244,34 @@ var K = h("voltro_parity_composite", {
|
|
|
139
244
|
replan: () => b.promise(l)
|
|
140
245
|
});
|
|
141
246
|
}));
|
|
142
|
-
let p = await r.store.query(
|
|
247
|
+
let p = await r.store.query(z(i));
|
|
143
248
|
k(p.map((e) => e.id).sort(), "every row survived the rename").toEqual(["rn_1", "rn_2"]), k((await l()).operations, `${n.dialect.id}: the plan must converge`).toEqual([]), await o();
|
|
144
249
|
}), A("schema evolution: create → add column → add index → drop column, converging at each step", async () => {
|
|
145
250
|
let t = "voltro_parity_evolve", s = r.run, u = async () => {
|
|
146
251
|
await s(b.gen(function* () {
|
|
147
|
-
let e = yield*
|
|
252
|
+
let e = yield* M.SqlClient;
|
|
148
253
|
yield* b.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${t}`), () => []), yield* b.orElseSucceed(e.unsafe("DROP TYPE IF EXISTS ev_status"), () => []), yield* b.orElseSucceed(e.unsafe("DELETE FROM _voltro_migration_ops"), () => []);
|
|
149
254
|
})).catch(() => {});
|
|
150
255
|
}, p = () => s(b.gen(function* () {
|
|
151
|
-
let e = yield*
|
|
256
|
+
let e = yield* M.SqlClient, n = yield* L(e);
|
|
152
257
|
return {
|
|
153
258
|
...n,
|
|
154
259
|
tables: n.tables.filter((e) => e.name === t)
|
|
155
260
|
};
|
|
156
|
-
})), m = async (e) =>
|
|
261
|
+
})), m = async (e) => R({
|
|
157
262
|
declared: e,
|
|
158
263
|
live: await p(),
|
|
159
264
|
dialect: n.dialect.id
|
|
160
265
|
}), y = async () => (await p()).tables[0]?.columns.map((e) => e.name) ?? [], x = async (e, r) => {
|
|
161
266
|
let i = await m(e);
|
|
162
|
-
r && k(i.operations.length, `${n.dialect.id}: nothing to apply — the step asserts nothing`).toBeGreaterThan(0), k(i.operations.filter((e) => e.blocked !== void 0), `${n.dialect.id}: nothing may be blocked`).toEqual([])
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
};
|
|
166
|
-
if (i.operations.length === 0) {
|
|
167
|
-
a();
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
await s(b.gen(function* () {
|
|
171
|
-
let r = yield* j.SqlClient;
|
|
172
|
-
return yield* M(r, i, {
|
|
267
|
+
r && k(i.operations.length, `${n.dialect.id}: nothing to apply — the step asserts nothing`).toBeGreaterThan(0), k(i.operations.filter((e) => e.blocked !== void 0), `${n.dialect.id}: nothing may be blocked`).toEqual([]), i.operations.length === 0 || (await s(b.gen(function* () {
|
|
268
|
+
let r = yield* M.SqlClient;
|
|
269
|
+
return yield* N(r, i, {
|
|
173
270
|
declared: e,
|
|
174
271
|
appliedBy: "dialect-parity",
|
|
175
272
|
environment: "dev",
|
|
176
273
|
source: "auto-diff",
|
|
177
|
-
replan: (r) => b.map(
|
|
274
|
+
replan: (r) => b.map(L(r), (r) => R({
|
|
178
275
|
declared: e,
|
|
179
276
|
live: {
|
|
180
277
|
...r,
|
|
@@ -183,7 +280,9 @@ var K = h("voltro_parity_composite", {
|
|
|
183
280
|
dialect: n.dialect.id
|
|
184
281
|
}))
|
|
185
282
|
});
|
|
186
|
-
})), k((await m(e)).operations, `${n.dialect.id}: the plan must converge`).toEqual([]),
|
|
283
|
+
})), k((await m(e)).operations, `${n.dialect.id}: the plan must converge`).toEqual([])), (() => {
|
|
284
|
+
for (let t of e) v(t.tableName), f(t);
|
|
285
|
+
})();
|
|
187
286
|
};
|
|
188
287
|
await u(), await r.migrate([e]), await x([h(t, {
|
|
189
288
|
id: c({ prefix: "ev" }),
|
|
@@ -235,7 +334,7 @@ var K = h("voltro_parity_composite", {
|
|
|
235
334
|
classification: "multi-step",
|
|
236
335
|
blocked: { fix: k.stringContaining("preserves precision") }
|
|
237
336
|
}), k(await p(), "Planning conversion must leave the physical schema unchanged").toEqual(e);
|
|
238
|
-
let i = await r.store.query(
|
|
337
|
+
let i = await r.store.query(z(t));
|
|
239
338
|
k(i.find((e) => e.id === "ev_3")?.amount).toBe("12.34"), k((await m([C])).operations, "The original precision must still converge").toEqual([]);
|
|
240
339
|
} else await x([w], !0);
|
|
241
340
|
let T = S ? 10 : 12, E = S ? 2 : 4, D = () => a(T, E).nullable(), O = (await p()).tables[0]?.columns.find((e) => e.name === "amount");
|
|
@@ -246,25 +345,25 @@ var K = h("voltro_parity_composite", {
|
|
|
246
345
|
p: T,
|
|
247
346
|
s: E
|
|
248
347
|
});
|
|
249
|
-
let A = i("ev_status", ["open", "closed"]),
|
|
348
|
+
let A = i("ev_status", ["open", "closed"]), j = h(t, {
|
|
250
349
|
id: c({ prefix: "ev" }),
|
|
251
350
|
name: g(),
|
|
252
351
|
amount: D(),
|
|
253
352
|
status: A.column().nullable()
|
|
254
353
|
});
|
|
255
|
-
await x([
|
|
354
|
+
await x([j], !0), k(await y(), `${n.dialect.id}: the enum column is live`).toContain("status"), await r.store.insert(t, {
|
|
256
355
|
id: "ev_4",
|
|
257
356
|
name: "four",
|
|
258
357
|
status: "closed"
|
|
259
358
|
});
|
|
260
|
-
let
|
|
359
|
+
let P = (e) => I({ tables: [{
|
|
261
360
|
name: t,
|
|
262
361
|
columns: e.filter((e) => e.name === "status"),
|
|
263
362
|
indexes: []
|
|
264
363
|
}] }), B = (await p()).tables.find((e) => e.name === t)?.columns ?? [];
|
|
265
364
|
k(B.some((e) => e.name === "status"), `${n.dialect.id}: nothing to compare`).toBe(!0);
|
|
266
|
-
let V =
|
|
267
|
-
k(
|
|
365
|
+
let V = F([j], n.dialect.id).tables[0].columns, H = (e) => JSON.stringify(e.find((e) => e.name === "status"));
|
|
366
|
+
k(P(B), `${n.dialect.id}: the enum column must not part the two readers\n live: ${H(B)}\n declared: ${H(V)}`).toBe(P(V));
|
|
268
367
|
let U = i("ev_status", [
|
|
269
368
|
"open",
|
|
270
369
|
"closed",
|
|
@@ -315,7 +414,7 @@ var K = h("voltro_parity_composite", {
|
|
|
315
414
|
createdAt: _().nullable(),
|
|
316
415
|
createdYear: l().backfill((e) => e.createdAt instanceof Date ? e.createdAt.getUTCFullYear() : -1)
|
|
317
416
|
})], !0);
|
|
318
|
-
let G = Object.fromEntries((await r.store.query(
|
|
417
|
+
let G = Object.fromEntries((await r.store.query(z(t))).map((e) => [String(e.id), e.createdYear]));
|
|
319
418
|
k(G, `${n.dialect.id}: the backfill saw each row's createdAt as a Date`).toMatchObject({
|
|
320
419
|
ev_1: 2024,
|
|
321
420
|
ev_2: 2025,
|
|
@@ -334,7 +433,7 @@ var K = h("voltro_parity_composite", {
|
|
|
334
433
|
})], !0);
|
|
335
434
|
let K = (await p()).tables[0]?.columns.find((e) => e.name === "receiptKey");
|
|
336
435
|
k(K?.unique, `${n.dialect.id}: receiptKey carries its unique in the live schema`).toBe(!0);
|
|
337
|
-
let q = await r.store.query(
|
|
436
|
+
let q = await r.store.query(z(t));
|
|
338
437
|
k(q.map((e) => e.id).sort(), `${n.dialect.id}: rows survived the evolution`).toEqual([
|
|
339
438
|
"ev_1",
|
|
340
439
|
"ev_2",
|
|
@@ -345,26 +444,26 @@ var K = h("voltro_parity_composite", {
|
|
|
345
444
|
]), k(q.find((e) => e.id === "ev_3")?.amount, "The exact decimal survives subsequent schema changes").toMatch(/^12\.340*$/), await u();
|
|
346
445
|
}), A("the data half of a plan is atomic: a failing backfill rolls back every backfill of the plan", async () => {
|
|
347
446
|
let t = "voltro_parity_atomic", i = (e) => r.run(e), a = () => i(b.gen(function* () {
|
|
348
|
-
let e = yield*
|
|
447
|
+
let e = yield* M.SqlClient;
|
|
349
448
|
yield* b.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${t}`), () => []), yield* b.orElseSucceed(e.unsafe("DELETE FROM _voltro_migration_ops"), () => []);
|
|
350
449
|
})).catch(() => {}), o = () => i(b.gen(function* () {
|
|
351
|
-
let e = yield*
|
|
450
|
+
let e = yield* M.SqlClient, n = yield* L(e);
|
|
352
451
|
return {
|
|
353
452
|
...n,
|
|
354
453
|
tables: n.tables.filter((e) => e.name === t)
|
|
355
454
|
};
|
|
356
455
|
})), s = (e) => i(b.gen(function* () {
|
|
357
|
-
let r = yield*
|
|
456
|
+
let r = yield* M.SqlClient, i = R({
|
|
358
457
|
declared: e,
|
|
359
458
|
live: yield* b.promise(o),
|
|
360
459
|
dialect: n.dialect.id
|
|
361
460
|
});
|
|
362
|
-
return yield*
|
|
461
|
+
return yield* N(r, i, {
|
|
363
462
|
declared: e,
|
|
364
463
|
appliedBy: "dialect-parity",
|
|
365
464
|
environment: "dev",
|
|
366
465
|
source: "auto-diff",
|
|
367
|
-
replan: (r) => b.map(
|
|
466
|
+
replan: (r) => b.map(L(r), (r) => R({
|
|
368
467
|
declared: e,
|
|
369
468
|
live: {
|
|
370
469
|
...r,
|
|
@@ -395,7 +494,7 @@ var K = h("voltro_parity_composite", {
|
|
|
395
494
|
})
|
|
396
495
|
});
|
|
397
496
|
await k(s([u])).rejects.toThrow(/no value for/);
|
|
398
|
-
let d = (await o()).tables[0]?.columns.map((e) => e.name) ?? [], f = await r.store.query(
|
|
497
|
+
let d = (await o()).tables[0]?.columns.map((e) => e.name) ?? [], f = await r.store.query(z(t));
|
|
399
498
|
k(f, `${n.dialect.id}: the rows survived`).toHaveLength(3), d.includes("first") ? k(f.map((e) => e.first), `${n.dialect.id}: no backfill of the failed group landed`).toEqual([
|
|
400
499
|
null,
|
|
401
500
|
null,
|
|
@@ -408,12 +507,12 @@ var K = h("voltro_parity_composite", {
|
|
|
408
507
|
second: l().backfill((e) => String(e.name).length)
|
|
409
508
|
});
|
|
410
509
|
await s([p]);
|
|
411
|
-
let m = await r.store.query(
|
|
510
|
+
let m = await r.store.query(z(t));
|
|
412
511
|
k(m.map((e) => [e.first, e.second]).sort(), `${n.dialect.id}: both backfills landed`).toEqual([
|
|
413
512
|
[1, 3],
|
|
414
513
|
[1, 3],
|
|
415
514
|
[1, 5]
|
|
416
|
-
]), k(
|
|
515
|
+
]), k(R({
|
|
417
516
|
declared: [p],
|
|
418
517
|
live: await o(),
|
|
419
518
|
dialect: n.dialect.id
|
|
@@ -421,11 +520,11 @@ var K = h("voltro_parity_composite", {
|
|
|
421
520
|
}), A("re-applying a create-table plan is a no-op, indexes included", async () => {
|
|
422
521
|
let t = "voltro_parity_reapply", i = r.run, a = async () => {
|
|
423
522
|
await i(b.gen(function* () {
|
|
424
|
-
let e = yield*
|
|
523
|
+
let e = yield* M.SqlClient;
|
|
425
524
|
yield* b.orElseSucceed(e.unsafe(`DROP TABLE IF EXISTS ${t}`), () => []);
|
|
426
525
|
})).catch(() => {});
|
|
427
526
|
}, o = () => i(b.gen(function* () {
|
|
428
|
-
let e = yield*
|
|
527
|
+
let e = yield* M.SqlClient, n = yield* L(e);
|
|
429
528
|
return {
|
|
430
529
|
...n,
|
|
431
530
|
tables: n.tables.filter((e) => e.name === t)
|
|
@@ -434,7 +533,7 @@ var K = h("voltro_parity_composite", {
|
|
|
434
533
|
id: c({ prefix: "ra" }),
|
|
435
534
|
name: g(),
|
|
436
535
|
qty: l().nullable()
|
|
437
|
-
}).index(["qty"]), u = async () =>
|
|
536
|
+
}).index(["qty"]), u = async () => R({
|
|
438
537
|
declared: [s],
|
|
439
538
|
live: await o(),
|
|
440
539
|
dialect: n.dialect.id
|
|
@@ -443,13 +542,13 @@ var K = h("voltro_parity_composite", {
|
|
|
443
542
|
let d = await u();
|
|
444
543
|
k(d.operations.some((e) => e.op.kind === "create-table"), `${n.dialect.id}: expected a create-table to re-apply`).toBe(!0);
|
|
445
544
|
for (let e = 0; e < 2; e++) await i(b.gen(function* () {
|
|
446
|
-
let e = yield*
|
|
447
|
-
return yield*
|
|
545
|
+
let e = yield* M.SqlClient;
|
|
546
|
+
return yield* N(e, d, {
|
|
448
547
|
declared: [s],
|
|
449
548
|
appliedBy: "dialect-parity",
|
|
450
549
|
environment: "dev",
|
|
451
550
|
source: "auto-diff",
|
|
452
|
-
replan: (e) => b.map(
|
|
551
|
+
replan: (e) => b.map(L(e), (e) => R({
|
|
453
552
|
declared: [s],
|
|
454
553
|
live: {
|
|
455
554
|
...e,
|
|
@@ -461,36 +560,36 @@ var K = h("voltro_parity_composite", {
|
|
|
461
560
|
}));
|
|
462
561
|
k((await u()).operations, `${n.dialect.id}: the re-applied plan must converge`).toEqual([]), await a();
|
|
463
562
|
});
|
|
464
|
-
let
|
|
465
|
-
let e = yield*
|
|
466
|
-
yield* b.orElseSucceed(e.unsafe(`DELETE FROM ${
|
|
467
|
-
})),
|
|
563
|
+
let P = "voltro_parity_bulk", X = () => r.run(b.gen(function* () {
|
|
564
|
+
let e = yield* M.SqlClient;
|
|
565
|
+
yield* b.orElseSucceed(e.unsafe(`DELETE FROM ${P}`), () => []);
|
|
566
|
+
})), Z = (e, t) => Array.from({ length: e }, (e, n) => ({
|
|
468
567
|
id: `${t}_${String(n).padStart(6, "0")}`,
|
|
469
568
|
title: `row ${n}`,
|
|
470
569
|
count: n,
|
|
471
570
|
flag: !1
|
|
472
571
|
}));
|
|
473
572
|
A("insertMany past this dialect's one-statement ceiling lands EVERY row", async () => {
|
|
474
|
-
let e =
|
|
573
|
+
let e = Y(n.dialect.id);
|
|
475
574
|
k(e, `no bulk-insert limits are declared for '${n.dialect.id}' — a dialect with no entry chunks at nothing, so this scenario would pass having tested nothing`).toBeGreaterThan(0);
|
|
476
575
|
let t = e + 5;
|
|
477
|
-
await
|
|
478
|
-
let i = await r.store.insertMany(
|
|
576
|
+
await X();
|
|
577
|
+
let i = await r.store.insertMany(P, Z(t, "bulk"));
|
|
479
578
|
k(i.length, `insertMany returned ${i.length} of ${t} post-images`).toBe(t), k(i[0]?.id).toBe("bulk_000000"), k(i[t - 1]?.id).toBe(`bulk_${String(t - 1).padStart(6, "0")}`);
|
|
480
|
-
let a = await r.store.query(
|
|
481
|
-
k(a.length, "the database holds fewer rows than insertMany reported").toBe(t), await
|
|
579
|
+
let a = await r.store.query(z(P));
|
|
580
|
+
k(a.length, "the database holds fewer rows than insertMany reported").toBe(t), await X();
|
|
482
581
|
}, 12e4), A("a chunked insertMany is still ALL-OR-NOTHING", async () => {
|
|
483
|
-
let e =
|
|
484
|
-
await
|
|
485
|
-
let t =
|
|
582
|
+
let e = Y(n.dialect.id) + 5;
|
|
583
|
+
await X();
|
|
584
|
+
let t = Z(e, "atomic");
|
|
486
585
|
t[e - 1] = {
|
|
487
586
|
...t[e - 1],
|
|
488
587
|
id: t[0].id
|
|
489
|
-
}, await k(r.store.insertMany(
|
|
490
|
-
let i = await r.store.query(
|
|
491
|
-
k(i.length, `${n.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
|
|
588
|
+
}, await k(r.store.insertMany(P, t), "a duplicate primary key must still reject the whole call").rejects.toThrow();
|
|
589
|
+
let i = await r.store.query(z(P));
|
|
590
|
+
k(i.length, `${n.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 X();
|
|
492
591
|
}, 12e4), A("DDL is idempotent — re-applying the schema is a no-op", async () => {
|
|
493
|
-
await r.migrate([
|
|
592
|
+
await r.migrate([B, V]);
|
|
494
593
|
}), A("insert + query round-trips a row", async () => {
|
|
495
594
|
let e = await r.store.insert("voltro_parity_a", {
|
|
496
595
|
id: "a1",
|
|
@@ -502,7 +601,7 @@ var K = h("voltro_parity_composite", {
|
|
|
502
601
|
title: "one",
|
|
503
602
|
count: 1
|
|
504
603
|
});
|
|
505
|
-
let t = await r.store.query(
|
|
604
|
+
let t = await r.store.query(z("voltro_parity_a"));
|
|
506
605
|
k(t.length).toBe(1), k(t[0]?.id).toBe("a1");
|
|
507
606
|
}), A("update returns the post-image", async () => {
|
|
508
607
|
await r.store.insert("voltro_parity_a", {
|
|
@@ -521,7 +620,7 @@ var K = h("voltro_parity_composite", {
|
|
|
521
620
|
title: "x",
|
|
522
621
|
count: 1
|
|
523
622
|
}), k(await r.store.delete("voltro_parity_a", "a3")).toBe(!0);
|
|
524
|
-
let e = await r.store.query(
|
|
623
|
+
let e = await r.store.query(z("voltro_parity_a"));
|
|
525
624
|
k(e.length).toBe(0);
|
|
526
625
|
}), A("a composite key addresses the row, and only that row", async () => {
|
|
527
626
|
await r.store.insert("voltro_parity_composite", {
|
|
@@ -542,7 +641,7 @@ var K = h("voltro_parity_composite", {
|
|
|
542
641
|
orgId: "o2",
|
|
543
642
|
role: "member"
|
|
544
643
|
});
|
|
545
|
-
let t = await r.store.query(
|
|
644
|
+
let t = await r.store.query(z("voltro_parity_composite")), n = new Map(t.map((e) => [e.orgId, e.role]));
|
|
546
645
|
k(n.get("o1")).toBe("admin"), k(n.get("o2")).toBe("member");
|
|
547
646
|
}), A("a composite key that matches nothing is `null` / `false`, not an error", async () => {
|
|
548
647
|
k(await r.store.update("voltro_parity_composite", {
|
|
@@ -565,7 +664,7 @@ var K = h("voltro_parity_composite", {
|
|
|
565
664
|
userId: "u2",
|
|
566
665
|
orgId: "o1"
|
|
567
666
|
})).toBe(!0);
|
|
568
|
-
let e = (await r.store.query(
|
|
667
|
+
let e = (await r.store.query(z("voltro_parity_composite"))).filter((e) => e.userId === "u2").map((e) => e.orgId);
|
|
569
668
|
k(e).toEqual(["o2"]);
|
|
570
669
|
}), A("undo: the _voltro_undo_log TEXT changes column round-trips a JSON ChangeSet", async () => {
|
|
571
670
|
let e = [{
|
|
@@ -597,7 +696,7 @@ var K = h("voltro_parity_composite", {
|
|
|
597
696
|
undone: !1,
|
|
598
697
|
createdAt: /* @__PURE__ */ new Date()
|
|
599
698
|
});
|
|
600
|
-
let t = await r.store.query(
|
|
699
|
+
let t = await r.store.query(z("_voltro_undo_log"));
|
|
601
700
|
k(t.length).toBe(1), k(JSON.parse(t[0].changes)).toEqual(e);
|
|
602
701
|
}), A("undo: reverts an INSERT (inverse delete) on this dialect", async () => {
|
|
603
702
|
let e = {
|
|
@@ -615,7 +714,7 @@ var K = h("voltro_parity_composite", {
|
|
|
615
714
|
}]
|
|
616
715
|
};
|
|
617
716
|
await S(r.store, w(e));
|
|
618
|
-
let t = await r.store.query(
|
|
717
|
+
let t = await r.store.query(z("voltro_parity_c"));
|
|
619
718
|
k(t.find((e) => e.id === "c2")).toBeUndefined();
|
|
620
719
|
}), A("undo: reverts an UPDATE including the BOOLEAN, restoring the captured value FAITHFULLY", async () => {
|
|
621
720
|
await r.store.insert("voltro_parity_c", {
|
|
@@ -625,7 +724,7 @@ var K = h("voltro_parity_composite", {
|
|
|
625
724
|
flag: !0
|
|
626
725
|
});
|
|
627
726
|
let e = (await r.store.query({
|
|
628
|
-
...
|
|
727
|
+
...z("voltro_parity_c"),
|
|
629
728
|
predicate: s("id", "c3")
|
|
630
729
|
}))[0], t = await r.store.update("voltro_parity_c", "c3", {
|
|
631
730
|
count: 2,
|
|
@@ -645,7 +744,7 @@ var K = h("voltro_parity_composite", {
|
|
|
645
744
|
};
|
|
646
745
|
await S(r.store, w(n));
|
|
647
746
|
let i = (await r.store.query({
|
|
648
|
-
...
|
|
747
|
+
...z("voltro_parity_c"),
|
|
649
748
|
predicate: s("id", "c3")
|
|
650
749
|
}))[0];
|
|
651
750
|
k(i.flag).toEqual(e.flag), k(i.count).toEqual(e.count);
|
|
@@ -669,7 +768,7 @@ var K = h("voltro_parity_composite", {
|
|
|
669
768
|
};
|
|
670
769
|
await S(r.store, w(t));
|
|
671
770
|
let n = (await r.store.query({
|
|
672
|
-
...
|
|
771
|
+
...z("voltro_parity_c"),
|
|
673
772
|
predicate: s("id", "c4")
|
|
674
773
|
}))[0];
|
|
675
774
|
k(n.id).toBe("c4"), k(n.title).toBe("gone"), k(n.flag).toEqual(e.flag);
|
|
@@ -702,7 +801,7 @@ var K = h("voltro_parity_composite", {
|
|
|
702
801
|
count: 0
|
|
703
802
|
}), Error("intentional rollback");
|
|
704
803
|
})).rejects.toThrow("intentional rollback"), t(), k(e).toEqual([]);
|
|
705
|
-
let n = await r.store.query(
|
|
804
|
+
let n = await r.store.query(z("voltro_parity_a"));
|
|
706
805
|
k(n.length).toBe(0);
|
|
707
806
|
}), A("transactional commit drains queued events in order", async () => {
|
|
708
807
|
let e = [], t = r.store.onChange((t) => e.push(t.op));
|
|
@@ -730,7 +829,7 @@ var K = h("voltro_parity_composite", {
|
|
|
730
829
|
conflictColumns: ["id"],
|
|
731
830
|
update: ["title", "count"]
|
|
732
831
|
});
|
|
733
|
-
let e = await r.store.query(
|
|
832
|
+
let e = await r.store.query(z("voltro_parity_a"));
|
|
734
833
|
k(e.length).toBe(1), k(e[0]).toMatchObject({
|
|
735
834
|
id: "u1",
|
|
736
835
|
title: "second",
|
|
@@ -746,21 +845,21 @@ var K = h("voltro_parity_composite", {
|
|
|
746
845
|
"{\"a\":1}",
|
|
747
846
|
"\"quoted\""
|
|
748
847
|
])("JSON scalar string %j survives insert and update", async (e) => {
|
|
749
|
-
let t =
|
|
848
|
+
let t = G.tableName, n = await r.store.insert(t, {
|
|
750
849
|
id: "json-string",
|
|
751
850
|
title: "before",
|
|
752
851
|
metadata: e,
|
|
753
852
|
labels: []
|
|
754
853
|
});
|
|
755
|
-
k(n.metadata).toBe(e), k((await r.store.query(
|
|
854
|
+
k(n.metadata).toBe(e), k((await r.store.query(z(t)))[0]?.metadata).toBe(e), await r.store.transactional(async (n) => {
|
|
756
855
|
let r = await n.update(t, "json-string", { metadata: `${e}\nupdated` });
|
|
757
856
|
k(r?.metadata).toBe(`${e}\nupdated`);
|
|
758
|
-
}), k((await r.store.query(
|
|
857
|
+
}), k((await r.store.query(z(t)))[0]?.metadata).toBe(`${e}\nupdated`);
|
|
759
858
|
}), A("JSON validity checks are not introspected as enum membership", async () => {
|
|
760
859
|
let e = (await r.run(b.gen(function* () {
|
|
761
|
-
let e = yield*
|
|
762
|
-
return yield*
|
|
763
|
-
}))).tables.find((e) => e.name ===
|
|
860
|
+
let e = yield* M.SqlClient;
|
|
861
|
+
return yield* L(e);
|
|
862
|
+
}))).tables.find((e) => e.name === G.tableName)?.columns.find((e) => e.name === "metadata");
|
|
764
863
|
k(e).toBeDefined(), k(e?.oneOf).toBeUndefined(), n.dialect.id === "mssql" && (k(e?.jsonValidation).toBe("value"), k(e?.jsonChecks).toEqual([{
|
|
765
864
|
name: k.any(String),
|
|
766
865
|
validation: "value",
|
|
@@ -769,10 +868,10 @@ var K = h("voltro_parity_composite", {
|
|
|
769
868
|
}]));
|
|
770
869
|
}), n.dialect.id === "mssql" && A("JSON check catalog includes table-level names and enforcement state", async () => {
|
|
771
870
|
let e = (e) => r.run(b.gen(function* () {
|
|
772
|
-
yield* (yield*
|
|
871
|
+
yield* (yield* M.SqlClient).unsafe(e);
|
|
773
872
|
})), t = () => r.run(b.gen(function* () {
|
|
774
|
-
let e = yield*
|
|
775
|
-
return (yield*
|
|
873
|
+
let e = yield* M.SqlClient;
|
|
874
|
+
return (yield* L(e)).tables.find((e) => e.name === "voltro_parity_json_checks")?.columns.find((e) => e.name === "metadata")?.jsonChecks;
|
|
776
875
|
}));
|
|
777
876
|
await e("CREATE TABLE voltro_parity_json_checks (id INT PRIMARY KEY, metadata NVARCHAR(MAX), CONSTRAINT json_container_probe CHECK (metadata IS NULL OR ISJSON(metadata) = 1), CONSTRAINT custom_json_probe CHECK (metadata IS NULL OR LEN(metadata) > 2))");
|
|
778
877
|
try {
|
|
@@ -817,12 +916,12 @@ var K = h("voltro_parity_composite", {
|
|
|
817
916
|
id: c(),
|
|
818
917
|
[a]: n ? u().nullable().renamedFrom("metadata") : u().nullable()
|
|
819
918
|
})], s = (e) => r.run(b.gen(function* () {
|
|
820
|
-
return yield* (yield*
|
|
821
|
-
})), l = (e) =>
|
|
919
|
+
return yield* (yield* M.SqlClient).unsafe(e);
|
|
920
|
+
})), l = (e) => L(e).pipe(b.map((e) => R({
|
|
822
921
|
declared: o,
|
|
823
922
|
dialect: "mssql",
|
|
824
923
|
live: { tables: e.tables.filter((e) => e.name === i) }
|
|
825
|
-
}))), d = () => r.run(
|
|
924
|
+
}))), d = () => r.run(M.SqlClient.pipe(b.flatMap(l)));
|
|
826
925
|
await r.migrate([e]), await s(`CREATE TABLE ${i} (id VARCHAR(64) PRIMARY KEY, metadata NVARCHAR(MAX) NULL, CONSTRAINT upgrade_json_old CHECK (metadata IS NULL OR ISJSON(metadata)=1), CONSTRAINT upgrade_json_custom CHECK NOT FOR REPLICATION (metadata IS NULL OR (LEN(metadata)<100 AND metadata<>N'"[metadata]"')))`);
|
|
827
926
|
try {
|
|
828
927
|
let e = () => s(`SELECT is_disabled AS disabled, is_not_trusted AS untrusted, is_not_for_replication AS notForReplication FROM sys.check_constraints WHERE parent_object_id=OBJECT_ID('${i}') AND name='upgrade_json_custom'`), c = await e();
|
|
@@ -845,8 +944,8 @@ var K = h("voltro_parity_composite", {
|
|
|
845
944
|
dropConstraints: ["upgrade_json_old"]
|
|
846
945
|
}]);
|
|
847
946
|
let f = r.run(b.gen(function* () {
|
|
848
|
-
let e = yield*
|
|
849
|
-
return yield*
|
|
947
|
+
let e = yield* M.SqlClient;
|
|
948
|
+
return yield* N(e, u, {
|
|
850
949
|
declared: o,
|
|
851
950
|
appliedBy: "json-parity",
|
|
852
951
|
environment: "dev",
|
|
@@ -867,8 +966,8 @@ var K = h("voltro_parity_composite", {
|
|
|
867
966
|
id: c(),
|
|
868
967
|
renamed: g().nullable().renamedFrom("original")
|
|
869
968
|
})], a = (e) => r.run(b.gen(function* () {
|
|
870
|
-
return yield* (yield*
|
|
871
|
-
})), o = (e) =>
|
|
969
|
+
return yield* (yield* M.SqlClient).unsafe(e);
|
|
970
|
+
})), o = (e) => L(e).pipe(b.map((e) => R({
|
|
872
971
|
declared: i,
|
|
873
972
|
dialect: "mssql",
|
|
874
973
|
live: { tables: e.tables.filter((e) => e.name === n) }
|
|
@@ -882,8 +981,8 @@ var K = h("voltro_parity_composite", {
|
|
|
882
981
|
disabled: t === "disabled",
|
|
883
982
|
untrusted: t !== "trusted"
|
|
884
983
|
}]), await a(`INSERT INTO ${n} (id,original) VALUES ('kept','${t === "disabled" ? "long invalid existing value" : "valid"}')`), await r.run(b.gen(function* () {
|
|
885
|
-
let e = yield*
|
|
886
|
-
k(t.operations.map((e) => e.op.kind)).toEqual(["rename-column"]), yield*
|
|
984
|
+
let e = yield* M.SqlClient, t = yield* o(e);
|
|
985
|
+
k(t.operations.map((e) => e.op.kind)).toEqual(["rename-column"]), yield* N(e, t, {
|
|
887
986
|
declared: i,
|
|
888
987
|
appliedBy: "rename-parity",
|
|
889
988
|
environment: "dev",
|
|
@@ -902,8 +1001,8 @@ var K = h("voltro_parity_composite", {
|
|
|
902
1001
|
metadata: u().nullable(),
|
|
903
1002
|
labels: t(g()).nullable()
|
|
904
1003
|
})], o = (e) => r.run(b.gen(function* () {
|
|
905
|
-
return yield* (yield*
|
|
906
|
-
})), s = (e) =>
|
|
1004
|
+
return yield* (yield* M.SqlClient).unsafe(e);
|
|
1005
|
+
})), s = (e) => L(e).pipe(b.map((e) => R({
|
|
907
1006
|
declared: a,
|
|
908
1007
|
dialect: "mssql",
|
|
909
1008
|
live: { tables: e.tables.filter((e) => e.name === i) }
|
|
@@ -911,8 +1010,8 @@ var K = h("voltro_parity_composite", {
|
|
|
911
1010
|
await r.migrate([e]), n === "add" && (await o(`CREATE TABLE ${i} (id VARCHAR(64) PRIMARY KEY)`), await o(`INSERT INTO ${i} (id) VALUES ('existing')`));
|
|
912
1011
|
try {
|
|
913
1012
|
await r.run(b.gen(function* () {
|
|
914
|
-
let e = yield*
|
|
915
|
-
k(t.operations.map((e) => e.op.kind)).toEqual(n === "create" ? ["create-table"] : ["add-column", "add-column"]), yield*
|
|
1013
|
+
let e = yield* M.SqlClient, t = yield* s(e);
|
|
1014
|
+
k(t.operations.map((e) => e.op.kind)).toEqual(n === "create" ? ["create-table"] : ["add-column", "add-column"]), yield* N(e, t, {
|
|
916
1015
|
declared: a,
|
|
917
1016
|
appliedBy: "json-ddl",
|
|
918
1017
|
environment: "dev",
|
|
@@ -935,8 +1034,8 @@ var K = h("voltro_parity_composite", {
|
|
|
935
1034
|
"undefined"
|
|
936
1035
|
])("JSON check rejects raw invalid value %j", async (e) => {
|
|
937
1036
|
await k(r.run(b.gen(function* () {
|
|
938
|
-
let t = yield*
|
|
939
|
-
yield* t`INSERT INTO ${t(
|
|
1037
|
+
let t = yield* M.SqlClient;
|
|
1038
|
+
yield* t`INSERT INTO ${t(G.tableName)} (${t("id")}, ${t("title")}, ${t("metadata")}) VALUES (${"invalid-json"}, ${"probe"}, ${e})`;
|
|
940
1039
|
}))).rejects.toThrow();
|
|
941
1040
|
}), O.each(["direct", "transactional"])("upsert recorder atomicity (%s)", (e) => {
|
|
942
1041
|
A.each([
|
|
@@ -988,13 +1087,13 @@ var K = h("voltro_parity_composite", {
|
|
|
988
1087
|
await k(m({
|
|
989
1088
|
traceId: "recorder-trace",
|
|
990
1089
|
subjectId: "recorder-subject"
|
|
991
|
-
}, () => e === "direct" ? d(a) : a.transactional(d))).rejects.toThrow("recorder refused"), k(await a.query(
|
|
1090
|
+
}, () => e === "direct" ? d(a) : a.transactional(d))).rejects.toThrow("recorder refused"), k(await a.query(z(o))).toEqual(i ? [s] : []), k(await a.query(z("voltro_parity_b"))).toEqual([]), k(l).toEqual([]);
|
|
992
1091
|
} finally {
|
|
993
1092
|
y(c), u();
|
|
994
1093
|
}
|
|
995
1094
|
});
|
|
996
1095
|
}), A("structured write returns and change images decode exactly once", async () => {
|
|
997
|
-
let e = r.store, t =
|
|
1096
|
+
let e = r.store, t = G.tableName, n = [], i = e.onChange((e) => {
|
|
998
1097
|
e.table === t && n.push((e.new ?? e.old)?.metadata);
|
|
999
1098
|
}), a = (e) => ({
|
|
1000
1099
|
id: e,
|
|
@@ -1249,7 +1348,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1249
1348
|
title: "after",
|
|
1250
1349
|
metadata: i,
|
|
1251
1350
|
labels: []
|
|
1252
|
-
}), k(await t.query(
|
|
1351
|
+
}), k(await t.query(z("voltro_parity_values"))).toEqual([{
|
|
1253
1352
|
id: "patch",
|
|
1254
1353
|
title: "after",
|
|
1255
1354
|
metadata: i,
|
|
@@ -1266,15 +1365,15 @@ var K = h("voltro_parity_composite", {
|
|
|
1266
1365
|
};
|
|
1267
1366
|
await e.insert("voltro_parity_values", t);
|
|
1268
1367
|
for (let t of [{ id: "renamed" }, { metadata: {} }]) await k(e.patchJson("voltro_parity_values", "refuse", "metadata.value", 1, t)).rejects.toThrow("cannot rewrite");
|
|
1269
|
-
k(await e.query(
|
|
1368
|
+
k(await e.query(z("voltro_parity_values"))).toEqual([t]), k(await e.patchJson("voltro_parity_values", "missing", "metadata.value", 1, { title: "absent" })).toBeNull();
|
|
1270
1369
|
});
|
|
1271
1370
|
}), A("does not confuse JSON columns named key/value with iterator columns", async () => {
|
|
1272
1371
|
await t(async (e) => {
|
|
1273
|
-
await e.insert(
|
|
1372
|
+
await e.insert(K.tableName, {
|
|
1274
1373
|
id: "names",
|
|
1275
1374
|
key: { "a\"b": { keep: !0 } },
|
|
1276
1375
|
value: { "c\\d": { keep: !1 } }
|
|
1277
|
-
}), await e.patchJson(
|
|
1376
|
+
}), await e.patchJson(K.tableName, "names", "key.a\"b.changed", !1), await e.patchJson(K.tableName, "names", "value.c\\d.changed", !0), k(await e.query(z(K.tableName))).toEqual([{
|
|
1278
1377
|
id: "names",
|
|
1279
1378
|
key: { "a\"b": {
|
|
1280
1379
|
keep: !0,
|
|
@@ -1288,11 +1387,11 @@ var K = h("voltro_parity_composite", {
|
|
|
1288
1387
|
});
|
|
1289
1388
|
}), A("executes application onUpdate across keyed, bulk, upsert and JSON writes", async () => {
|
|
1290
1389
|
let t = C([{
|
|
1291
|
-
tableName:
|
|
1292
|
-
fields:
|
|
1390
|
+
tableName: U.tableName,
|
|
1391
|
+
fields: U.fields
|
|
1293
1392
|
}, {
|
|
1294
|
-
tableName:
|
|
1295
|
-
fields:
|
|
1393
|
+
tableName: G.tableName,
|
|
1394
|
+
fields: G.fields
|
|
1296
1395
|
}]), n = T(r.store, {
|
|
1297
1396
|
subject: {
|
|
1298
1397
|
type: "anonymous",
|
|
@@ -1319,7 +1418,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1319
1418
|
conflictColumns: ["id"],
|
|
1320
1419
|
update: n === "callback" ? () => ({ title: "edited" }) : ["title"]
|
|
1321
1420
|
});
|
|
1322
|
-
let r = await e.query(
|
|
1421
|
+
let r = await e.query(z("voltro_parity_d"));
|
|
1323
1422
|
k(r).toHaveLength(4);
|
|
1324
1423
|
for (let e of r) {
|
|
1325
1424
|
k(e).toMatchObject({
|
|
@@ -1334,7 +1433,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1334
1433
|
title: "original",
|
|
1335
1434
|
metadata: { keep: !0 },
|
|
1336
1435
|
labels: []
|
|
1337
|
-
}), await e.patchJson("voltro_parity_values", "automatic", "metadata.child.value", !1), k(await e.query(
|
|
1436
|
+
}), await e.patchJson("voltro_parity_values", "automatic", "metadata.child.value", !1), k(await e.query(z("voltro_parity_values"))).toEqual([{
|
|
1338
1437
|
id: "automatic",
|
|
1339
1438
|
title: "automatic",
|
|
1340
1439
|
metadata: {
|
|
@@ -1359,14 +1458,14 @@ var K = h("voltro_parity_composite", {
|
|
|
1359
1458
|
metadata: { keep: !0 },
|
|
1360
1459
|
labels: []
|
|
1361
1460
|
};
|
|
1362
|
-
await r.store.insert("voltro_parity_values", e), await k(r.store.patchJson("voltro_parity_values", e.id, "metadata.changed", !0, { title: null })).rejects.toThrow(), k(await r.store.query(
|
|
1461
|
+
await r.store.insert("voltro_parity_values", e), await k(r.store.patchJson("voltro_parity_values", e.id, "metadata.changed", !0, { title: null })).rejects.toThrow(), k(await r.store.query(z("voltro_parity_values"))).toEqual([e]);
|
|
1363
1462
|
}), A("concurrent JSON patches preserve every sibling and the companion write", async () => {
|
|
1364
1463
|
await r.store.insert("voltro_parity_values", {
|
|
1365
1464
|
id: "concurrent-json",
|
|
1366
1465
|
title: "before",
|
|
1367
1466
|
metadata: {},
|
|
1368
1467
|
labels: []
|
|
1369
|
-
}), await Promise.all(Array.from({ length: 8 }, (e, t) => r.store.transactional((e) => e.patchJson("voltro_parity_values", "concurrent-json", `metadata.key${t}`, t, { title: "after" })))), k(await r.store.query(
|
|
1468
|
+
}), await Promise.all(Array.from({ length: 8 }, (e, t) => r.store.transactional((e) => e.patchJson("voltro_parity_values", "concurrent-json", `metadata.key${t}`, t, { title: "after" })))), k(await r.store.query(z("voltro_parity_values"))).toEqual([{
|
|
1370
1469
|
id: "concurrent-json",
|
|
1371
1470
|
title: "after",
|
|
1372
1471
|
metadata: Object.fromEntries(Array.from({ length: 8 }, (e, t) => [`key${t}`, t])),
|
|
@@ -1387,7 +1486,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1387
1486
|
conflictColumns: ["teamId", "year"],
|
|
1388
1487
|
update: ["hours"]
|
|
1389
1488
|
});
|
|
1390
|
-
let e = await r.store.query(
|
|
1489
|
+
let e = await r.store.query(z("voltro_parity_upsert"));
|
|
1391
1490
|
k(e.length, "the second upsert inserted a duplicate instead of updating").toBe(1), k(e[0]).toMatchObject({
|
|
1392
1491
|
id: "up_first",
|
|
1393
1492
|
teamId: "t-1",
|
|
@@ -1426,7 +1525,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1426
1525
|
n: 42
|
|
1427
1526
|
}), k(new Date(String(i.at)).toISOString()).toBe(e.toISOString());
|
|
1428
1527
|
});
|
|
1429
|
-
let [i] = await r.store.query(
|
|
1528
|
+
let [i] = await r.store.query(z("voltro_parity_d"));
|
|
1430
1529
|
k(i).toMatchObject({
|
|
1431
1530
|
id: "constant",
|
|
1432
1531
|
title: "Lobby",
|
|
@@ -1461,7 +1560,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1461
1560
|
year: 2026,
|
|
1462
1561
|
hours: 42
|
|
1463
1562
|
});
|
|
1464
|
-
}), k(await r.store.query(
|
|
1563
|
+
}), k(await r.store.query(z("voltro_parity_upsert"))).toEqual([k.objectContaining({
|
|
1465
1564
|
id: "original",
|
|
1466
1565
|
teamId: "t1",
|
|
1467
1566
|
year: 2026,
|
|
@@ -1521,7 +1620,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1521
1620
|
count: 0
|
|
1522
1621
|
}
|
|
1523
1622
|
});
|
|
1524
|
-
let n = await e.query(
|
|
1623
|
+
let n = await e.query(z("voltro_parity_c"));
|
|
1525
1624
|
k(n).toEqual([k.objectContaining({
|
|
1526
1625
|
id: "falsy",
|
|
1527
1626
|
title: "keep",
|
|
@@ -1553,7 +1652,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1553
1652
|
update: [],
|
|
1554
1653
|
updateValues: n
|
|
1555
1654
|
};
|
|
1556
|
-
await e.upsert("voltro_parity_values", t, r), k(await e.query(
|
|
1655
|
+
await e.upsert("voltro_parity_values", t, r), k(await e.query(z("voltro_parity_values"))).toEqual([t]), await e.upsert("voltro_parity_values", t, r), k(await e.query(z("voltro_parity_values"))).toEqual([{
|
|
1557
1656
|
id: "structured",
|
|
1558
1657
|
...n
|
|
1559
1658
|
}]), await e.upsert("voltro_parity_values", t, {
|
|
@@ -1562,7 +1661,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1562
1661
|
metadata: null,
|
|
1563
1662
|
labels: []
|
|
1564
1663
|
}
|
|
1565
|
-
}), k(await e.query(
|
|
1664
|
+
}), k(await e.query(z("voltro_parity_values"))).toEqual([{
|
|
1566
1665
|
id: "structured",
|
|
1567
1666
|
title: n.title,
|
|
1568
1667
|
metadata: null,
|
|
@@ -1602,7 +1701,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1602
1701
|
id: "ignore-new",
|
|
1603
1702
|
...n
|
|
1604
1703
|
}, { conflictColumns: ["id"] });
|
|
1605
|
-
let r = await e.query(
|
|
1704
|
+
let r = await e.query(z("voltro_parity_values"));
|
|
1606
1705
|
k([...r].sort((e, t) => String(e.id).localeCompare(String(t.id)))).toEqual([
|
|
1607
1706
|
{
|
|
1608
1707
|
id: "bulk",
|
|
@@ -1638,7 +1737,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1638
1737
|
update: [],
|
|
1639
1738
|
updateValues: { [e]: "different" }
|
|
1640
1739
|
};
|
|
1641
|
-
await k(t.upsert("voltro_parity_upsert", n, r)).rejects.toThrow("identity"), k(await t.query(
|
|
1740
|
+
await k(t.upsert("voltro_parity_upsert", n, r)).rejects.toThrow("identity"), k(await t.query(z("voltro_parity_upsert"))).toEqual([]), await t.insert("voltro_parity_upsert", n), await k(t.upsert("voltro_parity_upsert", n, r)).rejects.toThrow("identity"), k(await t.query(z("voltro_parity_upsert"))).toEqual([k.objectContaining(n)]);
|
|
1642
1741
|
});
|
|
1643
1742
|
});
|
|
1644
1743
|
}), A("upsert updateValues rolls back row changes and discards transaction events", async () => {
|
|
@@ -1665,7 +1764,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1665
1764
|
title: "keep",
|
|
1666
1765
|
count: 42
|
|
1667
1766
|
}), Error("rollback values");
|
|
1668
|
-
})).rejects.toThrow("rollback values"), k(await r.store.query(
|
|
1767
|
+
})).rejects.toThrow("rollback values"), k(await r.store.query(z("voltro_parity_a"))).toEqual([k.objectContaining({
|
|
1669
1768
|
id: "rollback-values",
|
|
1670
1769
|
title: "keep",
|
|
1671
1770
|
count: 1
|
|
@@ -1688,7 +1787,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1688
1787
|
conflictColumns: ["teamId", "year"],
|
|
1689
1788
|
update: ["hours"]
|
|
1690
1789
|
});
|
|
1691
|
-
let e = await r.store.query(
|
|
1790
|
+
let e = await r.store.query(z("voltro_parity_upsert"));
|
|
1692
1791
|
k(e.length).toBe(2), k([...e].map((e) => e.hours).sort()).toEqual([1, 2]);
|
|
1693
1792
|
}), A("insert + update bind an explicit NULL into a datetime2/int column", async () => {
|
|
1694
1793
|
let e = await r.store.insert("voltro_parity_d", {
|
|
@@ -1738,7 +1837,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1738
1837
|
} });
|
|
1739
1838
|
k(e).toBe(2);
|
|
1740
1839
|
let t = await r.store.query({
|
|
1741
|
-
...
|
|
1840
|
+
...z("voltro_parity_a"),
|
|
1742
1841
|
predicate: {
|
|
1743
1842
|
column: "title",
|
|
1744
1843
|
op: "eq",
|
|
@@ -1784,7 +1883,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1784
1883
|
value: 5
|
|
1785
1884
|
} });
|
|
1786
1885
|
k(e).toBe(2);
|
|
1787
|
-
let t = await r.store.query(
|
|
1886
|
+
let t = await r.store.query(z("voltro_parity_a"));
|
|
1788
1887
|
k(t.map((e) => e.id)).toEqual(["d3"]);
|
|
1789
1888
|
}), A("deleteMany emits one delete ChangeEvent per removed row (old-image)", async () => {
|
|
1790
1889
|
await r.store.insert("voltro_parity_a", {
|
|
@@ -1823,7 +1922,7 @@ var K = h("voltro_parity_composite", {
|
|
|
1823
1922
|
value: "absent"
|
|
1824
1923
|
} });
|
|
1825
1924
|
k(e).toBe(0);
|
|
1826
|
-
let t = await r.store.query(
|
|
1925
|
+
let t = await r.store.query(z("voltro_parity_a"));
|
|
1827
1926
|
k(t.length).toBe(1);
|
|
1828
1927
|
}), A("retryFilter recognises the dialect's own transient codes", () => {
|
|
1829
1928
|
let e = n.dialect.retryFilter(/* @__PURE__ */ Error("garbage"));
|
|
@@ -1832,4 +1931,4 @@ var K = h("voltro_parity_composite", {
|
|
|
1832
1931
|
});
|
|
1833
1932
|
};
|
|
1834
1933
|
//#endregion
|
|
1835
|
-
export {
|
|
1934
|
+
export { P as applySchema, X as runDialectParity };
|