@prisma-next/sql-runtime 0.14.0-dev.6 → 0.14.0-dev.61
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/{exports-BXdIMaxT.mjs → exports-DDMKrdHY.mjs} +46 -4
- package/dist/exports-DDMKrdHY.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{prepared-statement-FQyyQnkC.d.mts → prepared-statement-BiwAFEou.d.mts} +14 -2
- package/dist/prepared-statement-BiwAFEou.d.mts.map +1 -0
- package/dist/test/utils.d.mts +413 -6
- package/dist/test/utils.d.mts.map +1 -1
- package/dist/test/utils.mjs +482 -8
- package/dist/test/utils.mjs.map +1 -1
- package/package.json +12 -12
- package/src/codecs/decoding.ts +40 -1
- package/src/codecs/encoding.ts +26 -0
- package/dist/exports-BXdIMaxT.mjs.map +0 -1
- package/dist/prepared-statement-FQyyQnkC.d.mts.map +0 -1
package/dist/test/utils.mjs
CHANGED
|
@@ -1,16 +1,484 @@
|
|
|
1
|
-
import { i as createSqlExecutionStack, r as
|
|
1
|
+
import { a as createExecutionContext, i as decodeRow, o as createSqlExecutionStack, r as buildDecodeContext, t as SqlRuntimeBase } from "../exports-DDMKrdHY.mjs";
|
|
2
2
|
import { canonicalizeJson } from "@prisma-next/framework-components/utils";
|
|
3
3
|
import { runtimeError } from "@prisma-next/framework-components/runtime";
|
|
4
4
|
import { SelectAst, TableSource } from "@prisma-next/sql-relational-core/ast";
|
|
5
5
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
6
6
|
import { instantiateExecutionStack } from "@prisma-next/framework-components/execution";
|
|
7
|
-
import {
|
|
7
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
8
|
+
import { asNamespaceId, coreHash, profileHash } from "@prisma-next/contract/types";
|
|
8
9
|
import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
|
|
9
|
-
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
10
|
+
import { IRNodeBase, NamespaceBase, UNBOUND_NAMESPACE_ID, freezeNode, hydrateNamespaceEntities } from "@prisma-next/framework-components/ir";
|
|
10
11
|
import { builtinGeneratorIds } from "@prisma-next/ids";
|
|
11
12
|
import { generateId } from "@prisma-next/ids/runtime";
|
|
12
|
-
import { SqlStorage
|
|
13
|
+
import { SqlStorage } from "@prisma-next/sql-contract/types";
|
|
13
14
|
import { applicationDomainOf, collectAsync, collectAsync as collectAsync$1, createDevDatabase, drainAsyncIterable, teardownTestDatabase, withClient } from "@prisma-next/test-utils";
|
|
15
|
+
import { type } from "arktype";
|
|
16
|
+
//#region ../1-core/contract/src/ir/storage-entry-schemas.ts
|
|
17
|
+
const literalKindSchema = type("'literal'");
|
|
18
|
+
const functionKindSchema = type("'function'");
|
|
19
|
+
const ControlPolicySchema = type("'managed' | 'tolerated' | 'external' | 'observed'");
|
|
20
|
+
const ColumnDefaultLiteralSchema = type.declare().type({
|
|
21
|
+
kind: literalKindSchema,
|
|
22
|
+
value: "string | number | boolean | null | unknown[] | Record<string, unknown>"
|
|
23
|
+
});
|
|
24
|
+
const ColumnDefaultFunctionSchema = type.declare().type({
|
|
25
|
+
kind: functionKindSchema,
|
|
26
|
+
expression: "string"
|
|
27
|
+
});
|
|
28
|
+
const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);
|
|
29
|
+
const StorageValueSetRefSchema = type({
|
|
30
|
+
plane: "'storage'",
|
|
31
|
+
namespaceId: "string",
|
|
32
|
+
entityKind: "'valueSet'",
|
|
33
|
+
entityName: "string",
|
|
34
|
+
"spaceId?": "string"
|
|
35
|
+
});
|
|
36
|
+
const StorageColumnSchema = type({
|
|
37
|
+
"+": "reject",
|
|
38
|
+
nativeType: "string",
|
|
39
|
+
codecId: "string",
|
|
40
|
+
nullable: "boolean",
|
|
41
|
+
"many?": "boolean",
|
|
42
|
+
"typeParams?": "Record<string, unknown>",
|
|
43
|
+
"typeRef?": "string",
|
|
44
|
+
"default?": ColumnDefaultSchema,
|
|
45
|
+
"control?": ControlPolicySchema,
|
|
46
|
+
"valueSet?": StorageValueSetRefSchema
|
|
47
|
+
}).narrow((col, ctx) => {
|
|
48
|
+
if (col.typeParams !== void 0 && col.typeRef !== void 0) return ctx.mustBe("a column with either typeParams or typeRef, not both");
|
|
49
|
+
return true;
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Storage value-set entry under `storage.namespaces[id].entries.valueSet[name]`.
|
|
53
|
+
* Carries a `kind: 'valueSet'` discriminator (enumerable, survives JSON) and an
|
|
54
|
+
* ordered `values` array of codec-encoded permitted values.
|
|
55
|
+
*/
|
|
56
|
+
const StorageValueSetSchema = type({
|
|
57
|
+
kind: "'valueSet'",
|
|
58
|
+
values: type("string | number | boolean | null | unknown[] | Record<string, unknown>").array().readonly()
|
|
59
|
+
});
|
|
60
|
+
const PrimaryKeySchema = type.declare().type({
|
|
61
|
+
columns: type.string.array().readonly(),
|
|
62
|
+
"name?": "string"
|
|
63
|
+
});
|
|
64
|
+
const UniqueConstraintSchema = type.declare().type({
|
|
65
|
+
columns: type.string.array().readonly(),
|
|
66
|
+
"name?": "string"
|
|
67
|
+
});
|
|
68
|
+
const IndexSchema = type({
|
|
69
|
+
columns: type.string.array().readonly(),
|
|
70
|
+
"name?": "string",
|
|
71
|
+
"type?": "string",
|
|
72
|
+
"options?": "Record<string, unknown>"
|
|
73
|
+
});
|
|
74
|
+
const ForeignKeyReferenceSchema = type({
|
|
75
|
+
"+": "reject",
|
|
76
|
+
namespaceId: "string",
|
|
77
|
+
tableName: "string",
|
|
78
|
+
columns: type.string.array().readonly(),
|
|
79
|
+
"spaceId?": "string"
|
|
80
|
+
});
|
|
81
|
+
const ForeignKeySourceSchema = type({
|
|
82
|
+
"+": "reject",
|
|
83
|
+
namespaceId: "string",
|
|
84
|
+
tableName: "string",
|
|
85
|
+
columns: type.string.array().readonly()
|
|
86
|
+
});
|
|
87
|
+
const ReferentialActionSchema = type.declare().type("'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'");
|
|
88
|
+
const ForeignKeySchema = type.declare().type({
|
|
89
|
+
source: ForeignKeySourceSchema,
|
|
90
|
+
target: ForeignKeyReferenceSchema,
|
|
91
|
+
"name?": "string",
|
|
92
|
+
"onDelete?": ReferentialActionSchema,
|
|
93
|
+
"onUpdate?": ReferentialActionSchema,
|
|
94
|
+
constraint: "boolean",
|
|
95
|
+
index: "boolean"
|
|
96
|
+
});
|
|
97
|
+
const CheckConstraintSchema = type({
|
|
98
|
+
"+": "reject",
|
|
99
|
+
name: "string",
|
|
100
|
+
column: "string",
|
|
101
|
+
valueSet: StorageValueSetRefSchema
|
|
102
|
+
});
|
|
103
|
+
const StorageTableSchema = type({
|
|
104
|
+
"+": "reject",
|
|
105
|
+
columns: type({ "[string]": StorageColumnSchema }),
|
|
106
|
+
"primaryKey?": PrimaryKeySchema,
|
|
107
|
+
uniques: UniqueConstraintSchema.array().readonly(),
|
|
108
|
+
indexes: IndexSchema.array().readonly(),
|
|
109
|
+
foreignKeys: ForeignKeySchema.array().readonly(),
|
|
110
|
+
"control?": ControlPolicySchema,
|
|
111
|
+
"checks?": CheckConstraintSchema.array().readonly()
|
|
112
|
+
});
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region ../1-core/contract/src/ir/sql-node.ts
|
|
115
|
+
/**
|
|
116
|
+
* SQL family IR node base. Carries the family-level `kind` discriminator
|
|
117
|
+
* `'sql'` and inherits the framework's `freezeNode` affordance.
|
|
118
|
+
*
|
|
119
|
+
* Single family-level discriminator (not per-leaf) reflects the fact that
|
|
120
|
+
* SQL IR has no polymorphic dispatch today — verifiers and serializers
|
|
121
|
+
* walk by structural position (`storage.tables[name].columns[name]`),
|
|
122
|
+
* not by inspecting `kind`. The abstract bar for per-leaf discriminators
|
|
123
|
+
* isn't earned until a future polymorphic consumer arrives.
|
|
124
|
+
*
|
|
125
|
+
* `kind` is installed as a non-enumerable own property on every instance,
|
|
126
|
+
* which keeps three things clean simultaneously:
|
|
127
|
+
*
|
|
128
|
+
* - `JSON.stringify(node)` produces the canonical pre-lift JSON envelope
|
|
129
|
+
* shape (no `kind` field), so emitted contract.json files and the
|
|
130
|
+
* `validateSqlContractFully` arktype schemas stay unchanged.
|
|
131
|
+
* - Test assertions that use `toEqual({...})` against the pre-lift flat
|
|
132
|
+
* shape continue to pass — only enumerable own properties are
|
|
133
|
+
* compared.
|
|
134
|
+
* - Direct access (`node.kind`) and runtime narrowing
|
|
135
|
+
* (`if (node.kind === 'sql')`) still work, so future polymorphic
|
|
136
|
+
* dispatch can begin reading `kind` without a runtime change.
|
|
137
|
+
*
|
|
138
|
+
* Future per-leaf overrides land cleanly: a class that gains a
|
|
139
|
+
* polymorphic-dispatch consumer (e.g. an enum type instance walked
|
|
140
|
+
* alongside other types) overrides `kind` with its narrower literal
|
|
141
|
+
* at that leaf level. Per-leaf overrides will use enumerable kind
|
|
142
|
+
* (matching the Mongo per-class-discriminator precedent) because they
|
|
143
|
+
* encode dispatch-relevant information that callers need to see in
|
|
144
|
+
* JSON envelopes; the family-level `'sql'` is uniform across all SQL
|
|
145
|
+
* IR and carries no dispatch-relevant information.
|
|
146
|
+
*/
|
|
147
|
+
var SqlNode = class extends IRNodeBase {
|
|
148
|
+
kind;
|
|
149
|
+
constructor() {
|
|
150
|
+
super();
|
|
151
|
+
Object.defineProperty(this, "kind", {
|
|
152
|
+
value: "sql",
|
|
153
|
+
writable: false,
|
|
154
|
+
enumerable: false,
|
|
155
|
+
configurable: true
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region ../1-core/contract/src/ir/check-constraint.ts
|
|
161
|
+
/**
|
|
162
|
+
* SQL Contract IR node for a table-level check constraint that restricts
|
|
163
|
+
* a column to the permitted values of a value-set.
|
|
164
|
+
*
|
|
165
|
+
* The constraint is **structured** (names a column and a value-set
|
|
166
|
+
* reference), not a raw SQL expression. Each target renders its own DDL
|
|
167
|
+
* from the structured form, keeping the contract target-agnostic.
|
|
168
|
+
*
|
|
169
|
+
* Construction is idempotent: passing an existing `CheckConstraint`
|
|
170
|
+
* instance as input produces a new instance with identical fields.
|
|
171
|
+
* The constructor does not use `instanceof` for input discrimination —
|
|
172
|
+
* it reads plain named properties, which is sufficient since
|
|
173
|
+
* `CheckConstraintInput` is a structural type.
|
|
174
|
+
*/
|
|
175
|
+
var CheckConstraint = class extends SqlNode {
|
|
176
|
+
name;
|
|
177
|
+
column;
|
|
178
|
+
valueSet;
|
|
179
|
+
constructor(input) {
|
|
180
|
+
super();
|
|
181
|
+
this.name = input.name;
|
|
182
|
+
this.column = input.column;
|
|
183
|
+
this.valueSet = input.valueSet;
|
|
184
|
+
freezeNode(this);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region ../1-core/contract/src/ir/foreign-key-reference.ts
|
|
189
|
+
/**
|
|
190
|
+
* SQL Contract IR node for one side (source or target) of a foreign-key
|
|
191
|
+
* declaration. Carries the full coordinate: namespace, table, and columns.
|
|
192
|
+
*
|
|
193
|
+
* Cross-space discrimination is based on `spaceId` presence: absent means
|
|
194
|
+
* local (same contract-space); present means cross-space (the referenced
|
|
195
|
+
* table lives in the contract-space identified by `spaceId`).
|
|
196
|
+
*
|
|
197
|
+
* For local references `spaceId` is absent from JSON, keeping the serialized
|
|
198
|
+
* shape byte-identical to contracts authored before cross-space support was
|
|
199
|
+
* added. For cross-space references `spaceId` appears in JSON so round-trips
|
|
200
|
+
* are lossless.
|
|
201
|
+
*
|
|
202
|
+
* Use `UNBOUND_NAMESPACE_ID` from `@prisma-next/framework-components/ir`
|
|
203
|
+
* as the sentinel `namespaceId` for single-namespace (unbound) references.
|
|
204
|
+
*/
|
|
205
|
+
var ForeignKeyReference = class extends SqlNode {
|
|
206
|
+
namespaceId;
|
|
207
|
+
tableName;
|
|
208
|
+
columns;
|
|
209
|
+
constructor(input) {
|
|
210
|
+
super();
|
|
211
|
+
this.namespaceId = asNamespaceId(input.namespaceId);
|
|
212
|
+
this.tableName = input.tableName;
|
|
213
|
+
this.columns = input.columns;
|
|
214
|
+
if (input.spaceId !== void 0) this.spaceId = input.spaceId;
|
|
215
|
+
freezeNode(this);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region ../1-core/contract/src/ir/foreign-key.ts
|
|
220
|
+
/**
|
|
221
|
+
* SQL Contract IR node for a table-level foreign-key declaration.
|
|
222
|
+
*
|
|
223
|
+
* Each FK carries explicit `source` and `target` {@link ForeignKeyReference}
|
|
224
|
+
* coordinates (namespace, table, columns). For single-namespace contracts the
|
|
225
|
+
* sentinel `UNBOUND_NAMESPACE_ID` appears on both sides.
|
|
226
|
+
*
|
|
227
|
+
* The nested references are normalised to {@link ForeignKeyReference}
|
|
228
|
+
* instances inside the constructor so downstream walks see a uniform AST
|
|
229
|
+
* regardless of whether the input was a JSON literal or an already-constructed
|
|
230
|
+
* class instance.
|
|
231
|
+
*/
|
|
232
|
+
var ForeignKey = class extends SqlNode {
|
|
233
|
+
source;
|
|
234
|
+
target;
|
|
235
|
+
constraint;
|
|
236
|
+
index;
|
|
237
|
+
constructor(input) {
|
|
238
|
+
super();
|
|
239
|
+
this.source = input.source instanceof ForeignKeyReference ? input.source : new ForeignKeyReference(input.source);
|
|
240
|
+
this.target = input.target instanceof ForeignKeyReference ? input.target : new ForeignKeyReference(input.target);
|
|
241
|
+
this.constraint = input.constraint;
|
|
242
|
+
this.index = input.index;
|
|
243
|
+
if (input.name !== void 0) this.name = input.name;
|
|
244
|
+
if (input.onDelete !== void 0) this.onDelete = input.onDelete;
|
|
245
|
+
if (input.onUpdate !== void 0) this.onUpdate = input.onUpdate;
|
|
246
|
+
freezeNode(this);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region ../1-core/contract/src/ir/primary-key.ts
|
|
251
|
+
/**
|
|
252
|
+
* SQL Contract IR node for a table's primary-key constraint.
|
|
253
|
+
*/
|
|
254
|
+
var PrimaryKey = class extends SqlNode {
|
|
255
|
+
columns;
|
|
256
|
+
constructor(input) {
|
|
257
|
+
super();
|
|
258
|
+
this.columns = input.columns;
|
|
259
|
+
if (input.name !== void 0) this.name = input.name;
|
|
260
|
+
freezeNode(this);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region ../1-core/contract/src/ir/sql-index.ts
|
|
265
|
+
/**
|
|
266
|
+
* SQL Contract IR node for a table-level secondary index.
|
|
267
|
+
*
|
|
268
|
+
* Note that this class shadows the global TypeScript `Index` lib type
|
|
269
|
+
* at the family-shared name; consumer files that need both should
|
|
270
|
+
* alias one (e.g.
|
|
271
|
+
* `import { Index as SqlIndexNode } from '@prisma-next/sql-contract/types'`).
|
|
272
|
+
*/
|
|
273
|
+
var Index = class extends SqlNode {
|
|
274
|
+
columns;
|
|
275
|
+
constructor(input) {
|
|
276
|
+
super();
|
|
277
|
+
this.columns = input.columns;
|
|
278
|
+
if (input.name !== void 0) this.name = input.name;
|
|
279
|
+
if (input.type !== void 0) this.type = input.type;
|
|
280
|
+
if (input.options !== void 0) this.options = input.options;
|
|
281
|
+
freezeNode(this);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region ../1-core/contract/src/ir/storage-column.ts
|
|
286
|
+
/**
|
|
287
|
+
* SQL Contract IR node for a single column entry in `StorageTable.columns`.
|
|
288
|
+
*
|
|
289
|
+
* Single concrete family-shared class — every SQL target reads the
|
|
290
|
+
* same column shape today, so there is no per-target subclass. The
|
|
291
|
+
* class type accepts any caller that constructs via
|
|
292
|
+
* `new StorageColumn(input)`; literal construction sites must pass
|
|
293
|
+
* through the constructor or the family-base hydration walker.
|
|
294
|
+
*
|
|
295
|
+
* The column's `name` is not on the class — columns are keyed by name
|
|
296
|
+
* in the parent `StorageTable.columns: Record<string, StorageColumn>`
|
|
297
|
+
* map, so a `name` field would be redundant with the key.
|
|
298
|
+
*/
|
|
299
|
+
var StorageColumn = class extends SqlNode {
|
|
300
|
+
nativeType;
|
|
301
|
+
codecId;
|
|
302
|
+
nullable;
|
|
303
|
+
constructor(input) {
|
|
304
|
+
super();
|
|
305
|
+
this.nativeType = input.nativeType;
|
|
306
|
+
this.codecId = input.codecId;
|
|
307
|
+
this.nullable = input.nullable;
|
|
308
|
+
if (input.many !== void 0) this.many = input.many;
|
|
309
|
+
if (input.typeParams !== void 0) this.typeParams = input.typeParams;
|
|
310
|
+
if (input.typeRef !== void 0) this.typeRef = input.typeRef;
|
|
311
|
+
if (input.default !== void 0) this.default = input.default;
|
|
312
|
+
if (input.control !== void 0) this.control = input.control;
|
|
313
|
+
if (input.valueSet !== void 0) this.valueSet = input.valueSet;
|
|
314
|
+
freezeNode(this);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region ../1-core/contract/src/ir/unique-constraint.ts
|
|
319
|
+
/**
|
|
320
|
+
* SQL Contract IR node for a table-level unique constraint.
|
|
321
|
+
*/
|
|
322
|
+
var UniqueConstraint = class extends SqlNode {
|
|
323
|
+
columns;
|
|
324
|
+
constructor(input) {
|
|
325
|
+
super();
|
|
326
|
+
this.columns = input.columns;
|
|
327
|
+
if (input.name !== void 0) this.name = input.name;
|
|
328
|
+
freezeNode(this);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region ../1-core/contract/src/ir/storage-table.ts
|
|
333
|
+
/**
|
|
334
|
+
* SQL Contract IR node for a single table entry in a namespace's
|
|
335
|
+
* `tables` map.
|
|
336
|
+
*
|
|
337
|
+
* The constructor normalises nested IR-class fields (columns, primary
|
|
338
|
+
* key, uniques, indexes, foreign keys) into the appropriate class
|
|
339
|
+
* instances so downstream walks see a uniform AST regardless of whether
|
|
340
|
+
* the input was a JSON literal or an already-constructed class.
|
|
341
|
+
*
|
|
342
|
+
* The table's `name` is not on the class — tables are keyed by name in
|
|
343
|
+
* the parent namespace's `tables: Record<string, StorageTable>` map.
|
|
344
|
+
*/
|
|
345
|
+
var StorageTable = class StorageTable extends SqlNode {
|
|
346
|
+
columns;
|
|
347
|
+
uniques;
|
|
348
|
+
indexes;
|
|
349
|
+
foreignKeys;
|
|
350
|
+
constructor(input) {
|
|
351
|
+
super();
|
|
352
|
+
this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([name, col]) => [name, col instanceof StorageColumn ? col : new StorageColumn(col)])));
|
|
353
|
+
if (input.primaryKey !== void 0) this.primaryKey = input.primaryKey instanceof PrimaryKey ? input.primaryKey : new PrimaryKey(input.primaryKey);
|
|
354
|
+
this.uniques = Object.freeze(input.uniques.map((u) => u instanceof UniqueConstraint ? u : new UniqueConstraint(u)));
|
|
355
|
+
this.indexes = Object.freeze(input.indexes.map((i) => i instanceof Index ? i : new Index(i)));
|
|
356
|
+
this.foreignKeys = Object.freeze(input.foreignKeys.map((fk) => fk instanceof ForeignKey ? fk : new ForeignKey(fk)));
|
|
357
|
+
if (input.control !== void 0) this.control = input.control;
|
|
358
|
+
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map((cc) => new CheckConstraint(cc)));
|
|
359
|
+
freezeNode(this);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Runtime guard that a namespace `table` entry is really a `StorageTable`.
|
|
363
|
+
* The compiler already types the entry as `StorageTable`, but a
|
|
364
|
+
* freshly-deserialized contract may carry plain JSON at that slot until
|
|
365
|
+
* hydration; this duck-types the structural shape. Accepts `undefined` so
|
|
366
|
+
* optional-chained entry lookups pass straight through.
|
|
367
|
+
*/
|
|
368
|
+
static is(value) {
|
|
369
|
+
if (typeof value !== "object" || value === null) return false;
|
|
370
|
+
return "columns" in value && "uniques" in value && "indexes" in value && "foreignKeys" in value;
|
|
371
|
+
}
|
|
372
|
+
static assert(value, coordinate) {
|
|
373
|
+
if (!StorageTable.is(value)) throw new Error(`Expected a StorageTable at ${coordinate}`);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region ../1-core/contract/src/ir/storage-value-set.ts
|
|
378
|
+
/**
|
|
379
|
+
* SQL Contract IR node for a value-set entry in a namespace's `valueSet`
|
|
380
|
+
* map (`SqlNamespace.entries.valueSet`).
|
|
381
|
+
*
|
|
382
|
+
* A value-set records the ordered set of permitted codec-encoded values for
|
|
383
|
+
* an enum-like column restriction. It does not carry a `codecId` — the
|
|
384
|
+
* column that references it already holds the codec; the value-set holds
|
|
385
|
+
* only the permitted values.
|
|
386
|
+
*
|
|
387
|
+
* The node's `kind` is enumerable (`'valueSet'`) so the JSON envelope
|
|
388
|
+
* carries the discriminator and the serializer hydration walker can
|
|
389
|
+
* dispatch on it. This follows the per-leaf enumerable-kind convention
|
|
390
|
+
* established in the SQL-node comment (future polymorphic dispatch on
|
|
391
|
+
* namespace entries needs the discriminator in JSON).
|
|
392
|
+
*
|
|
393
|
+
* The entry's name is not on the class — value-sets are keyed by name in
|
|
394
|
+
* the parent namespace's `valueSet: Record<string, StorageValueSet>` map.
|
|
395
|
+
*/
|
|
396
|
+
var StorageValueSet = class extends SqlNode {
|
|
397
|
+
kind = "valueSet";
|
|
398
|
+
values;
|
|
399
|
+
constructor(input) {
|
|
400
|
+
super();
|
|
401
|
+
this.values = Object.freeze([...input.values]);
|
|
402
|
+
freezeNode(this);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region ../1-core/contract/src/entity-kinds.ts
|
|
407
|
+
const tableEntityKind = {
|
|
408
|
+
kind: "table",
|
|
409
|
+
schema: StorageTableSchema,
|
|
410
|
+
construct: (input) => new StorageTable(input)
|
|
411
|
+
};
|
|
412
|
+
const valueSetEntityKind = {
|
|
413
|
+
kind: "valueSet",
|
|
414
|
+
schema: StorageValueSetSchema,
|
|
415
|
+
construct: (input) => new StorageValueSet(input)
|
|
416
|
+
};
|
|
417
|
+
/**
|
|
418
|
+
* Assembles the `kind → descriptor` registry for SQL namespaces: the built-in
|
|
419
|
+
* `table` and `valueSet` kinds plus any target `packKinds`. This builds the
|
|
420
|
+
* lookup table — it does not touch contract data. `hydrateNamespaceEntities`
|
|
421
|
+
* later consumes this registry to turn a namespace's raw entries into IR
|
|
422
|
+
* instances, and `createSqlContractSchema` derives validation from the same
|
|
423
|
+
* registry. Throws on a duplicate kind.
|
|
424
|
+
*/
|
|
425
|
+
function composeSqlEntityKinds(packKinds = []) {
|
|
426
|
+
const kinds = new Map([["table", tableEntityKind], ["valueSet", valueSetEntityKind]]);
|
|
427
|
+
for (const descriptor of packKinds) {
|
|
428
|
+
if (kinds.has(descriptor.kind)) throw new Error(`composeSqlEntityKinds: duplicate entity kind "${descriptor.kind}" — each kind may be registered only once`);
|
|
429
|
+
kinds.set(descriptor.kind, descriptor);
|
|
430
|
+
}
|
|
431
|
+
return kinds;
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region ../1-core/contract/src/ir/sql-storage.ts
|
|
435
|
+
/**
|
|
436
|
+
* Abstract SQL family namespace base class. Target concretions (`PostgresSchema`,
|
|
437
|
+
* `SqliteDatabase`, …) extend this — it is never instantiated directly.
|
|
438
|
+
* `entries` is the open ADR 224 dictionary: `entries[entityKind][entityName]`
|
|
439
|
+
* addresses any entity.
|
|
440
|
+
*/
|
|
441
|
+
var SqlNamespaceBase = class extends NamespaceBase {};
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region ../1-core/contract/test/test-support.ts
|
|
444
|
+
/**
|
|
445
|
+
* Minimal concrete `SqlNamespaceBase` for use in `packages/2-sql/**` unit tests.
|
|
446
|
+
*
|
|
447
|
+
* This is a legitimate target concretion — not a materialised family
|
|
448
|
+
* namespace. Production code never constructs one; the target-specific
|
|
449
|
+
* concretions (`PostgresSchema`, `SqliteDatabase`) are used in production.
|
|
450
|
+
*/
|
|
451
|
+
var TestSqlNamespace = class extends SqlNamespaceBase {
|
|
452
|
+
id;
|
|
453
|
+
entries;
|
|
454
|
+
constructor(input) {
|
|
455
|
+
super();
|
|
456
|
+
this.id = input.id;
|
|
457
|
+
const dispatched = hydrateNamespaceEntities(input.entries, composeSqlEntityKinds(), "carry");
|
|
458
|
+
this.entries = Object.freeze(blindCast(dispatched));
|
|
459
|
+
Object.defineProperty(this, "kind", {
|
|
460
|
+
value: "test-sql-namespace",
|
|
461
|
+
writable: false,
|
|
462
|
+
enumerable: false,
|
|
463
|
+
configurable: true
|
|
464
|
+
});
|
|
465
|
+
freezeNode(this);
|
|
466
|
+
}
|
|
467
|
+
get table() {
|
|
468
|
+
return this.entries.table ?? Object.freeze({});
|
|
469
|
+
}
|
|
470
|
+
get valueSet() {
|
|
471
|
+
return this.entries.valueSet;
|
|
472
|
+
}
|
|
473
|
+
qualifyTable(tableName) {
|
|
474
|
+
if (this.id === UNBOUND_NAMESPACE_ID) return `"${tableName}"`;
|
|
475
|
+
return `"${this.id}"."${tableName}"`;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
function createTestSqlNamespace(input) {
|
|
479
|
+
return new TestSqlNamespace(input);
|
|
480
|
+
}
|
|
481
|
+
//#endregion
|
|
14
482
|
//#region test/test-codec.ts
|
|
15
483
|
function defineTestCodec(config) {
|
|
16
484
|
const identity = (v) => v;
|
|
@@ -327,7 +795,7 @@ function createStubAdapter() {
|
|
|
327
795
|
};
|
|
328
796
|
}
|
|
329
797
|
function unboundNamespaceWithTables(tables) {
|
|
330
|
-
return
|
|
798
|
+
return createTestSqlNamespace({
|
|
331
799
|
id: UNBOUND_NAMESPACE_ID,
|
|
332
800
|
entries: { table: tables }
|
|
333
801
|
});
|
|
@@ -344,10 +812,16 @@ function createTestContract(contract) {
|
|
|
344
812
|
storage: rest["storage"] ? new SqlStorage({
|
|
345
813
|
...rest["storage"],
|
|
346
814
|
storageHash: storageHashValue,
|
|
347
|
-
namespaces: rest["storage"].namespaces ?? { __unbound__:
|
|
815
|
+
namespaces: rest["storage"].namespaces ?? { __unbound__: createTestSqlNamespace({
|
|
816
|
+
id: "__unbound__",
|
|
817
|
+
entries: { table: {} }
|
|
818
|
+
}) }
|
|
348
819
|
}) : new SqlStorage({
|
|
349
820
|
storageHash: storageHashValue,
|
|
350
|
-
namespaces: { __unbound__:
|
|
821
|
+
namespaces: { __unbound__: createTestSqlNamespace({
|
|
822
|
+
id: "__unbound__",
|
|
823
|
+
entries: { table: {} }
|
|
824
|
+
}) }
|
|
351
825
|
}),
|
|
352
826
|
domain: rest["domain"] ?? applicationDomainOf({ models: rest["models"] ?? {} }),
|
|
353
827
|
roots: rest["roots"] ?? {},
|
|
@@ -362,6 +836,6 @@ function stubAst() {
|
|
|
362
836
|
return SelectAst.from(TableSource.named("stub"));
|
|
363
837
|
}
|
|
364
838
|
//#endregion
|
|
365
|
-
export { buildTestContractCodecs, collectAsync, createDevDatabase, createStubAdapter, createTestAdapterDescriptor, createTestContext, createTestContract, createTestRuntime, createTestStackInstance, createTestTargetDescriptor, descriptorsFromCodecs, drainPlanExecution, emptySqlTestDomain, executePlanAndCollect, seedTestMarker, setupTestDatabase, stubAst, teardownTestDatabase, unboundNamespaceWithTables, withClient, writeTestContractMarker };
|
|
839
|
+
export { buildDecodeContext, buildTestContractCodecs, collectAsync, createDevDatabase, createStubAdapter, createTestAdapterDescriptor, createTestContext, createTestContract, createTestRuntime, createTestStackInstance, createTestTargetDescriptor, decodeRow, descriptorsFromCodecs, drainPlanExecution, emptySqlTestDomain, executePlanAndCollect, seedTestMarker, setupTestDatabase, stubAst, teardownTestDatabase, unboundNamespaceWithTables, withClient, writeTestContractMarker };
|
|
366
840
|
|
|
367
841
|
//# sourceMappingURL=utils.mjs.map
|