qubu 0.0.0 → 0.3.4
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/canonical-BbnqavJm.mjs +972 -0
- package/dist/codegen.d.mts +107 -0
- package/dist/codegen.mjs +1199 -0
- package/dist/column-CXMxx8Hq.mjs +118 -0
- package/dist/complete-D5Djh-zo.mjs +1788 -0
- package/dist/complete-types-BdFqUfbb.d.mts +371 -0
- package/dist/core.d.mts +33 -0
- package/dist/core.mjs +36 -0
- package/dist/ddl.d.mts +118 -0
- package/dist/ddl.mjs +1120 -0
- package/dist/dialect-b2-Z6uBF.mjs +13 -0
- package/dist/diff.d.mts +2 -0
- package/dist/diff.mjs +883 -0
- package/dist/drizzle-mysql.d.mts +24 -0
- package/dist/drizzle-mysql.mjs +72 -0
- package/dist/drizzle-postgres.d.mts +24 -0
- package/dist/drizzle-postgres.mjs +73 -0
- package/dist/drizzle-sqlite.d.mts +24 -0
- package/dist/drizzle-sqlite.mjs +82 -0
- package/dist/drizzle.d.mts +13 -0
- package/dist/drizzle.mjs +2 -0
- package/dist/errors-BGCoLe_r.mjs +14 -0
- package/dist/errors-Dxv73YJu.mjs +26 -0
- package/dist/explain-CkIK13L_.mjs +98 -0
- package/dist/index-Ds7-mhJi.d.mts +146 -0
- package/dist/index-Dug5HnLB.d.mts +204 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1276 -0
- package/dist/introspection.d.mts +117 -0
- package/dist/introspection.mjs +4341 -0
- package/dist/json-CUZlv4HT.mjs +169 -0
- package/dist/migration.d.mts +215 -0
- package/dist/migration.mjs +1161 -0
- package/dist/mysql-DqkqXB6A.mjs +355 -0
- package/dist/mysql.d.mts +5 -0
- package/dist/mysql.mjs +50 -0
- package/dist/naming-QVCOnSj2.mjs +20 -0
- package/dist/omit-OxV58AwX.mjs +5 -0
- package/dist/on-conflict-BxnxubMb.mjs +143 -0
- package/dist/postgres-DEBBeh52.mjs +235 -0
- package/dist/postgres.d.mts +123 -0
- package/dist/postgres.mjs +52 -0
- package/dist/registry-BufIskVN.mjs +569 -0
- package/dist/relational-DCZrrNia.mjs +77 -0
- package/dist/runtime-BTr-MTlo.mjs +193 -0
- package/dist/schema.d.mts +2 -0
- package/dist/schema.mjs +5 -0
- package/dist/serialize-PF1cfH2P.mjs +556 -0
- package/dist/snapshot-CWPgzxNx.mjs +392 -0
- package/dist/snapshot.d.mts +4 -0
- package/dist/snapshot.mjs +8 -0
- package/dist/source-DUoJVXmL.mjs +68 -0
- package/dist/sqlite-BU6DBxef.mjs +320 -0
- package/dist/sqlite.d.mts +5 -0
- package/dist/sqlite.mjs +48 -0
- package/dist/standard-BTVYKh_F.mjs +12 -0
- package/dist/table-llv9tsZ8.mjs +384 -0
- package/dist/types-4Q076HKo.d.mts +3636 -0
- package/dist/types-BX0mckiU.d.mts +644 -0
- package/dist/types-Cec0xzo4.mjs +116 -0
- package/dist/types-H4vyCw8_.d.mts +45 -0
- package/dist/value-BvilP0oz.mjs +29 -0
- package/dist/vite/ambient.d.ts +449 -0
- package/dist/vite.d.mts +35 -0
- package/dist/vite.mjs +498 -0
- package/docs/config.json +21 -0
- package/docs/dialects-and-execution.md +427 -0
- package/docs/getting-started.md +96 -0
- package/docs/guides/compose-queries.md +225 -0
- package/docs/guides/drizzle.md +130 -0
- package/docs/guides/extensions/dialects.md +40 -0
- package/docs/guides/extensions/overview.md +36 -0
- package/docs/guides/extensions/sources-and-clauses.md +82 -0
- package/docs/guides/extensions/typed-expressions.md +94 -0
- package/docs/guides/extensions/unsafe-syntax.md +27 -0
- package/docs/guides/json.md +65 -0
- package/docs/guides/mutations.md +138 -0
- package/docs/guides/select/conditions.md +110 -0
- package/docs/guides/select/grouping-and-windows.md +82 -0
- package/docs/guides/select/ordering-and-pagination.md +78 -0
- package/docs/guides/select/overview.md +139 -0
- package/docs/guides/sql-templates.md +157 -0
- package/docs/guides/vite-plugin.md +92 -0
- package/docs/index.md +111 -0
- package/docs/query-model/fragments.md +109 -0
- package/docs/query-model/result-shapes.md +125 -0
- package/docs/query-model/source-scope.md +182 -0
- package/docs/reference/introspection-support.md +196 -0
- package/docs/reference/mysql-snapshot.md +55 -0
- package/docs/reference/postgres-snapshot.md +61 -0
- package/docs/reference/sqlite-snapshot.md +53 -0
- package/docs/reference/supported-surface.md +104 -0
- package/docs/schema/catalog-model.md +58 -0
- package/docs/schema/code-generation.md +139 -0
- package/docs/schema/columns-and-writes.md +130 -0
- package/docs/schema/constraints-and-indexes.md +180 -0
- package/docs/schema/ddl-emission.md +75 -0
- package/docs/schema/diff.md +75 -0
- package/docs/schema/introspection.md +214 -0
- package/docs/schema/migration-plans.md +76 -0
- package/docs/schema/snapshots.md +93 -0
- package/docs/schema/storage-and-schema-sql.md +104 -0
- package/docs/schema/tables-and-names.md +106 -0
- package/docs/sql-semantic-types.md +141 -0
- package/docs/troubleshooting.md +151 -0
- package/package.json +132 -10
- package/skills/qubu/SKILL.md +42 -0
- package/skills/qubu/agents/openai.yaml +6 -0
- package/readme.md +0 -1
|
@@ -0,0 +1,1788 @@
|
|
|
1
|
+
import { n as canonicalJson } from "./canonical-BbnqavJm.mjs";
|
|
2
|
+
//#region src/snapshot/complete-types.ts
|
|
3
|
+
/** The stable envelope tag shared by Snapshot v1 and the complete model. */
|
|
4
|
+
const completeSchemaSnapshotFormat = "qubu-schema";
|
|
5
|
+
/** The strict format version for the complete catalog/object model. */
|
|
6
|
+
const completeSchemaSnapshotVersion = 2;
|
|
7
|
+
/** Descriptive alias for consumers that select a numbered snapshot version. */
|
|
8
|
+
const schemaSnapshotV2Version = 2;
|
|
9
|
+
/** Explicit format-version aliases for generated tooling and fixtures. */
|
|
10
|
+
const schemaSnapshotCompleteVersion = 2;
|
|
11
|
+
const schemaSnapshotVersion2 = 2;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/snapshot/complete.ts
|
|
14
|
+
/** Error raised by throwing APIs after collecting strict v2 diagnostics. */
|
|
15
|
+
var CompleteSnapshotValidationError = class extends TypeError {
|
|
16
|
+
name = "CompleteSnapshotValidationError";
|
|
17
|
+
diagnostics;
|
|
18
|
+
issues;
|
|
19
|
+
constructor(diagnostics) {
|
|
20
|
+
const frozen = Object.freeze(diagnostics.map((issue) => Object.freeze({
|
|
21
|
+
...issue,
|
|
22
|
+
path: Object.freeze([...issue.path]),
|
|
23
|
+
relatedPaths: issue.relatedPaths ? Object.freeze(issue.relatedPaths.map((path) => Object.freeze([...path]))) : void 0
|
|
24
|
+
})));
|
|
25
|
+
super(frozen.map((issue) => issue.message).join("\n"));
|
|
26
|
+
this.diagnostics = frozen;
|
|
27
|
+
this.issues = frozen;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/** Decode and strictly validate a complete Snapshot v2 JSON value. */
|
|
31
|
+
function decodeCompleteSchemaSnapshot(input) {
|
|
32
|
+
let value = input;
|
|
33
|
+
if (typeof input === "string") try {
|
|
34
|
+
value = JSON.parse(input);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
diagnostics: Object.freeze([issue("invalid-snapshot", `Snapshot JSON could not be parsed: ${error instanceof Error ? error.message : String(error)}`, [])])
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (!isRecord(value)) return {
|
|
42
|
+
ok: false,
|
|
43
|
+
diagnostics: Object.freeze([issue("invalid-snapshot", "Snapshot root must be an object", [])])
|
|
44
|
+
};
|
|
45
|
+
const diagnostics = [];
|
|
46
|
+
const snapshot = validateCompleteSnapshot(value, diagnostics);
|
|
47
|
+
if (diagnostics.length > 0 || snapshot === void 0) return {
|
|
48
|
+
ok: false,
|
|
49
|
+
diagnostics: Object.freeze(diagnostics)
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
value: deepFreeze(snapshot)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Validate a complete snapshot and throw one structured error on failure. */
|
|
57
|
+
function assertCompleteSchemaSnapshot(input) {
|
|
58
|
+
const result = decodeCompleteSchemaSnapshot(input);
|
|
59
|
+
if (!result.ok) throw new CompleteSnapshotValidationError(result.diagnostics);
|
|
60
|
+
return result.value;
|
|
61
|
+
}
|
|
62
|
+
/** Return a fixed-order, deeply immutable complete snapshot. */
|
|
63
|
+
function canonicalizeCompleteSchemaSnapshot(input) {
|
|
64
|
+
return assertCompleteSchemaSnapshot(input);
|
|
65
|
+
}
|
|
66
|
+
/** Encode a complete snapshot with deterministic property and array order. */
|
|
67
|
+
function encodeCompleteSchemaSnapshot(snapshot) {
|
|
68
|
+
const canonical = assertCompleteSchemaSnapshot(snapshot);
|
|
69
|
+
return canonicalJson(canonical);
|
|
70
|
+
}
|
|
71
|
+
/** Compute the deterministic content digest for a complete Snapshot v2. */
|
|
72
|
+
function completeSchemaSnapshotDigest(snapshot) {
|
|
73
|
+
const source = encodeCompleteSchemaSnapshot(snapshot);
|
|
74
|
+
let hash = 14695981039346656037n;
|
|
75
|
+
const prime = 1099511628211n;
|
|
76
|
+
const mask = 18446744073709551615n;
|
|
77
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
78
|
+
const codePoint = source.codePointAt(index) ?? 0;
|
|
79
|
+
if (codePoint > 65535) index += 1;
|
|
80
|
+
for (const byte of new TextEncoder().encode(String.fromCodePoint(codePoint))) {
|
|
81
|
+
hash ^= BigInt(byte);
|
|
82
|
+
hash = hash * prime & mask;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return `fnv1a64:${hash.toString(16).padStart(16, "0")}`;
|
|
86
|
+
}
|
|
87
|
+
/** Numbered aliases for tooling that keeps v1 and v2 side by side. */
|
|
88
|
+
const decodeSchemaSnapshotV2 = decodeCompleteSchemaSnapshot;
|
|
89
|
+
const assertSchemaSnapshotV2 = assertCompleteSchemaSnapshot;
|
|
90
|
+
const encodeSchemaSnapshotV2 = encodeCompleteSchemaSnapshot;
|
|
91
|
+
const canonicalizeSchemaSnapshotV2 = canonicalizeCompleteSchemaSnapshot;
|
|
92
|
+
const schemaSnapshotV2Digest = completeSchemaSnapshotDigest;
|
|
93
|
+
const decodeCompleteSnapshot = decodeCompleteSchemaSnapshot;
|
|
94
|
+
const assertCompleteSnapshot = assertCompleteSchemaSnapshot;
|
|
95
|
+
const encodeCompleteSnapshot = encodeCompleteSchemaSnapshot;
|
|
96
|
+
const digestCompleteSchemaSnapshot = completeSchemaSnapshotDigest;
|
|
97
|
+
function validateCompleteSnapshot(value, diagnostics) {
|
|
98
|
+
requireKeys(value, [
|
|
99
|
+
"format",
|
|
100
|
+
"version",
|
|
101
|
+
"dialect",
|
|
102
|
+
"namingPolicy",
|
|
103
|
+
"namespace",
|
|
104
|
+
"capabilities",
|
|
105
|
+
"tables",
|
|
106
|
+
"views",
|
|
107
|
+
"sequences",
|
|
108
|
+
"enums",
|
|
109
|
+
"domains",
|
|
110
|
+
"collations",
|
|
111
|
+
"triggers",
|
|
112
|
+
"routines",
|
|
113
|
+
"partitions",
|
|
114
|
+
"policies",
|
|
115
|
+
"extensions",
|
|
116
|
+
"deferredObjects",
|
|
117
|
+
"opaqueObjects",
|
|
118
|
+
"comments",
|
|
119
|
+
"ownership"
|
|
120
|
+
], [], diagnostics);
|
|
121
|
+
if (value.format !== "qubu-schema") diagnostics.push(issue("invalid-snapshot", `Snapshot format must be "${completeSchemaSnapshotFormat}"`, ["format"]));
|
|
122
|
+
if (value.version !== 2) diagnostics.push(issue(typeof value.version === "number" && value.version > 2 ? "future-version" : "invalid-snapshot", `Unsupported complete schema snapshot version: ${String(value.version)}`, ["version"]));
|
|
123
|
+
const dialect = validateDialect(value.dialect, ["dialect"], diagnostics);
|
|
124
|
+
const namingPolicy = validateNamingPolicy(value.namingPolicy, ["namingPolicy"], diagnostics);
|
|
125
|
+
const namespace = validateNamespace(value.namespace, ["namespace"], diagnostics, dialect?.name);
|
|
126
|
+
const capabilities = validateCapabilities(value.capabilities, ["capabilities"], diagnostics);
|
|
127
|
+
const tables = validateObjects(value.tables, ["tables"], diagnostics, validateTable);
|
|
128
|
+
const views = validateObjects(value.views, ["views"], diagnostics, validateView);
|
|
129
|
+
const sequences = validateObjects(value.sequences, ["sequences"], diagnostics, validateSequence);
|
|
130
|
+
const enums = validateObjects(value.enums, ["enums"], diagnostics, validateEnum);
|
|
131
|
+
const domains = validateObjects(value.domains, ["domains"], diagnostics, validateDomain);
|
|
132
|
+
const collations = validateObjects(value.collations, ["collations"], diagnostics, validateCollation);
|
|
133
|
+
const triggers = validateObjects(value.triggers, ["triggers"], diagnostics, validateTrigger);
|
|
134
|
+
const routines = validateObjects(value.routines, ["routines"], diagnostics, validateRoutine);
|
|
135
|
+
const partitions = validateObjects(value.partitions, ["partitions"], diagnostics, validatePartition);
|
|
136
|
+
const policies = validateObjects(value.policies, ["policies"], diagnostics, validatePolicy);
|
|
137
|
+
const extensions = validateObjects(value.extensions, ["extensions"], diagnostics, validateExtensionObject);
|
|
138
|
+
const deferredObjects = validateObjects(value.deferredObjects, ["deferredObjects"], diagnostics, validateDeferredObject);
|
|
139
|
+
const opaqueObjects = validateObjects(value.opaqueObjects, ["opaqueObjects"], diagnostics, validateOpaqueObject);
|
|
140
|
+
const comments = validateObjects(value.comments, ["comments"], diagnostics, validateComment);
|
|
141
|
+
const ownership = validateObjects(value.ownership, ["ownership"], diagnostics, validateOwnership);
|
|
142
|
+
if (dialect === void 0 || namingPolicy === void 0 || namespace === void 0 || capabilities === void 0 || tables === void 0 || views === void 0 || sequences === void 0 || enums === void 0 || domains === void 0 || collations === void 0 || triggers === void 0 || routines === void 0 || partitions === void 0 || policies === void 0 || extensions === void 0 || deferredObjects === void 0 || opaqueObjects === void 0 || comments === void 0 || ownership === void 0) return void 0;
|
|
143
|
+
const snapshot = {
|
|
144
|
+
format: completeSchemaSnapshotFormat,
|
|
145
|
+
version: 2,
|
|
146
|
+
dialect,
|
|
147
|
+
namingPolicy,
|
|
148
|
+
namespace,
|
|
149
|
+
capabilities,
|
|
150
|
+
tables,
|
|
151
|
+
views,
|
|
152
|
+
sequences,
|
|
153
|
+
enums,
|
|
154
|
+
domains,
|
|
155
|
+
collations,
|
|
156
|
+
triggers,
|
|
157
|
+
routines,
|
|
158
|
+
partitions,
|
|
159
|
+
policies,
|
|
160
|
+
extensions,
|
|
161
|
+
deferredObjects,
|
|
162
|
+
opaqueObjects,
|
|
163
|
+
comments,
|
|
164
|
+
ownership
|
|
165
|
+
};
|
|
166
|
+
validateCompleteDialectMetadata(snapshot, diagnostics);
|
|
167
|
+
validateCompleteCrossReferences(snapshot, diagnostics);
|
|
168
|
+
return diagnostics.length === 0 ? snapshot : void 0;
|
|
169
|
+
}
|
|
170
|
+
function validateDialect(value, path, diagnostics) {
|
|
171
|
+
if (!isRecord(value)) {
|
|
172
|
+
diagnostics.push(issue("invalid-snapshot", "Dialect must be an object", path));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
requireKeys(value, ["name", "version"], path, diagnostics);
|
|
176
|
+
const name = stringValue(value.name, [...path, "name"], diagnostics, true);
|
|
177
|
+
const version = integerValue(value.version, [...path, "version"], diagnostics);
|
|
178
|
+
if (version !== void 0 && version < 1) diagnostics.push(issue("invalid-snapshot", "Dialect version must be positive", [...path, "version"]));
|
|
179
|
+
if (version !== void 0 && version > 1) diagnostics.push(issue("future-version", `Unsupported dialect version: ${version}`, [...path, "version"]));
|
|
180
|
+
if (name === void 0 || version === void 0) return void 0;
|
|
181
|
+
return {
|
|
182
|
+
name,
|
|
183
|
+
version
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function validateNamingPolicy(value, path, diagnostics) {
|
|
187
|
+
if (!isRecord(value)) {
|
|
188
|
+
diagnostics.push(issue("invalid-snapshot", "Naming policy must be an object", path));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
requireKeys(value, ["name", "version"], path, diagnostics);
|
|
192
|
+
const name = stringValue(value.name, [...path, "name"], diagnostics, true);
|
|
193
|
+
const version = integerValue(value.version, [...path, "version"], diagnostics);
|
|
194
|
+
if (version !== 1) diagnostics.push(issue(typeof value.version === "number" && value.version > 1 ? "future-version" : "invalid-snapshot", `Unsupported naming-policy version: ${String(value.version)}`, [...path, "version"]));
|
|
195
|
+
return name === void 0 || version === void 0 ? void 0 : {
|
|
196
|
+
name,
|
|
197
|
+
version
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function validateNamespace(value, path, diagnostics, dialect) {
|
|
201
|
+
if (!isRecord(value)) {
|
|
202
|
+
diagnostics.push(issue("invalid-snapshot", "Snapshot namespace must be an object", path));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
requireKeys(value, [
|
|
206
|
+
"kind",
|
|
207
|
+
"name",
|
|
208
|
+
"provenance",
|
|
209
|
+
"physicalReference",
|
|
210
|
+
"dialect"
|
|
211
|
+
], path, diagnostics, [
|
|
212
|
+
"provenance",
|
|
213
|
+
"physicalReference",
|
|
214
|
+
"dialect"
|
|
215
|
+
]);
|
|
216
|
+
const kind = value.kind;
|
|
217
|
+
if (kind !== "postgres-schema" && kind !== "sqlite-database" && kind !== "mysql-database") diagnostics.push(issue("invalid-snapshot", "Snapshot namespace kind is invalid", [...path, "kind"]));
|
|
218
|
+
const name = stringValue(value.name, [...path, "name"], diagnostics, true);
|
|
219
|
+
const metadata = validateObjectMetadata(value, path, dialect, diagnostics);
|
|
220
|
+
return name === void 0 || typeof kind !== "string" ? void 0 : {
|
|
221
|
+
kind,
|
|
222
|
+
name,
|
|
223
|
+
...metadata
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function validateCapabilities(value, path, diagnostics) {
|
|
227
|
+
if (!isRecord(value)) {
|
|
228
|
+
diagnostics.push(issue("invalid-snapshot", "Snapshot capabilities must be an object", path));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const required = [
|
|
232
|
+
"generatedColumns",
|
|
233
|
+
"identityMetadata",
|
|
234
|
+
"checkConstraints",
|
|
235
|
+
"checkConstraintEnforcement",
|
|
236
|
+
"expressionDecompilation",
|
|
237
|
+
"indexExpressions",
|
|
238
|
+
"indexPredicates",
|
|
239
|
+
"indexIncludedColumns",
|
|
240
|
+
"namespaces",
|
|
241
|
+
"visibility"
|
|
242
|
+
];
|
|
243
|
+
requireKeys(value, required, path, diagnostics);
|
|
244
|
+
const result = {};
|
|
245
|
+
for (const key of Object.keys(value).sort()) {
|
|
246
|
+
const child = value[key];
|
|
247
|
+
if (typeof child !== "boolean" && typeof child !== "string") diagnostics.push(issue("invalid-value", "Capability values must be boolean or string", [...path, key]));
|
|
248
|
+
else result[key] = child;
|
|
249
|
+
}
|
|
250
|
+
const enforcement = value.checkConstraintEnforcement;
|
|
251
|
+
if (enforcement !== "enforced" && enforcement !== "metadata-only" && enforcement !== "unknown") diagnostics.push(issue("invalid-snapshot", "Check-constraint enforcement is invalid", [...path, "checkConstraintEnforcement"]));
|
|
252
|
+
const visibility = value.visibility;
|
|
253
|
+
if (visibility !== "complete" && visibility !== "limited" && visibility !== "unknown") diagnostics.push(issue("invalid-snapshot", "Capability visibility is invalid", [...path, "visibility"]));
|
|
254
|
+
for (const key of required) if (typeof value[key] !== "boolean" && key !== "checkConstraintEnforcement" && key !== "visibility") diagnostics.push(issue("invalid-snapshot", "Capability must be boolean", [...path, key]));
|
|
255
|
+
if (diagnostics.some((diagnostic) => diagnostic.path.length === path.length + 1 && diagnostic.path.slice(0, path.length).every((part, i) => part === path[i]))) return void 0;
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
function validateObjects(value, path, diagnostics, validate) {
|
|
259
|
+
if (!Array.isArray(value)) {
|
|
260
|
+
diagnostics.push(issue("invalid-snapshot", "Value must be an array", path));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
validateSortedIds(value, path, diagnostics);
|
|
264
|
+
const result = [];
|
|
265
|
+
for (const [index, item] of value.entries()) {
|
|
266
|
+
const valid = validate(item, [...path, index], diagnostics);
|
|
267
|
+
if (valid !== void 0) result.push(valid);
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
function validateObjectMetadata(value, path, dialect, diagnostics, allowed = []) {
|
|
272
|
+
const provenance = value.provenance === void 0 ? void 0 : validateProvenance(value.provenance, [...path, "provenance"], dialect, diagnostics);
|
|
273
|
+
const extension = value.dialect === void 0 ? void 0 : validateExtension(value.dialect, [...path, "dialect"], dialect, diagnostics);
|
|
274
|
+
const physicalReference = value.physicalReference === void 0 ? void 0 : validatePhysicalReference(value.physicalReference, [...path, "physicalReference"], diagnostics);
|
|
275
|
+
return {
|
|
276
|
+
...provenance === void 0 ? {} : { provenance },
|
|
277
|
+
...physicalReference === void 0 ? {} : { physicalReference },
|
|
278
|
+
...extension === void 0 ? {} : { dialect: extension }
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function validateBase(value, path, kind, dialect, diagnostics, allowed = []) {
|
|
282
|
+
if (!isRecord(value)) {
|
|
283
|
+
diagnostics.push(issue("invalid-snapshot", `${kind} must be an object`, path));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
requireKeys(value, [
|
|
287
|
+
"kind",
|
|
288
|
+
"id",
|
|
289
|
+
"physicalName",
|
|
290
|
+
"provenance",
|
|
291
|
+
"physicalReference",
|
|
292
|
+
"dialect",
|
|
293
|
+
...allowed
|
|
294
|
+
], path, diagnostics, [
|
|
295
|
+
"provenance",
|
|
296
|
+
"physicalReference",
|
|
297
|
+
"dialect",
|
|
298
|
+
...allowed
|
|
299
|
+
]);
|
|
300
|
+
if (value.kind !== kind && !(kind === "view" && value.kind === "materialized-view")) diagnostics.push(issue("invalid-snapshot", `${kind} kind is invalid`, [...path, "kind"]));
|
|
301
|
+
const id = stringValue(value.id, [...path, "id"], diagnostics, true);
|
|
302
|
+
const physicalName = stringValue(value.physicalName, [...path, "physicalName"], diagnostics, true);
|
|
303
|
+
const metadata = validateObjectMetadata(value, path, dialect, diagnostics, allowed);
|
|
304
|
+
return id === void 0 || physicalName === void 0 ? void 0 : {
|
|
305
|
+
id,
|
|
306
|
+
physicalName,
|
|
307
|
+
metadata
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function validateTable(value, path, diagnostics) {
|
|
311
|
+
const base = validateBase(value, path, "table", void 0, diagnostics, [
|
|
312
|
+
"columns",
|
|
313
|
+
"constraints",
|
|
314
|
+
"indexes"
|
|
315
|
+
]);
|
|
316
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
317
|
+
const columns = validateObjects(value.columns, [...path, "columns"], diagnostics, validateColumn);
|
|
318
|
+
const constraints = validateObjects(value.constraints, [...path, "constraints"], diagnostics, validateConstraint);
|
|
319
|
+
const indexes = validateObjects(value.indexes, [...path, "indexes"], diagnostics, validateIndex);
|
|
320
|
+
if (columns === void 0 || constraints === void 0 || indexes === void 0) return void 0;
|
|
321
|
+
return {
|
|
322
|
+
kind: "table",
|
|
323
|
+
id: base.id,
|
|
324
|
+
physicalName: base.physicalName,
|
|
325
|
+
columns,
|
|
326
|
+
constraints,
|
|
327
|
+
indexes,
|
|
328
|
+
...base.metadata
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function validateColumn(value, path, diagnostics) {
|
|
332
|
+
const base = validateBase(value, path, "column", void 0, diagnostics, [
|
|
333
|
+
"ordinalPosition",
|
|
334
|
+
"nullable",
|
|
335
|
+
"hasDefault",
|
|
336
|
+
"generated",
|
|
337
|
+
"storage",
|
|
338
|
+
"default",
|
|
339
|
+
"generatedColumn",
|
|
340
|
+
"identity",
|
|
341
|
+
"onUpdate"
|
|
342
|
+
]);
|
|
343
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
344
|
+
const ordinalPosition = integerValue(value.ordinalPosition, [...path, "ordinalPosition"], diagnostics);
|
|
345
|
+
const nullable = booleanValue(value.nullable, [...path, "nullable"], diagnostics);
|
|
346
|
+
const hasDefault = booleanValue(value.hasDefault, [...path, "hasDefault"], diagnostics);
|
|
347
|
+
const generated = booleanValue(value.generated, [...path, "generated"], diagnostics);
|
|
348
|
+
const storage = value.storage === void 0 ? void 0 : validateStorage(value.storage, [...path, "storage"], diagnostics);
|
|
349
|
+
const defaultValue = value.default === void 0 ? void 0 : validateDefault(value.default, [...path, "default"], diagnostics);
|
|
350
|
+
const generatedColumn = value.generatedColumn === void 0 ? void 0 : validateGenerated(value.generatedColumn, [...path, "generatedColumn"], diagnostics);
|
|
351
|
+
const identity = value.identity === void 0 ? void 0 : validateIdentity(value.identity, [...path, "identity"], diagnostics);
|
|
352
|
+
const onUpdate = value.onUpdate === void 0 ? void 0 : validateExpression(value.onUpdate, [...path, "onUpdate"], diagnostics);
|
|
353
|
+
if (ordinalPosition === void 0 || nullable === void 0 || hasDefault === void 0 || generated === void 0) return void 0;
|
|
354
|
+
return {
|
|
355
|
+
kind: "column",
|
|
356
|
+
id: base.id,
|
|
357
|
+
physicalName: base.physicalName,
|
|
358
|
+
ordinalPosition,
|
|
359
|
+
nullable,
|
|
360
|
+
hasDefault,
|
|
361
|
+
generated,
|
|
362
|
+
...storage === void 0 ? {} : { storage },
|
|
363
|
+
...defaultValue === void 0 ? {} : { default: defaultValue },
|
|
364
|
+
...generatedColumn === void 0 ? {} : { generatedColumn },
|
|
365
|
+
...identity === void 0 ? {} : { identity },
|
|
366
|
+
...onUpdate === void 0 ? {} : { onUpdate },
|
|
367
|
+
...base.metadata
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function validateConstraint(value, path, diagnostics) {
|
|
371
|
+
if (!isRecord(value)) {
|
|
372
|
+
diagnostics.push(issue("invalid-snapshot", "Constraint must be an object", path));
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const kind = value.kind;
|
|
376
|
+
const base = validateBase(value, path, String(kind), void 0, diagnostics, kind === "foreign-key" ? [
|
|
377
|
+
"columns",
|
|
378
|
+
"target",
|
|
379
|
+
"onUpdate",
|
|
380
|
+
"onDelete",
|
|
381
|
+
"match",
|
|
382
|
+
"deferrable",
|
|
383
|
+
"initially",
|
|
384
|
+
"validated"
|
|
385
|
+
] : kind === "check" ? [
|
|
386
|
+
"expression",
|
|
387
|
+
"deferrable",
|
|
388
|
+
"initially",
|
|
389
|
+
"validated"
|
|
390
|
+
] : [
|
|
391
|
+
"columns",
|
|
392
|
+
"nulls",
|
|
393
|
+
"backingIndex",
|
|
394
|
+
"deferrable",
|
|
395
|
+
"initially",
|
|
396
|
+
"validated"
|
|
397
|
+
]);
|
|
398
|
+
if (base === void 0) return void 0;
|
|
399
|
+
if (kind === "check") {
|
|
400
|
+
const expression = validateExpression(value.expression, [...path, "expression"], diagnostics);
|
|
401
|
+
const timing = validateTiming(value, path, diagnostics);
|
|
402
|
+
const validated = optionalBoolean(value.validated, [...path, "validated"], diagnostics);
|
|
403
|
+
if (expression === void 0) return void 0;
|
|
404
|
+
return {
|
|
405
|
+
kind: "check",
|
|
406
|
+
id: base.id,
|
|
407
|
+
physicalName: base.physicalName,
|
|
408
|
+
expression,
|
|
409
|
+
...timing,
|
|
410
|
+
...validated === void 0 ? {} : { validated },
|
|
411
|
+
...base.metadata
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
if (kind === "foreign-key") {
|
|
415
|
+
const columns = validateIds(value.columns, [...path, "columns"], diagnostics);
|
|
416
|
+
const target = validateForeignKeyTarget(value.target, [...path, "target"], diagnostics);
|
|
417
|
+
const onUpdate = validateAction(value.onUpdate, [...path, "onUpdate"], diagnostics);
|
|
418
|
+
const onDelete = validateAction(value.onDelete, [...path, "onDelete"], diagnostics);
|
|
419
|
+
const match = validateMatch(value.match, [...path, "match"], diagnostics);
|
|
420
|
+
const timing = validateTiming(value, path, diagnostics);
|
|
421
|
+
const validated = optionalBoolean(value.validated, [...path, "validated"], diagnostics);
|
|
422
|
+
if (columns === void 0 || target === void 0) return void 0;
|
|
423
|
+
return {
|
|
424
|
+
kind: "foreign-key",
|
|
425
|
+
id: base.id,
|
|
426
|
+
physicalName: base.physicalName,
|
|
427
|
+
columns,
|
|
428
|
+
target,
|
|
429
|
+
...onUpdate === void 0 ? {} : { onUpdate },
|
|
430
|
+
...onDelete === void 0 ? {} : { onDelete },
|
|
431
|
+
...match === void 0 ? {} : { match },
|
|
432
|
+
...timing,
|
|
433
|
+
...validated === void 0 ? {} : { validated },
|
|
434
|
+
...base.metadata
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
if (kind !== "primary-key" && kind !== "unique" && kind !== "unique-constraint") {
|
|
438
|
+
diagnostics.push(issue("invalid-snapshot", "Constraint kind is invalid", [...path, "kind"]));
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const columns = validateIds(value.columns, [...path, "columns"], diagnostics);
|
|
442
|
+
const nulls = value.nulls === void 0 ? void 0 : validateNulls(value.nulls, [...path, "nulls"], diagnostics);
|
|
443
|
+
const backingIndex = value.backingIndex === void 0 ? void 0 : validateObjectReference(value.backingIndex, [...path, "backingIndex"], diagnostics);
|
|
444
|
+
const timing = validateTiming(value, path, diagnostics);
|
|
445
|
+
const validated = optionalBoolean(value.validated, [...path, "validated"], diagnostics);
|
|
446
|
+
if (columns === void 0) return void 0;
|
|
447
|
+
if (kind === "unique-constraint" && nulls === void 0) {
|
|
448
|
+
diagnostics.push(issue("invalid-snapshot", "Unique constraints require nulls semantics", [...path, "nulls"]));
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
kind,
|
|
453
|
+
id: base.id,
|
|
454
|
+
physicalName: base.physicalName,
|
|
455
|
+
columns,
|
|
456
|
+
...nulls === void 0 ? {} : { nulls },
|
|
457
|
+
...backingIndex === void 0 ? {} : { backingIndex },
|
|
458
|
+
...timing,
|
|
459
|
+
...validated === void 0 ? {} : { validated },
|
|
460
|
+
...base.metadata
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function validateIndex(value, path, diagnostics) {
|
|
464
|
+
const base = validateBase(value, path, "index", void 0, diagnostics, [
|
|
465
|
+
"terms",
|
|
466
|
+
"unique",
|
|
467
|
+
"candidateKey",
|
|
468
|
+
"predicate",
|
|
469
|
+
"includedColumns",
|
|
470
|
+
"backingConstraint",
|
|
471
|
+
"method"
|
|
472
|
+
]);
|
|
473
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
474
|
+
const terms = validateArray(value.terms, [...path, "terms"], diagnostics, validateIndexTerm);
|
|
475
|
+
if (terms !== void 0) validateSortedPositions(terms, [...path, "terms"], diagnostics);
|
|
476
|
+
const unique = booleanValue(value.unique, [...path, "unique"], diagnostics);
|
|
477
|
+
const candidateKey = booleanValue(value.candidateKey, [...path, "candidateKey"], diagnostics);
|
|
478
|
+
const predicate = value.predicate === void 0 ? void 0 : validateExpression(value.predicate, [...path, "predicate"], diagnostics);
|
|
479
|
+
const includedColumns = value.includedColumns === void 0 ? void 0 : validateIds(value.includedColumns, [...path, "includedColumns"], diagnostics, false);
|
|
480
|
+
const backingConstraint = value.backingConstraint === void 0 ? void 0 : validateObjectReference(value.backingConstraint, [...path, "backingConstraint"], diagnostics);
|
|
481
|
+
const method = value.method === void 0 ? void 0 : stringValue(value.method, [...path, "method"], diagnostics, true);
|
|
482
|
+
if (terms === void 0 || unique === void 0 || candidateKey === void 0) return void 0;
|
|
483
|
+
return {
|
|
484
|
+
kind: "index",
|
|
485
|
+
id: base.id,
|
|
486
|
+
physicalName: base.physicalName,
|
|
487
|
+
terms,
|
|
488
|
+
unique,
|
|
489
|
+
candidateKey,
|
|
490
|
+
...predicate === void 0 ? {} : { predicate },
|
|
491
|
+
...includedColumns === void 0 ? {} : { includedColumns },
|
|
492
|
+
...backingConstraint === void 0 ? {} : { backingConstraint },
|
|
493
|
+
...method === void 0 ? {} : { method },
|
|
494
|
+
...base.metadata
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function validateIndexTerm(value, path, diagnostics) {
|
|
498
|
+
if (!isRecord(value)) {
|
|
499
|
+
diagnostics.push(issue("invalid-snapshot", "Index term must be an object", path));
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const kind = value.kind;
|
|
503
|
+
requireKeys(value, [
|
|
504
|
+
"kind",
|
|
505
|
+
"position",
|
|
506
|
+
"direction",
|
|
507
|
+
"nulls",
|
|
508
|
+
"operatorClass",
|
|
509
|
+
...kind === "column" ? ["column", "prefixLength"] : ["expression"]
|
|
510
|
+
], path, diagnostics, [
|
|
511
|
+
"direction",
|
|
512
|
+
"nulls",
|
|
513
|
+
"operatorClass",
|
|
514
|
+
"prefixLength"
|
|
515
|
+
]);
|
|
516
|
+
const position = integerValue(value.position, [...path, "position"], diagnostics);
|
|
517
|
+
const direction = validateDirection(value.direction, [...path, "direction"], diagnostics);
|
|
518
|
+
const nulls = validateIndexNulls(value.nulls, [...path, "nulls"], diagnostics);
|
|
519
|
+
const operatorClass = value.operatorClass === void 0 ? void 0 : stringValue(value.operatorClass, [...path, "operatorClass"], diagnostics, true);
|
|
520
|
+
if (kind === "column") {
|
|
521
|
+
const column = stringValue(value.column, [...path, "column"], diagnostics, true);
|
|
522
|
+
const prefixLength = value.prefixLength === void 0 ? void 0 : validateValueFact(value.prefixLength, [...path, "prefixLength"], diagnostics);
|
|
523
|
+
if (column === void 0 || position === void 0) return void 0;
|
|
524
|
+
return {
|
|
525
|
+
kind: "column",
|
|
526
|
+
column,
|
|
527
|
+
position,
|
|
528
|
+
...direction === void 0 ? {} : { direction },
|
|
529
|
+
...nulls === void 0 ? {} : { nulls },
|
|
530
|
+
...prefixLength === void 0 ? {} : { prefixLength },
|
|
531
|
+
...operatorClass === void 0 ? {} : { operatorClass }
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (kind === "expression") {
|
|
535
|
+
const expression = validateExpression(value.expression, [...path, "expression"], diagnostics);
|
|
536
|
+
if (expression === void 0 || position === void 0) return void 0;
|
|
537
|
+
return {
|
|
538
|
+
kind: "expression",
|
|
539
|
+
expression,
|
|
540
|
+
position,
|
|
541
|
+
...direction === void 0 ? {} : { direction },
|
|
542
|
+
...nulls === void 0 ? {} : { nulls },
|
|
543
|
+
...operatorClass === void 0 ? {} : { operatorClass }
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
diagnostics.push(issue("invalid-snapshot", "Index term kind is invalid", [...path, "kind"]));
|
|
547
|
+
}
|
|
548
|
+
function validateView(value, path, diagnostics) {
|
|
549
|
+
const base = validateBase(value, path, "view", void 0, diagnostics, [
|
|
550
|
+
"columns",
|
|
551
|
+
"definition",
|
|
552
|
+
"dependencies",
|
|
553
|
+
"checkOption",
|
|
554
|
+
"securityBarrier",
|
|
555
|
+
"securityInvoker"
|
|
556
|
+
]);
|
|
557
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
558
|
+
const columns = validateObjects(value.columns, [...path, "columns"], diagnostics, validateColumn);
|
|
559
|
+
const definition = validateExpression(value.definition, [...path, "definition"], diagnostics);
|
|
560
|
+
const dependencies = value.dependencies === void 0 ? void 0 : validateReferences(value.dependencies, [...path, "dependencies"], diagnostics);
|
|
561
|
+
const checkOption = validateCheckOption(value.checkOption, [...path, "checkOption"], diagnostics);
|
|
562
|
+
const securityBarrier = optionalBoolean(value.securityBarrier, [...path, "securityBarrier"], diagnostics);
|
|
563
|
+
const securityInvoker = optionalBoolean(value.securityInvoker, [...path, "securityInvoker"], diagnostics);
|
|
564
|
+
if (columns === void 0 || definition === void 0) return void 0;
|
|
565
|
+
return {
|
|
566
|
+
kind: value.kind,
|
|
567
|
+
id: base.id,
|
|
568
|
+
physicalName: base.physicalName,
|
|
569
|
+
columns,
|
|
570
|
+
definition,
|
|
571
|
+
...dependencies === void 0 ? {} : { dependencies },
|
|
572
|
+
...checkOption === void 0 ? {} : { checkOption },
|
|
573
|
+
...securityBarrier === void 0 ? {} : { securityBarrier },
|
|
574
|
+
...securityInvoker === void 0 ? {} : { securityInvoker },
|
|
575
|
+
...base.metadata
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function validateSequence(value, path, diagnostics) {
|
|
579
|
+
const base = validateBase(value, path, "sequence", void 0, diagnostics, [
|
|
580
|
+
"storage",
|
|
581
|
+
"start",
|
|
582
|
+
"increment",
|
|
583
|
+
"minimum",
|
|
584
|
+
"maximum",
|
|
585
|
+
"cache",
|
|
586
|
+
"cycle",
|
|
587
|
+
"ownedBy",
|
|
588
|
+
"identity"
|
|
589
|
+
]);
|
|
590
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
591
|
+
const storage = value.storage === void 0 ? void 0 : validateStorage(value.storage, [...path, "storage"], diagnostics);
|
|
592
|
+
const start = value.start === void 0 ? void 0 : validateValueFact(value.start, [...path, "start"], diagnostics);
|
|
593
|
+
const increment = value.increment === void 0 ? void 0 : validateValueFact(value.increment, [...path, "increment"], diagnostics);
|
|
594
|
+
const minimum = value.minimum === void 0 ? void 0 : validateValueFact(value.minimum, [...path, "minimum"], diagnostics);
|
|
595
|
+
const maximum = value.maximum === void 0 ? void 0 : validateValueFact(value.maximum, [...path, "maximum"], diagnostics);
|
|
596
|
+
const cache = value.cache === void 0 ? void 0 : validateValueFact(value.cache, [...path, "cache"], diagnostics);
|
|
597
|
+
const cycle = optionalBoolean(value.cycle, [...path, "cycle"], diagnostics);
|
|
598
|
+
const ownedBy = value.ownedBy === void 0 ? void 0 : validateObjectReference(value.ownedBy, [...path, "ownedBy"], diagnostics);
|
|
599
|
+
const identity = value.identity === void 0 ? void 0 : validateIdentity(value.identity, [...path, "identity"], diagnostics);
|
|
600
|
+
return {
|
|
601
|
+
kind: "sequence",
|
|
602
|
+
id: base.id,
|
|
603
|
+
physicalName: base.physicalName,
|
|
604
|
+
...storage === void 0 ? {} : { storage },
|
|
605
|
+
...start === void 0 ? {} : { start },
|
|
606
|
+
...increment === void 0 ? {} : { increment },
|
|
607
|
+
...minimum === void 0 ? {} : { minimum },
|
|
608
|
+
...maximum === void 0 ? {} : { maximum },
|
|
609
|
+
...cache === void 0 ? {} : { cache },
|
|
610
|
+
...cycle === void 0 ? {} : { cycle },
|
|
611
|
+
...ownedBy === void 0 ? {} : { ownedBy },
|
|
612
|
+
...identity === void 0 ? {} : { identity },
|
|
613
|
+
...base.metadata
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
function validateEnum(value, path, diagnostics) {
|
|
617
|
+
const base = validateBase(value, path, "enum", void 0, diagnostics, ["values"]);
|
|
618
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
619
|
+
const values = validateArray(value.values, [...path, "values"], diagnostics, validateEnumValue);
|
|
620
|
+
if (values === void 0) return void 0;
|
|
621
|
+
let previous = -1;
|
|
622
|
+
for (const [index, item] of values.entries()) {
|
|
623
|
+
if (item.ordinalPosition <= previous) diagnostics.push(issue("non-canonical", "Enum labels must be sorted by ordinal position", [
|
|
624
|
+
...path,
|
|
625
|
+
"values",
|
|
626
|
+
index,
|
|
627
|
+
"ordinalPosition"
|
|
628
|
+
]));
|
|
629
|
+
previous = item.ordinalPosition;
|
|
630
|
+
}
|
|
631
|
+
return {
|
|
632
|
+
kind: "enum",
|
|
633
|
+
id: base.id,
|
|
634
|
+
physicalName: base.physicalName,
|
|
635
|
+
values,
|
|
636
|
+
...base.metadata
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
function validateEnumValue(value, path, diagnostics) {
|
|
640
|
+
if (!isRecord(value)) {
|
|
641
|
+
diagnostics.push(issue("invalid-snapshot", "Enum value must be an object", path));
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
requireKeys(value, [
|
|
645
|
+
"value",
|
|
646
|
+
"ordinalPosition",
|
|
647
|
+
"provenance"
|
|
648
|
+
], path, diagnostics, ["provenance"]);
|
|
649
|
+
const label = stringValue(value.value, [...path, "value"], diagnostics);
|
|
650
|
+
const ordinalPosition = integerValue(value.ordinalPosition, [...path, "ordinalPosition"], diagnostics);
|
|
651
|
+
const provenance = value.provenance === void 0 ? void 0 : validateProvenance(value.provenance, [...path, "provenance"], void 0, diagnostics);
|
|
652
|
+
return label === void 0 || ordinalPosition === void 0 ? void 0 : {
|
|
653
|
+
value: label,
|
|
654
|
+
ordinalPosition,
|
|
655
|
+
...provenance === void 0 ? {} : { provenance }
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function validateDomain(value, path, diagnostics) {
|
|
659
|
+
const base = validateBase(value, path, "domain", void 0, diagnostics, [
|
|
660
|
+
"storage",
|
|
661
|
+
"nullable",
|
|
662
|
+
"default",
|
|
663
|
+
"constraints"
|
|
664
|
+
]);
|
|
665
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
666
|
+
const storage = validateStorage(value.storage, [...path, "storage"], diagnostics);
|
|
667
|
+
const nullable = optionalBoolean(value.nullable, [...path, "nullable"], diagnostics);
|
|
668
|
+
const defaultValue = value.default === void 0 ? void 0 : validateValueFact(value.default, [...path, "default"], diagnostics);
|
|
669
|
+
const constraints = value.constraints === void 0 ? void 0 : validateArray(value.constraints, [...path, "constraints"], diagnostics, validateCheckConstraint);
|
|
670
|
+
if (storage === void 0) return void 0;
|
|
671
|
+
return {
|
|
672
|
+
kind: "domain",
|
|
673
|
+
id: base.id,
|
|
674
|
+
physicalName: base.physicalName,
|
|
675
|
+
storage,
|
|
676
|
+
...nullable === void 0 ? {} : { nullable },
|
|
677
|
+
...defaultValue === void 0 ? {} : { default: defaultValue },
|
|
678
|
+
...constraints === void 0 ? {} : { constraints },
|
|
679
|
+
...base.metadata
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function validateCheckConstraint(value, path, diagnostics) {
|
|
683
|
+
const constraint = validateConstraint(value, path, diagnostics);
|
|
684
|
+
if (constraint?.kind !== "check") {
|
|
685
|
+
diagnostics.push(issue("invalid-snapshot", "Domain constraints must be check constraints", path));
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
return constraint;
|
|
689
|
+
}
|
|
690
|
+
function validateCollation(value, path, diagnostics) {
|
|
691
|
+
const base = validateBase(value, path, "collation", void 0, diagnostics, [
|
|
692
|
+
"provider",
|
|
693
|
+
"locale",
|
|
694
|
+
"deterministic",
|
|
695
|
+
"version"
|
|
696
|
+
]);
|
|
697
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
698
|
+
const provider = value.provider === void 0 ? void 0 : stringValue(value.provider, [...path, "provider"], diagnostics, true);
|
|
699
|
+
const locale = value.locale === void 0 ? void 0 : stringValue(value.locale, [...path, "locale"], diagnostics);
|
|
700
|
+
const deterministic = optionalBoolean(value.deterministic, [...path, "deterministic"], diagnostics);
|
|
701
|
+
const version = value.version === void 0 ? void 0 : stringValue(value.version, [...path, "version"], diagnostics);
|
|
702
|
+
return {
|
|
703
|
+
kind: "collation",
|
|
704
|
+
id: base.id,
|
|
705
|
+
physicalName: base.physicalName,
|
|
706
|
+
...provider === void 0 ? {} : { provider },
|
|
707
|
+
...locale === void 0 ? {} : { locale },
|
|
708
|
+
...deterministic === void 0 ? {} : { deterministic },
|
|
709
|
+
...version === void 0 ? {} : { version },
|
|
710
|
+
...base.metadata
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
function validateTrigger(value, path, diagnostics) {
|
|
714
|
+
const base = validateBase(value, path, "trigger", void 0, diagnostics, [
|
|
715
|
+
"table",
|
|
716
|
+
"timing",
|
|
717
|
+
"events",
|
|
718
|
+
"orientation",
|
|
719
|
+
"condition",
|
|
720
|
+
"body",
|
|
721
|
+
"enabled"
|
|
722
|
+
]);
|
|
723
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
724
|
+
const table = validateObjectReference(value.table, [...path, "table"], diagnostics);
|
|
725
|
+
const timing = validateTimingKind(value.timing, [...path, "timing"], diagnostics);
|
|
726
|
+
const events = validateEvents(value.events, [...path, "events"], diagnostics);
|
|
727
|
+
const orientation = validateOrientation(value.orientation, [...path, "orientation"], diagnostics);
|
|
728
|
+
const condition = value.condition === void 0 ? void 0 : validateExpression(value.condition, [...path, "condition"], diagnostics);
|
|
729
|
+
const body = validateExpression(value.body, [...path, "body"], diagnostics);
|
|
730
|
+
const enabled = optionalBoolean(value.enabled, [...path, "enabled"], diagnostics);
|
|
731
|
+
if (table === void 0 || timing === void 0 || events === void 0 || body === void 0) return void 0;
|
|
732
|
+
return {
|
|
733
|
+
kind: "trigger",
|
|
734
|
+
id: base.id,
|
|
735
|
+
physicalName: base.physicalName,
|
|
736
|
+
table,
|
|
737
|
+
timing,
|
|
738
|
+
events,
|
|
739
|
+
...orientation === void 0 ? {} : { orientation },
|
|
740
|
+
...condition === void 0 ? {} : { condition },
|
|
741
|
+
body,
|
|
742
|
+
...enabled === void 0 ? {} : { enabled },
|
|
743
|
+
...base.metadata
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function validateRoutine(value, path, diagnostics) {
|
|
747
|
+
const base = validateBase(value, path, "routine", void 0, diagnostics, [
|
|
748
|
+
"routineKind",
|
|
749
|
+
"parameters",
|
|
750
|
+
"returnType",
|
|
751
|
+
"language",
|
|
752
|
+
"body",
|
|
753
|
+
"volatility",
|
|
754
|
+
"parallel",
|
|
755
|
+
"security",
|
|
756
|
+
"dependencies"
|
|
757
|
+
]);
|
|
758
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
759
|
+
const routineKind = validateRoutineKind(value.routineKind, [...path, "routineKind"], diagnostics);
|
|
760
|
+
const parameters = validateArray(value.parameters, [...path, "parameters"], diagnostics, validateRoutineParameter);
|
|
761
|
+
if (parameters !== void 0) validateSortedPositions(parameters, [...path, "parameters"], diagnostics);
|
|
762
|
+
const returnType = value.returnType === void 0 ? void 0 : validateStorage(value.returnType, [...path, "returnType"], diagnostics);
|
|
763
|
+
const language = value.language === void 0 ? void 0 : stringValue(value.language, [...path, "language"], diagnostics, true);
|
|
764
|
+
const body = value.body === void 0 ? void 0 : validateExpression(value.body, [...path, "body"], diagnostics);
|
|
765
|
+
const volatility = validateChoice(value.volatility, [
|
|
766
|
+
"immutable",
|
|
767
|
+
"stable",
|
|
768
|
+
"volatile",
|
|
769
|
+
"unknown"
|
|
770
|
+
], [...path, "volatility"], diagnostics);
|
|
771
|
+
const parallel = validateChoice(value.parallel, [
|
|
772
|
+
"safe",
|
|
773
|
+
"restricted",
|
|
774
|
+
"unsafe",
|
|
775
|
+
"unknown"
|
|
776
|
+
], [...path, "parallel"], diagnostics);
|
|
777
|
+
const security = validateChoice(value.security, [
|
|
778
|
+
"invoker",
|
|
779
|
+
"definer",
|
|
780
|
+
"unknown"
|
|
781
|
+
], [...path, "security"], diagnostics);
|
|
782
|
+
const dependencies = value.dependencies === void 0 ? void 0 : validateReferences(value.dependencies, [...path, "dependencies"], diagnostics);
|
|
783
|
+
if (routineKind === void 0 || parameters === void 0) return void 0;
|
|
784
|
+
return {
|
|
785
|
+
kind: "routine",
|
|
786
|
+
id: base.id,
|
|
787
|
+
physicalName: base.physicalName,
|
|
788
|
+
routineKind,
|
|
789
|
+
parameters,
|
|
790
|
+
...returnType === void 0 ? {} : { returnType },
|
|
791
|
+
...language === void 0 ? {} : { language },
|
|
792
|
+
...body === void 0 ? {} : { body },
|
|
793
|
+
...volatility === void 0 ? {} : { volatility },
|
|
794
|
+
...parallel === void 0 ? {} : { parallel },
|
|
795
|
+
...security === void 0 ? {} : { security },
|
|
796
|
+
...dependencies === void 0 ? {} : { dependencies },
|
|
797
|
+
...base.metadata
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function validateRoutineParameter(value, path, diagnostics) {
|
|
801
|
+
if (!isRecord(value)) {
|
|
802
|
+
diagnostics.push(issue("invalid-snapshot", "Routine parameter must be an object", path));
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
requireKeys(value, [
|
|
806
|
+
"name",
|
|
807
|
+
"mode",
|
|
808
|
+
"storage",
|
|
809
|
+
"default",
|
|
810
|
+
"ordinalPosition"
|
|
811
|
+
], path, diagnostics, [
|
|
812
|
+
"name",
|
|
813
|
+
"mode",
|
|
814
|
+
"default"
|
|
815
|
+
]);
|
|
816
|
+
const name = value.name === void 0 ? void 0 : stringValue(value.name, [...path, "name"], diagnostics);
|
|
817
|
+
const mode = validateChoice(value.mode, [
|
|
818
|
+
"in",
|
|
819
|
+
"out",
|
|
820
|
+
"inout",
|
|
821
|
+
"variadic",
|
|
822
|
+
"table"
|
|
823
|
+
], [...path, "mode"], diagnostics);
|
|
824
|
+
const storage = validateStorage(value.storage, [...path, "storage"], diagnostics);
|
|
825
|
+
const defaultValue = value.default === void 0 ? void 0 : validateValueFact(value.default, [...path, "default"], diagnostics);
|
|
826
|
+
const ordinalPosition = integerValue(value.ordinalPosition, [...path, "ordinalPosition"], diagnostics);
|
|
827
|
+
return storage === void 0 || ordinalPosition === void 0 ? void 0 : {
|
|
828
|
+
...name === void 0 ? {} : { name },
|
|
829
|
+
...mode === void 0 ? {} : { mode },
|
|
830
|
+
storage,
|
|
831
|
+
...defaultValue === void 0 ? {} : { default: defaultValue },
|
|
832
|
+
ordinalPosition
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
function validatePartition(value, path, diagnostics) {
|
|
836
|
+
const base = validateBase(value, path, "partition", void 0, diagnostics, [
|
|
837
|
+
"parent",
|
|
838
|
+
"strategy",
|
|
839
|
+
"keyColumns",
|
|
840
|
+
"bound",
|
|
841
|
+
"default"
|
|
842
|
+
]);
|
|
843
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
844
|
+
const parent = validateObjectReference(value.parent, [...path, "parent"], diagnostics);
|
|
845
|
+
const strategy = validateChoice(value.strategy, [
|
|
846
|
+
"range",
|
|
847
|
+
"list",
|
|
848
|
+
"hash",
|
|
849
|
+
"reference",
|
|
850
|
+
"unknown"
|
|
851
|
+
], [...path, "strategy"], diagnostics);
|
|
852
|
+
const keyColumns = value.keyColumns === void 0 ? void 0 : validateIds(value.keyColumns, [...path, "keyColumns"], diagnostics, false);
|
|
853
|
+
const bound = value.bound === void 0 ? void 0 : validateExpression(value.bound, [...path, "bound"], diagnostics);
|
|
854
|
+
const defaultValue = optionalBoolean(value.default, [...path, "default"], diagnostics);
|
|
855
|
+
if (parent === void 0 || strategy === void 0) return void 0;
|
|
856
|
+
return {
|
|
857
|
+
kind: "partition",
|
|
858
|
+
id: base.id,
|
|
859
|
+
physicalName: base.physicalName,
|
|
860
|
+
parent,
|
|
861
|
+
strategy,
|
|
862
|
+
...keyColumns === void 0 ? {} : { keyColumns },
|
|
863
|
+
...bound === void 0 ? {} : { bound },
|
|
864
|
+
...defaultValue === void 0 ? {} : { default: defaultValue },
|
|
865
|
+
...base.metadata
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
function validatePolicy(value, path, diagnostics) {
|
|
869
|
+
const base = validateBase(value, path, "policy", void 0, diagnostics, [
|
|
870
|
+
"table",
|
|
871
|
+
"command",
|
|
872
|
+
"roles",
|
|
873
|
+
"permissive",
|
|
874
|
+
"using",
|
|
875
|
+
"check"
|
|
876
|
+
]);
|
|
877
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
878
|
+
const table = validateObjectReference(value.table, [...path, "table"], diagnostics);
|
|
879
|
+
const command = validateChoice(value.command, [
|
|
880
|
+
"all",
|
|
881
|
+
"select",
|
|
882
|
+
"insert",
|
|
883
|
+
"update",
|
|
884
|
+
"delete",
|
|
885
|
+
"unknown"
|
|
886
|
+
], [...path, "command"], diagnostics);
|
|
887
|
+
const roles = value.roles === void 0 ? void 0 : validateStrings(value.roles, [...path, "roles"], diagnostics, false);
|
|
888
|
+
const permissive = optionalBoolean(value.permissive, [...path, "permissive"], diagnostics);
|
|
889
|
+
const using = value.using === void 0 ? void 0 : validateExpression(value.using, [...path, "using"], diagnostics);
|
|
890
|
+
const check = value.check === void 0 ? void 0 : validateExpression(value.check, [...path, "check"], diagnostics);
|
|
891
|
+
if (table === void 0 || command === void 0) return void 0;
|
|
892
|
+
return {
|
|
893
|
+
kind: "policy",
|
|
894
|
+
id: base.id,
|
|
895
|
+
physicalName: base.physicalName,
|
|
896
|
+
table,
|
|
897
|
+
command,
|
|
898
|
+
...roles === void 0 ? {} : { roles },
|
|
899
|
+
...permissive === void 0 ? {} : { permissive },
|
|
900
|
+
...using === void 0 ? {} : { using },
|
|
901
|
+
...check === void 0 ? {} : { check },
|
|
902
|
+
...base.metadata
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function validateExtensionObject(value, path, diagnostics) {
|
|
906
|
+
const base = validateBase(value, path, "extension", void 0, diagnostics, [
|
|
907
|
+
"extensionName",
|
|
908
|
+
"extensionVersion",
|
|
909
|
+
"schema",
|
|
910
|
+
"data",
|
|
911
|
+
"configuration"
|
|
912
|
+
]);
|
|
913
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
914
|
+
const extensionName = stringValue(value.extensionName, [...path, "extensionName"], diagnostics, true);
|
|
915
|
+
const extensionVersion = value.extensionVersion === void 0 ? void 0 : stringValue(value.extensionVersion, [...path, "extensionVersion"], diagnostics);
|
|
916
|
+
const schema = value.schema === void 0 ? void 0 : stringValue(value.schema, [...path, "schema"], diagnostics, true);
|
|
917
|
+
const data = validateJsonValue(value.data, [...path, "data"], diagnostics);
|
|
918
|
+
const configuration = value.configuration === void 0 ? void 0 : validateJsonValue(value.configuration, [...path, "configuration"], diagnostics);
|
|
919
|
+
if (extensionName === void 0 || data === void 0) return void 0;
|
|
920
|
+
return {
|
|
921
|
+
kind: "extension",
|
|
922
|
+
id: base.id,
|
|
923
|
+
physicalName: base.physicalName,
|
|
924
|
+
extensionName,
|
|
925
|
+
...extensionVersion === void 0 ? {} : { extensionVersion },
|
|
926
|
+
...schema === void 0 ? {} : { schema },
|
|
927
|
+
data,
|
|
928
|
+
...configuration === void 0 ? {} : { configuration },
|
|
929
|
+
...base.metadata
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
function validateDeferredObject(value, path, diagnostics) {
|
|
933
|
+
const base = validateBase(value, path, "deferred-object", void 0, diagnostics, [
|
|
934
|
+
"objectKind",
|
|
935
|
+
"reason",
|
|
936
|
+
"data"
|
|
937
|
+
]);
|
|
938
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
939
|
+
const objectKind = stringValue(value.objectKind, [...path, "objectKind"], diagnostics, true);
|
|
940
|
+
const reason = value.reason === void 0 ? void 0 : stringValue(value.reason, [...path, "reason"], diagnostics);
|
|
941
|
+
const data = value.data === void 0 ? void 0 : validateJsonValue(value.data, [...path, "data"], diagnostics);
|
|
942
|
+
if (objectKind === void 0) return void 0;
|
|
943
|
+
return {
|
|
944
|
+
kind: "deferred-object",
|
|
945
|
+
id: base.id,
|
|
946
|
+
objectKind,
|
|
947
|
+
physicalName: base.physicalName,
|
|
948
|
+
...reason === void 0 ? {} : { reason },
|
|
949
|
+
...data === void 0 ? {} : { data },
|
|
950
|
+
...base.metadata
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function validateOpaqueObject(value, path, diagnostics) {
|
|
954
|
+
const base = validateBase(value, path, "opaque-object", void 0, diagnostics, [
|
|
955
|
+
"objectKind",
|
|
956
|
+
"data",
|
|
957
|
+
"sql"
|
|
958
|
+
]);
|
|
959
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
960
|
+
const objectKind = stringValue(value.objectKind, [...path, "objectKind"], diagnostics, true);
|
|
961
|
+
const data = validateJsonValue(value.data, [...path, "data"], diagnostics);
|
|
962
|
+
const sql = value.sql === void 0 ? void 0 : validateExpression(value.sql, [...path, "sql"], diagnostics);
|
|
963
|
+
if (objectKind === void 0 || data === void 0) return void 0;
|
|
964
|
+
return {
|
|
965
|
+
kind: "opaque-object",
|
|
966
|
+
id: base.id,
|
|
967
|
+
objectKind,
|
|
968
|
+
physicalName: base.physicalName,
|
|
969
|
+
data,
|
|
970
|
+
...sql === void 0 ? {} : { sql },
|
|
971
|
+
...base.metadata
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function validateComment(value, path, diagnostics) {
|
|
975
|
+
const base = validateBase(value, path, "comment", void 0, diagnostics, ["object", "text"]);
|
|
976
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
977
|
+
const object = validateObjectReference(value.object, [...path, "object"], diagnostics);
|
|
978
|
+
const text = stringValue(value.text, [...path, "text"], diagnostics);
|
|
979
|
+
if (object === void 0 || text === void 0) return void 0;
|
|
980
|
+
return {
|
|
981
|
+
kind: "comment",
|
|
982
|
+
id: base.id,
|
|
983
|
+
physicalName: base.physicalName,
|
|
984
|
+
object,
|
|
985
|
+
text,
|
|
986
|
+
...base.metadata
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
function validateOwnership(value, path, diagnostics) {
|
|
990
|
+
const base = validateBase(value, path, "ownership", void 0, diagnostics, ["object", "owner"]);
|
|
991
|
+
if (!isRecord(value) || base === void 0) return void 0;
|
|
992
|
+
const object = validateObjectReference(value.object, [...path, "object"], diagnostics);
|
|
993
|
+
const owner = stringValue(value.owner, [...path, "owner"], diagnostics, true);
|
|
994
|
+
if (object === void 0 || owner === void 0) return void 0;
|
|
995
|
+
return {
|
|
996
|
+
kind: "ownership",
|
|
997
|
+
id: base.id,
|
|
998
|
+
physicalName: base.physicalName,
|
|
999
|
+
object,
|
|
1000
|
+
owner,
|
|
1001
|
+
...base.metadata
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
function validateStorage(value, path, diagnostics) {
|
|
1005
|
+
if (!isRecord(value)) {
|
|
1006
|
+
diagnostics.push(issue("invalid-snapshot", "Storage must be an object", path));
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
if (value.kind === "portable") {
|
|
1010
|
+
requireKeys(value, ["kind", "type"], path, diagnostics);
|
|
1011
|
+
const type = stringValue(value.type, [...path, "type"], diagnostics, true);
|
|
1012
|
+
return type === void 0 ? void 0 : {
|
|
1013
|
+
kind: "portable",
|
|
1014
|
+
type
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
if (value.kind === "native") {
|
|
1018
|
+
requireKeys(value, [
|
|
1019
|
+
"kind",
|
|
1020
|
+
"dialect",
|
|
1021
|
+
"type",
|
|
1022
|
+
"affinity"
|
|
1023
|
+
], path, diagnostics, ["affinity"]);
|
|
1024
|
+
const dialect = stringValue(value.dialect, [...path, "dialect"], diagnostics, true);
|
|
1025
|
+
const type = stringValue(value.type, [...path, "type"], diagnostics, true);
|
|
1026
|
+
const affinity = value.affinity === void 0 ? void 0 : validateChoice(value.affinity, [
|
|
1027
|
+
"blob",
|
|
1028
|
+
"integer",
|
|
1029
|
+
"numeric",
|
|
1030
|
+
"real",
|
|
1031
|
+
"text"
|
|
1032
|
+
], [...path, "affinity"], diagnostics);
|
|
1033
|
+
if (dialect === void 0 || type === void 0) return void 0;
|
|
1034
|
+
return {
|
|
1035
|
+
kind: "native",
|
|
1036
|
+
dialect,
|
|
1037
|
+
type,
|
|
1038
|
+
...affinity === void 0 ? {} : { affinity }
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
diagnostics.push(issue("invalid-snapshot", "Storage kind is invalid", [...path, "kind"]));
|
|
1042
|
+
}
|
|
1043
|
+
function validateDefault(value, path, diagnostics) {
|
|
1044
|
+
if (!isRecord(value)) {
|
|
1045
|
+
diagnostics.push(issue("invalid-snapshot", "Default must be an object", path));
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
if (value.kind === "external") {
|
|
1049
|
+
requireKeys(value, ["kind"], path, diagnostics);
|
|
1050
|
+
return { kind: "external" };
|
|
1051
|
+
}
|
|
1052
|
+
if (value.kind === "literal") {
|
|
1053
|
+
requireKeys(value, ["kind", "value"], path, diagnostics);
|
|
1054
|
+
const literal = validateLiteral(value.value, [...path, "value"], diagnostics);
|
|
1055
|
+
return literal === void 0 ? void 0 : {
|
|
1056
|
+
kind: "literal",
|
|
1057
|
+
value: literal
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
if (value.kind === "expression") {
|
|
1061
|
+
requireKeys(value, ["kind", "expression"], path, diagnostics);
|
|
1062
|
+
const expression = validateExpression(value.expression, [...path, "expression"], diagnostics);
|
|
1063
|
+
return expression === void 0 ? void 0 : {
|
|
1064
|
+
kind: "expression",
|
|
1065
|
+
expression
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
diagnostics.push(issue("invalid-snapshot", "Default kind is invalid", [...path, "kind"]));
|
|
1069
|
+
}
|
|
1070
|
+
function validateGenerated(value, path, diagnostics) {
|
|
1071
|
+
if (!isRecord(value)) {
|
|
1072
|
+
diagnostics.push(issue("invalid-snapshot", "Generated-column metadata must be an object", path));
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (value.kind === "external") {
|
|
1076
|
+
requireKeys(value, ["kind"], path, diagnostics);
|
|
1077
|
+
return { kind: "external" };
|
|
1078
|
+
}
|
|
1079
|
+
if (value.kind === "expression") {
|
|
1080
|
+
requireKeys(value, [
|
|
1081
|
+
"kind",
|
|
1082
|
+
"expression",
|
|
1083
|
+
"mode"
|
|
1084
|
+
], path, diagnostics);
|
|
1085
|
+
const expression = validateExpression(value.expression, [...path, "expression"], diagnostics);
|
|
1086
|
+
const mode = validateChoice(value.mode, ["stored", "virtual"], [...path, "mode"], diagnostics);
|
|
1087
|
+
return expression === void 0 || mode === void 0 ? void 0 : {
|
|
1088
|
+
kind: "expression",
|
|
1089
|
+
expression,
|
|
1090
|
+
mode
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
diagnostics.push(issue("invalid-snapshot", "Generated-column kind is invalid", [...path, "kind"]));
|
|
1094
|
+
}
|
|
1095
|
+
function validateIdentity(value, path, diagnostics) {
|
|
1096
|
+
if (!isRecord(value)) {
|
|
1097
|
+
diagnostics.push(issue("invalid-snapshot", "Identity must be an object", path));
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
requireKeys(value, [
|
|
1101
|
+
"kind",
|
|
1102
|
+
"generation",
|
|
1103
|
+
"options",
|
|
1104
|
+
"provenance",
|
|
1105
|
+
"physicalReference",
|
|
1106
|
+
"dialect"
|
|
1107
|
+
], path, diagnostics, [
|
|
1108
|
+
"provenance",
|
|
1109
|
+
"physicalReference",
|
|
1110
|
+
"dialect"
|
|
1111
|
+
]);
|
|
1112
|
+
if (value.kind !== "identity") diagnostics.push(issue("invalid-snapshot", "Identity kind must be identity", [...path, "kind"]));
|
|
1113
|
+
const generation = validateChoice(value.generation, ["always", "by-default"], [...path, "generation"], diagnostics);
|
|
1114
|
+
const options = validateValueFactRecord(value.options, [...path, "options"], diagnostics);
|
|
1115
|
+
const metadata = validateObjectMetadata(value, path, void 0, diagnostics);
|
|
1116
|
+
if (generation === void 0 || options === void 0 || value.kind !== "identity") return void 0;
|
|
1117
|
+
return {
|
|
1118
|
+
kind: "identity",
|
|
1119
|
+
generation,
|
|
1120
|
+
options,
|
|
1121
|
+
...metadata
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
function validateExpression(value, path, diagnostics) {
|
|
1125
|
+
if (!isRecord(value)) {
|
|
1126
|
+
diagnostics.push(issue("invalid-snapshot", "Expression must be an object", path));
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
requireKeys(value, [
|
|
1130
|
+
"kind",
|
|
1131
|
+
"expressionKind",
|
|
1132
|
+
"sql",
|
|
1133
|
+
"dialect"
|
|
1134
|
+
], path, diagnostics, ["dialect"]);
|
|
1135
|
+
const expressionKind = stringValue(value.expressionKind, [...path, "expressionKind"], diagnostics, true);
|
|
1136
|
+
const sql = stringValue(value.sql, [...path, "sql"], diagnostics);
|
|
1137
|
+
const dialect = value.dialect === void 0 ? void 0 : stringValue(value.dialect, [...path, "dialect"], diagnostics, true);
|
|
1138
|
+
if (value.kind !== "expression") diagnostics.push(issue("invalid-snapshot", "Expression kind must be expression", [...path, "kind"]));
|
|
1139
|
+
if (sql !== void 0 && sql !== sql.replace(/\r\n?/g, "\n")) diagnostics.push(issue("non-canonical", "Expression SQL must use LF line endings", [...path, "sql"]));
|
|
1140
|
+
if (expressionKind === "unsafe" && dialect === void 0) diagnostics.push(issue("invalid-snapshot", "Unsafe expressions must carry a dialect tag", [...path, "dialect"]));
|
|
1141
|
+
if (expressionKind !== void 0 && expressionKind !== "unsafe" && dialect !== void 0) diagnostics.push(issue("invalid-snapshot", "Only unsafe expressions may carry a dialect tag", [...path, "dialect"]));
|
|
1142
|
+
if (expressionKind === void 0 || sql === void 0 || value.kind !== "expression") return void 0;
|
|
1143
|
+
return {
|
|
1144
|
+
kind: "expression",
|
|
1145
|
+
expressionKind,
|
|
1146
|
+
sql,
|
|
1147
|
+
...dialect === void 0 ? {} : { dialect }
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
function validateLiteral(value, path, diagnostics) {
|
|
1151
|
+
if (!isRecord(value)) {
|
|
1152
|
+
diagnostics.push(issue("invalid-snapshot", "Literal must be an object", path));
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
if (value.kind === "null") {
|
|
1156
|
+
requireKeys(value, ["kind"], path, diagnostics);
|
|
1157
|
+
return { kind: "null" };
|
|
1158
|
+
}
|
|
1159
|
+
if (value.kind === "boolean" || value.kind === "string") {
|
|
1160
|
+
requireKeys(value, ["kind", "value"], path, diagnostics);
|
|
1161
|
+
const expected = value.kind === "boolean" ? "boolean" : "string";
|
|
1162
|
+
if (typeof value.value !== expected) diagnostics.push(issue("invalid-snapshot", `${expected} literal value is invalid`, [...path, "value"]));
|
|
1163
|
+
return typeof value.value === expected ? {
|
|
1164
|
+
kind: value.kind,
|
|
1165
|
+
value: value.value
|
|
1166
|
+
} : void 0;
|
|
1167
|
+
}
|
|
1168
|
+
if (value.kind === "number" || value.kind === "bigint") {
|
|
1169
|
+
requireKeys(value, ["kind", "value"], path, diagnostics);
|
|
1170
|
+
const raw = value.value;
|
|
1171
|
+
const valid = typeof raw === "string" && isCanonicalNumber(raw, value.kind === "bigint");
|
|
1172
|
+
if (!valid) diagnostics.push(issue("invalid-snapshot", `${value.kind} literal value is not canonical`, [...path, "value"]));
|
|
1173
|
+
return valid ? {
|
|
1174
|
+
kind: value.kind,
|
|
1175
|
+
value: raw
|
|
1176
|
+
} : void 0;
|
|
1177
|
+
}
|
|
1178
|
+
diagnostics.push(issue("invalid-snapshot", "Literal kind is invalid", [...path, "kind"]));
|
|
1179
|
+
}
|
|
1180
|
+
function validateValueFact(value, path, diagnostics) {
|
|
1181
|
+
if (!isRecord(value)) {
|
|
1182
|
+
diagnostics.push(issue("invalid-snapshot", "Value fact must be an object", path));
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
if (value.kind === "literal") {
|
|
1186
|
+
requireKeys(value, ["kind", "value"], path, diagnostics);
|
|
1187
|
+
const literal = validateLiteral(value.value, [...path, "value"], diagnostics);
|
|
1188
|
+
return literal === void 0 ? void 0 : {
|
|
1189
|
+
kind: "literal",
|
|
1190
|
+
value: literal
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
if (value.kind === "expression") {
|
|
1194
|
+
requireKeys(value, ["kind", "expression"], path, diagnostics);
|
|
1195
|
+
const expression = validateExpression(value.expression, [...path, "expression"], diagnostics);
|
|
1196
|
+
return expression === void 0 ? void 0 : {
|
|
1197
|
+
kind: "expression",
|
|
1198
|
+
expression
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
diagnostics.push(issue("invalid-snapshot", "Value fact kind is invalid", [...path, "kind"]));
|
|
1202
|
+
}
|
|
1203
|
+
function validateValueFactRecord(value, path, diagnostics) {
|
|
1204
|
+
if (!isRecord(value)) {
|
|
1205
|
+
diagnostics.push(issue("invalid-snapshot", "Value-fact options must be an object", path));
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
const result = {};
|
|
1209
|
+
for (const key of Object.keys(value).sort()) {
|
|
1210
|
+
const fact = validateValueFact(value[key], [...path, key], diagnostics);
|
|
1211
|
+
if (fact !== void 0) result[key] = fact;
|
|
1212
|
+
}
|
|
1213
|
+
return result;
|
|
1214
|
+
}
|
|
1215
|
+
function validateProvenance(value, path, dialect, diagnostics) {
|
|
1216
|
+
if (!isRecord(value)) {
|
|
1217
|
+
diagnostics.push(issue("invalid-snapshot", "Provenance must be an object", path));
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
requireKeys(value, [
|
|
1221
|
+
"kind",
|
|
1222
|
+
"dialect",
|
|
1223
|
+
"path"
|
|
1224
|
+
], path, diagnostics, ["path"]);
|
|
1225
|
+
const kind = validateChoice(value.kind, [
|
|
1226
|
+
"catalog",
|
|
1227
|
+
"decompiler",
|
|
1228
|
+
"create-sql"
|
|
1229
|
+
], [...path, "kind"], diagnostics);
|
|
1230
|
+
const sourceDialect = stringValue(value.dialect, [...path, "dialect"], diagnostics, true);
|
|
1231
|
+
const sourcePath = value.path === void 0 ? void 0 : validatePath(value.path, [...path, "path"], diagnostics);
|
|
1232
|
+
if (dialect !== void 0 && sourceDialect !== void 0 && sourceDialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Provenance belongs to "${sourceDialect}" but snapshot dialect is "${dialect}"`, [...path, "dialect"]));
|
|
1233
|
+
if (kind === void 0 || sourceDialect === void 0) return void 0;
|
|
1234
|
+
return {
|
|
1235
|
+
kind,
|
|
1236
|
+
dialect: sourceDialect,
|
|
1237
|
+
...sourcePath === void 0 ? {} : { path: sourcePath }
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
function validatePhysicalReference(value, path, diagnostics) {
|
|
1241
|
+
if (!isRecord(value)) {
|
|
1242
|
+
diagnostics.push(issue("invalid-snapshot", "Physical reference must be an object", path));
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
requireKeys(value, [
|
|
1246
|
+
"kind",
|
|
1247
|
+
"namespace",
|
|
1248
|
+
"table",
|
|
1249
|
+
"name"
|
|
1250
|
+
], path, diagnostics, ["namespace", "table"]);
|
|
1251
|
+
const kind = stringValue(value.kind, [...path, "kind"], diagnostics, true);
|
|
1252
|
+
const namespace = value.namespace === void 0 ? void 0 : stringValue(value.namespace, [...path, "namespace"], diagnostics, true);
|
|
1253
|
+
const table = value.table === void 0 ? void 0 : stringValue(value.table, [...path, "table"], diagnostics, true);
|
|
1254
|
+
const name = stringValue(value.name, [...path, "name"], diagnostics, true);
|
|
1255
|
+
if (kind !== void 0 && !completeObjectKinds.has(kind) && kind !== "namespace") diagnostics.push(issue("invalid-snapshot", `Unknown physical reference kind: ${kind}`, [...path, "kind"]));
|
|
1256
|
+
return kind === void 0 || name === void 0 ? void 0 : {
|
|
1257
|
+
kind,
|
|
1258
|
+
...namespace === void 0 ? {} : { namespace },
|
|
1259
|
+
...table === void 0 ? {} : { table },
|
|
1260
|
+
name
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
function validateExtension(value, path, dialect, diagnostics) {
|
|
1264
|
+
if (!isRecord(value)) {
|
|
1265
|
+
diagnostics.push(issue("invalid-snapshot", "Dialect extension must be an object", path));
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
requireKeys(value, [
|
|
1269
|
+
"dialect",
|
|
1270
|
+
"version",
|
|
1271
|
+
"data"
|
|
1272
|
+
], path, diagnostics);
|
|
1273
|
+
const extensionDialect = stringValue(value.dialect, [...path, "dialect"], diagnostics, true);
|
|
1274
|
+
const version = integerValue(value.version, [...path, "version"], diagnostics);
|
|
1275
|
+
const data = validateJsonValue(value.data, [...path, "data"], diagnostics);
|
|
1276
|
+
if (version !== void 0 && version < 1) diagnostics.push(issue("invalid-snapshot", "Dialect extension version must be positive", [...path, "version"]));
|
|
1277
|
+
if (version !== void 0 && version > 1) diagnostics.push(issue("future-version", `Unsupported dialect extension version: ${version}`, [...path, "version"]));
|
|
1278
|
+
if (dialect !== void 0 && extensionDialect !== void 0 && extensionDialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Dialect extension belongs to "${extensionDialect}" but snapshot dialect is "${dialect}"`, [...path, "dialect"]));
|
|
1279
|
+
if (extensionDialect === void 0 || version === void 0 || data === void 0) return void 0;
|
|
1280
|
+
return {
|
|
1281
|
+
dialect: extensionDialect,
|
|
1282
|
+
version,
|
|
1283
|
+
data
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
function validateJsonValue(value, path, diagnostics, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1287
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
1288
|
+
if (typeof value === "number") {
|
|
1289
|
+
if (!Number.isFinite(value)) diagnostics.push(issue("invalid-value", "Non-finite JSON numbers must use a tagged value", path));
|
|
1290
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1291
|
+
}
|
|
1292
|
+
if (typeof value !== "object") {
|
|
1293
|
+
diagnostics.push(issue("invalid-value", "Snapshot data contains an unsupported value", path));
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
if (seen.has(value)) {
|
|
1297
|
+
diagnostics.push(issue("invalid-value", "Snapshot data cannot be cyclic", path));
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
seen.add(value);
|
|
1301
|
+
try {
|
|
1302
|
+
if (Array.isArray(value)) {
|
|
1303
|
+
const result = [];
|
|
1304
|
+
for (const [index, item] of value.entries()) {
|
|
1305
|
+
const child = validateJsonValue(item, [...path, index], diagnostics, seen);
|
|
1306
|
+
if (child !== void 0) result.push(child);
|
|
1307
|
+
}
|
|
1308
|
+
return result;
|
|
1309
|
+
}
|
|
1310
|
+
if (!isRecord(value)) {
|
|
1311
|
+
diagnostics.push(issue("invalid-value", "Snapshot data must use plain objects", path));
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
if (Object.keys(value).length === 1 && "$bigint" in value) {
|
|
1315
|
+
if (typeof value.$bigint !== "string" || !isCanonicalNumber(value.$bigint, true)) diagnostics.push(issue("invalid-value", "Tagged bigint is not canonical", [...path, "$bigint"]));
|
|
1316
|
+
return typeof value.$bigint === "string" && isCanonicalNumber(value.$bigint, true) ? { $bigint: value.$bigint } : void 0;
|
|
1317
|
+
}
|
|
1318
|
+
if (Object.keys(value).length === 1 && "$number" in value) {
|
|
1319
|
+
if (value.$number !== "NaN" && value.$number !== "Infinity" && value.$number !== "-Infinity") diagnostics.push(issue("invalid-value", "Tagged number is invalid", [...path, "$number"]));
|
|
1320
|
+
return value.$number === "NaN" || value.$number === "Infinity" || value.$number === "-Infinity" ? { $number: value.$number } : void 0;
|
|
1321
|
+
}
|
|
1322
|
+
const result = {};
|
|
1323
|
+
for (const key of Object.keys(value).sort()) {
|
|
1324
|
+
const child = validateJsonValue(value[key], [...path, key], diagnostics, seen);
|
|
1325
|
+
if (child !== void 0) result[key] = child;
|
|
1326
|
+
}
|
|
1327
|
+
return result;
|
|
1328
|
+
} finally {
|
|
1329
|
+
seen.delete(value);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
function validateObjectReference(value, path, diagnostics) {
|
|
1333
|
+
if (!isRecord(value)) {
|
|
1334
|
+
diagnostics.push(issue("invalid-snapshot", "Object reference must be an object", path));
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
requireKeys(value, ["kind", "id"], path, diagnostics);
|
|
1338
|
+
const kind = stringValue(value.kind, [...path, "kind"], diagnostics, true);
|
|
1339
|
+
const id = stringValue(value.id, [...path, "id"], diagnostics, true);
|
|
1340
|
+
if (kind === "namespace") diagnostics.push(issue("invalid-snapshot", "Object references cannot target a namespace", [...path, "kind"]));
|
|
1341
|
+
if (kind !== void 0 && !completeObjectKinds.has(kind)) diagnostics.push(issue("invalid-snapshot", `Unknown object reference kind: ${kind}`, [...path, "kind"]));
|
|
1342
|
+
return kind === void 0 || id === void 0 || !completeObjectKinds.has(kind) || kind === "namespace" ? void 0 : {
|
|
1343
|
+
kind,
|
|
1344
|
+
id
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
function validateReferences(value, path, diagnostics) {
|
|
1348
|
+
return validateArray(value, path, diagnostics, validateObjectReference);
|
|
1349
|
+
}
|
|
1350
|
+
function validateForeignKeyTarget(value, path, diagnostics) {
|
|
1351
|
+
if (!isRecord(value)) {
|
|
1352
|
+
diagnostics.push(issue("invalid-snapshot", "Foreign-key target must be an object", path));
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
requireKeys(value, ["table", "columns"], path, diagnostics);
|
|
1356
|
+
const table = validateObjectReference(value.table, [...path, "table"], diagnostics);
|
|
1357
|
+
const columns = validateIds(value.columns, [...path, "columns"], diagnostics);
|
|
1358
|
+
return table === void 0 || columns === void 0 ? void 0 : {
|
|
1359
|
+
table,
|
|
1360
|
+
columns
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
function validateIds(value, path, diagnostics, nonEmpty = true) {
|
|
1364
|
+
const result = validateStrings(value, path, diagnostics, nonEmpty);
|
|
1365
|
+
if (result === void 0) return void 0;
|
|
1366
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1367
|
+
for (const [index, id] of result.entries()) {
|
|
1368
|
+
if (seen.has(id)) diagnostics.push(issue("non-canonical", "References cannot contain duplicate IDs", [...path, index]));
|
|
1369
|
+
seen.add(id);
|
|
1370
|
+
}
|
|
1371
|
+
return result;
|
|
1372
|
+
}
|
|
1373
|
+
function validateStrings(value, path, diagnostics, nonEmpty) {
|
|
1374
|
+
if (!Array.isArray(value)) {
|
|
1375
|
+
diagnostics.push(issue("invalid-snapshot", "Value must be an array", path));
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
const result = [];
|
|
1379
|
+
for (const [index, item] of value.entries()) {
|
|
1380
|
+
const string = stringValue(item, [...path, index], diagnostics, nonEmpty);
|
|
1381
|
+
if (string !== void 0) result.push(string);
|
|
1382
|
+
}
|
|
1383
|
+
if (nonEmpty && result.length === 0) diagnostics.push(issue("invalid-snapshot", "Array cannot be empty", path));
|
|
1384
|
+
return result;
|
|
1385
|
+
}
|
|
1386
|
+
function validateArray(value, path, diagnostics, validate) {
|
|
1387
|
+
if (!Array.isArray(value)) {
|
|
1388
|
+
diagnostics.push(issue("invalid-snapshot", "Value must be an array", path));
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
const result = [];
|
|
1392
|
+
for (const [index, item] of value.entries()) {
|
|
1393
|
+
const child = validate(item, [...path, index], diagnostics);
|
|
1394
|
+
if (child !== void 0) result.push(child);
|
|
1395
|
+
}
|
|
1396
|
+
return result;
|
|
1397
|
+
}
|
|
1398
|
+
function validateTiming(value, path, diagnostics) {
|
|
1399
|
+
const deferrable = optionalBoolean(value.deferrable, [...path, "deferrable"], diagnostics);
|
|
1400
|
+
const initially = validateChoice(value.initially, ["immediate", "deferred"], [...path, "initially"], diagnostics);
|
|
1401
|
+
return {
|
|
1402
|
+
...deferrable === void 0 ? {} : { deferrable },
|
|
1403
|
+
...initially === void 0 ? {} : { initially }
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
function validateAction(value, path, diagnostics) {
|
|
1407
|
+
return validateChoice(value, [
|
|
1408
|
+
"no-action",
|
|
1409
|
+
"restrict",
|
|
1410
|
+
"cascade",
|
|
1411
|
+
"set-null",
|
|
1412
|
+
"set-default"
|
|
1413
|
+
], path, diagnostics);
|
|
1414
|
+
}
|
|
1415
|
+
function validateMatch(value, path, diagnostics) {
|
|
1416
|
+
return validateChoice(value, [
|
|
1417
|
+
"simple",
|
|
1418
|
+
"full",
|
|
1419
|
+
"partial"
|
|
1420
|
+
], path, diagnostics);
|
|
1421
|
+
}
|
|
1422
|
+
function validateNulls(value, path, diagnostics) {
|
|
1423
|
+
return validateChoice(value, ["distinct", "not-distinct"], path, diagnostics);
|
|
1424
|
+
}
|
|
1425
|
+
function validateDirection(value, path, diagnostics) {
|
|
1426
|
+
return validateChoice(value, ["ASC", "DESC"], path, diagnostics);
|
|
1427
|
+
}
|
|
1428
|
+
function validateIndexNulls(value, path, diagnostics) {
|
|
1429
|
+
return validateChoice(value, ["FIRST", "LAST"], path, diagnostics);
|
|
1430
|
+
}
|
|
1431
|
+
function validateCheckOption(value, path, diagnostics) {
|
|
1432
|
+
return validateChoice(value, [
|
|
1433
|
+
"none",
|
|
1434
|
+
"local",
|
|
1435
|
+
"cascaded"
|
|
1436
|
+
], path, diagnostics);
|
|
1437
|
+
}
|
|
1438
|
+
function validateTimingKind(value, path, diagnostics) {
|
|
1439
|
+
return validateChoice(value, [
|
|
1440
|
+
"before",
|
|
1441
|
+
"after",
|
|
1442
|
+
"instead-of",
|
|
1443
|
+
"unknown"
|
|
1444
|
+
], path, diagnostics);
|
|
1445
|
+
}
|
|
1446
|
+
function validateOrientation(value, path, diagnostics) {
|
|
1447
|
+
return validateChoice(value, ["row", "statement"], path, diagnostics);
|
|
1448
|
+
}
|
|
1449
|
+
function validateRoutineKind(value, path, diagnostics) {
|
|
1450
|
+
return validateChoice(value, [
|
|
1451
|
+
"function",
|
|
1452
|
+
"procedure",
|
|
1453
|
+
"aggregate",
|
|
1454
|
+
"window",
|
|
1455
|
+
"unknown"
|
|
1456
|
+
], path, diagnostics);
|
|
1457
|
+
}
|
|
1458
|
+
function validateEvents(value, path, diagnostics) {
|
|
1459
|
+
const events = validateStrings(value, path, diagnostics, true);
|
|
1460
|
+
if (events === void 0) return void 0;
|
|
1461
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
1462
|
+
"insert",
|
|
1463
|
+
"update",
|
|
1464
|
+
"delete",
|
|
1465
|
+
"truncate"
|
|
1466
|
+
]);
|
|
1467
|
+
const result = [];
|
|
1468
|
+
for (const [index, event] of events.entries()) if (!allowed.has(event)) diagnostics.push(issue("invalid-snapshot", "Trigger event is invalid", [...path, index]));
|
|
1469
|
+
else result.push(event);
|
|
1470
|
+
if ([...result].sort().some((event, index) => event !== result[index])) diagnostics.push(issue("non-canonical", "Trigger events must be sorted", path));
|
|
1471
|
+
return result;
|
|
1472
|
+
}
|
|
1473
|
+
function validatePath(value, path, diagnostics) {
|
|
1474
|
+
if (!Array.isArray(value)) {
|
|
1475
|
+
diagnostics.push(issue("invalid-snapshot", "Provenance path must be an array", path));
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
const result = [];
|
|
1479
|
+
for (const [index, part] of value.entries()) if (typeof part !== "string" && typeof part !== "number" || typeof part === "number" && !Number.isSafeInteger(part)) diagnostics.push(issue("invalid-snapshot", "Provenance path parts must be strings or safe integers", [...path, index]));
|
|
1480
|
+
else result.push(part);
|
|
1481
|
+
return result;
|
|
1482
|
+
}
|
|
1483
|
+
function validateChoice(value, choices, path, diagnostics) {
|
|
1484
|
+
if (value === void 0) return void 0;
|
|
1485
|
+
if (choices.includes(value)) return value;
|
|
1486
|
+
diagnostics.push(issue("invalid-snapshot", `Value must be one of ${choices.join(", ")}`, path));
|
|
1487
|
+
}
|
|
1488
|
+
function stringValue(value, path, diagnostics, nonEmpty = false) {
|
|
1489
|
+
if (typeof value !== "string" || nonEmpty && value.length === 0) {
|
|
1490
|
+
diagnostics.push(issue("invalid-snapshot", nonEmpty ? "Value must be a non-empty string" : "Value must be a string", path));
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
return value;
|
|
1494
|
+
}
|
|
1495
|
+
function integerValue(value, path, diagnostics) {
|
|
1496
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value)) {
|
|
1497
|
+
diagnostics.push(issue("invalid-snapshot", "Value must be a safe integer", path));
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
return value;
|
|
1501
|
+
}
|
|
1502
|
+
function booleanValue(value, path, diagnostics) {
|
|
1503
|
+
if (typeof value !== "boolean") {
|
|
1504
|
+
diagnostics.push(issue("invalid-snapshot", "Value must be boolean", path));
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
return value;
|
|
1508
|
+
}
|
|
1509
|
+
function optionalBoolean(value, path, diagnostics) {
|
|
1510
|
+
return value === void 0 ? void 0 : booleanValue(value, path, diagnostics);
|
|
1511
|
+
}
|
|
1512
|
+
function isCanonicalNumber(value, integer) {
|
|
1513
|
+
return integer ? /^(?:0|-[1-9]\d*|[1-9]\d*)$/u.test(value) : /^(?:0|-?(?:[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|0(?:\.\d+)?(?:[eE][+-]?\d+)?)$/u.test(value);
|
|
1514
|
+
}
|
|
1515
|
+
const completeObjectKinds = /* @__PURE__ */ new Set([
|
|
1516
|
+
"table",
|
|
1517
|
+
"column",
|
|
1518
|
+
"constraint",
|
|
1519
|
+
"index",
|
|
1520
|
+
"view",
|
|
1521
|
+
"materialized-view",
|
|
1522
|
+
"sequence",
|
|
1523
|
+
"enum",
|
|
1524
|
+
"domain",
|
|
1525
|
+
"collation",
|
|
1526
|
+
"trigger",
|
|
1527
|
+
"routine",
|
|
1528
|
+
"partition",
|
|
1529
|
+
"policy",
|
|
1530
|
+
"extension",
|
|
1531
|
+
"comment",
|
|
1532
|
+
"ownership",
|
|
1533
|
+
"deferred-object",
|
|
1534
|
+
"opaque-object"
|
|
1535
|
+
]);
|
|
1536
|
+
function validateCompleteDialectMetadata(snapshot, diagnostics) {
|
|
1537
|
+
const dialect = snapshot.dialect.name;
|
|
1538
|
+
const objects = [
|
|
1539
|
+
...snapshot.tables,
|
|
1540
|
+
...snapshot.views,
|
|
1541
|
+
...snapshot.sequences,
|
|
1542
|
+
...snapshot.enums,
|
|
1543
|
+
...snapshot.domains,
|
|
1544
|
+
...snapshot.collations,
|
|
1545
|
+
...snapshot.triggers,
|
|
1546
|
+
...snapshot.routines,
|
|
1547
|
+
...snapshot.partitions,
|
|
1548
|
+
...snapshot.policies,
|
|
1549
|
+
...snapshot.extensions,
|
|
1550
|
+
...snapshot.deferredObjects,
|
|
1551
|
+
...snapshot.opaqueObjects,
|
|
1552
|
+
...snapshot.comments,
|
|
1553
|
+
...snapshot.ownership
|
|
1554
|
+
];
|
|
1555
|
+
for (const object of objects) {
|
|
1556
|
+
if (object.dialect?.dialect !== void 0 && object.dialect.dialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Dialect extension belongs to "${object.dialect.dialect}" but snapshot dialect is "${dialect}"`, [
|
|
1557
|
+
object.kind,
|
|
1558
|
+
object.id,
|
|
1559
|
+
"dialect",
|
|
1560
|
+
"dialect"
|
|
1561
|
+
]));
|
|
1562
|
+
if (object.provenance?.dialect !== void 0 && object.provenance.dialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Provenance belongs to "${object.provenance.dialect}" but snapshot dialect is "${dialect}"`, [
|
|
1563
|
+
object.kind,
|
|
1564
|
+
object.id,
|
|
1565
|
+
"provenance",
|
|
1566
|
+
"dialect"
|
|
1567
|
+
]));
|
|
1568
|
+
}
|
|
1569
|
+
walkCompleteMetadata(snapshot, [], dialect, diagnostics);
|
|
1570
|
+
}
|
|
1571
|
+
function walkCompleteMetadata(value, path, dialect, diagnostics, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1572
|
+
if (value === null || typeof value !== "object") return;
|
|
1573
|
+
if (seen.has(value)) return;
|
|
1574
|
+
seen.add(value);
|
|
1575
|
+
try {
|
|
1576
|
+
if (Array.isArray(value)) {
|
|
1577
|
+
for (const [index, child] of value.entries()) walkCompleteMetadata(child, [...path, index], dialect, diagnostics, seen);
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
if (!isRecord(value)) return;
|
|
1581
|
+
if (value.kind === "expression" && typeof value.dialect === "string" && value.dialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Expression belongs to "${value.dialect}" but snapshot dialect is "${dialect}"`, [...path, "dialect"]));
|
|
1582
|
+
if (value.kind === "native" && typeof value.dialect === "string" && value.dialect !== dialect) diagnostics.push(issue("dialect-mismatch", `Native storage belongs to "${value.dialect}" but snapshot dialect is "${dialect}"`, [...path, "dialect"]));
|
|
1583
|
+
for (const [key, child] of Object.entries(value)) if (key !== "data") walkCompleteMetadata(child, [...path, key], dialect, diagnostics, seen);
|
|
1584
|
+
} finally {
|
|
1585
|
+
seen.delete(value);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
function validateCompleteCrossReferences(snapshot, diagnostics) {
|
|
1589
|
+
const objects = /* @__PURE__ */ new Map();
|
|
1590
|
+
const add = (object) => {
|
|
1591
|
+
const kind = object.kind;
|
|
1592
|
+
objects.set(referenceKey(kind, object.id), object);
|
|
1593
|
+
if (kind === "primary-key" || kind === "unique" || kind === "unique-constraint" || kind === "foreign-key" || kind === "check") objects.set(referenceKey("constraint", object.id), object);
|
|
1594
|
+
};
|
|
1595
|
+
for (const table of snapshot.tables) {
|
|
1596
|
+
add(table);
|
|
1597
|
+
for (const column of table.columns) add(column);
|
|
1598
|
+
for (const constraint of table.constraints) add(constraint);
|
|
1599
|
+
for (const index of table.indexes) add(index);
|
|
1600
|
+
}
|
|
1601
|
+
for (const group of [
|
|
1602
|
+
snapshot.views,
|
|
1603
|
+
snapshot.sequences,
|
|
1604
|
+
snapshot.enums,
|
|
1605
|
+
snapshot.domains,
|
|
1606
|
+
snapshot.collations,
|
|
1607
|
+
snapshot.triggers,
|
|
1608
|
+
snapshot.routines,
|
|
1609
|
+
snapshot.partitions,
|
|
1610
|
+
snapshot.policies,
|
|
1611
|
+
snapshot.extensions,
|
|
1612
|
+
snapshot.deferredObjects,
|
|
1613
|
+
snapshot.opaqueObjects,
|
|
1614
|
+
snapshot.comments,
|
|
1615
|
+
snapshot.ownership
|
|
1616
|
+
]) for (const object of group) add(object);
|
|
1617
|
+
for (const view of snapshot.views) for (const column of view.columns) add(column);
|
|
1618
|
+
const requireReference = (reference, path, expected) => {
|
|
1619
|
+
if (expected !== void 0 && reference.kind !== expected) diagnostics.push(issue("invalid-cross-reference", `Reference must target a ${expected}`, path));
|
|
1620
|
+
if (!objects.has(referenceKey(reference.kind, reference.id))) diagnostics.push(issue("invalid-cross-reference", `Referenced ${reference.kind} "${reference.id}" does not exist`, path));
|
|
1621
|
+
};
|
|
1622
|
+
for (const [tableIndex, table] of snapshot.tables.entries()) {
|
|
1623
|
+
const columns = new Set(table.columns.map((column) => column.id));
|
|
1624
|
+
for (const [constraintIndex, constraint] of table.constraints.entries()) {
|
|
1625
|
+
if (constraint.kind !== "check") {
|
|
1626
|
+
for (const [columnIndex, column] of constraint.columns.entries()) if (!columns.has(column)) diagnostics.push(issue("invalid-cross-reference", `Constraint column "${column}" is not declared on table "${table.id}"`, [
|
|
1627
|
+
"tables",
|
|
1628
|
+
tableIndex,
|
|
1629
|
+
"constraints",
|
|
1630
|
+
constraintIndex,
|
|
1631
|
+
"columns",
|
|
1632
|
+
columnIndex
|
|
1633
|
+
]));
|
|
1634
|
+
}
|
|
1635
|
+
if (constraint.kind === "foreign-key") {
|
|
1636
|
+
requireReference(constraint.target.table, [
|
|
1637
|
+
"tables",
|
|
1638
|
+
tableIndex,
|
|
1639
|
+
"constraints",
|
|
1640
|
+
constraintIndex,
|
|
1641
|
+
"target",
|
|
1642
|
+
"table"
|
|
1643
|
+
], "table");
|
|
1644
|
+
const target = objects.get(referenceKey(constraint.target.table.kind, constraint.target.table.id));
|
|
1645
|
+
if (target?.kind === "table") {
|
|
1646
|
+
const targetColumns = new Set(target.columns.map((column) => column.id));
|
|
1647
|
+
for (const [columnIndex, column] of constraint.target.columns.entries()) if (!targetColumns.has(column)) diagnostics.push(issue("invalid-cross-reference", `Foreign-key target column "${column}" is not declared on table "${target.id}"`, [
|
|
1648
|
+
"tables",
|
|
1649
|
+
tableIndex,
|
|
1650
|
+
"constraints",
|
|
1651
|
+
constraintIndex,
|
|
1652
|
+
"target",
|
|
1653
|
+
"columns",
|
|
1654
|
+
columnIndex
|
|
1655
|
+
]));
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
if (constraint.kind !== "foreign-key" && "backingIndex" in constraint && constraint.backingIndex !== void 0) requireReference(constraint.backingIndex, [
|
|
1659
|
+
"tables",
|
|
1660
|
+
tableIndex,
|
|
1661
|
+
"constraints",
|
|
1662
|
+
constraintIndex,
|
|
1663
|
+
"backingIndex"
|
|
1664
|
+
], "index");
|
|
1665
|
+
}
|
|
1666
|
+
for (const [indexIndex, index] of table.indexes.entries()) {
|
|
1667
|
+
for (const [termIndex, term] of index.terms.entries()) if (term.kind === "column" && !columns.has(term.column)) diagnostics.push(issue("invalid-cross-reference", `Index column "${term.column}" is not declared on table "${table.id}"`, [
|
|
1668
|
+
"tables",
|
|
1669
|
+
tableIndex,
|
|
1670
|
+
"indexes",
|
|
1671
|
+
indexIndex,
|
|
1672
|
+
"terms",
|
|
1673
|
+
termIndex,
|
|
1674
|
+
"column"
|
|
1675
|
+
]));
|
|
1676
|
+
for (const [columnIndex, column] of (index.includedColumns ?? []).entries()) if (!columns.has(column)) diagnostics.push(issue("invalid-cross-reference", `Included index column "${column}" is not declared on table "${table.id}"`, [
|
|
1677
|
+
"tables",
|
|
1678
|
+
tableIndex,
|
|
1679
|
+
"indexes",
|
|
1680
|
+
indexIndex,
|
|
1681
|
+
"includedColumns",
|
|
1682
|
+
columnIndex
|
|
1683
|
+
]));
|
|
1684
|
+
if (index.backingConstraint !== void 0) requireReference(index.backingConstraint, [
|
|
1685
|
+
"tables",
|
|
1686
|
+
tableIndex,
|
|
1687
|
+
"indexes",
|
|
1688
|
+
indexIndex,
|
|
1689
|
+
"backingConstraint"
|
|
1690
|
+
], "constraint");
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
for (const [index, sequence] of snapshot.sequences.entries()) if (sequence.ownedBy !== void 0) requireReference(sequence.ownedBy, [
|
|
1694
|
+
"sequences",
|
|
1695
|
+
index,
|
|
1696
|
+
"ownedBy"
|
|
1697
|
+
]);
|
|
1698
|
+
for (const [index, view] of snapshot.views.entries()) for (const [dependency, reference] of (view.dependencies ?? []).entries()) requireReference(reference, [
|
|
1699
|
+
"views",
|
|
1700
|
+
index,
|
|
1701
|
+
"dependencies",
|
|
1702
|
+
dependency
|
|
1703
|
+
]);
|
|
1704
|
+
for (const [index, trigger] of snapshot.triggers.entries()) requireReference(trigger.table, [
|
|
1705
|
+
"triggers",
|
|
1706
|
+
index,
|
|
1707
|
+
"table"
|
|
1708
|
+
]);
|
|
1709
|
+
for (const [index, routine] of snapshot.routines.entries()) for (const [dependency, reference] of (routine.dependencies ?? []).entries()) requireReference(reference, [
|
|
1710
|
+
"routines",
|
|
1711
|
+
index,
|
|
1712
|
+
"dependencies",
|
|
1713
|
+
dependency
|
|
1714
|
+
]);
|
|
1715
|
+
for (const [index, partition] of snapshot.partitions.entries()) requireReference(partition.parent, [
|
|
1716
|
+
"partitions",
|
|
1717
|
+
index,
|
|
1718
|
+
"parent"
|
|
1719
|
+
], "table");
|
|
1720
|
+
for (const [index, policy] of snapshot.policies.entries()) requireReference(policy.table, [
|
|
1721
|
+
"policies",
|
|
1722
|
+
index,
|
|
1723
|
+
"table"
|
|
1724
|
+
], "table");
|
|
1725
|
+
for (const [index, comment] of snapshot.comments.entries()) requireReference(comment.object, [
|
|
1726
|
+
"comments",
|
|
1727
|
+
index,
|
|
1728
|
+
"object"
|
|
1729
|
+
]);
|
|
1730
|
+
for (const [index, ownership] of snapshot.ownership.entries()) requireReference(ownership.object, [
|
|
1731
|
+
"ownership",
|
|
1732
|
+
index,
|
|
1733
|
+
"object"
|
|
1734
|
+
]);
|
|
1735
|
+
}
|
|
1736
|
+
function referenceKey(kind, id) {
|
|
1737
|
+
return `${kind}\u0000${id}`;
|
|
1738
|
+
}
|
|
1739
|
+
function validateSortedIds(value, path, diagnostics) {
|
|
1740
|
+
if (!Array.isArray(value)) return;
|
|
1741
|
+
let previous;
|
|
1742
|
+
for (const [index, item] of value.entries()) {
|
|
1743
|
+
if (!isRecord(item) || typeof item.id !== "string") continue;
|
|
1744
|
+
if (previous !== void 0 && item.id <= previous) diagnostics.push(issue("non-canonical", "Entities must be sorted by stable logical ID", [
|
|
1745
|
+
...path,
|
|
1746
|
+
index,
|
|
1747
|
+
"id"
|
|
1748
|
+
]));
|
|
1749
|
+
previous = item.id;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
function validateSortedPositions(value, path, diagnostics) {
|
|
1753
|
+
let previous;
|
|
1754
|
+
for (const [index, item] of value.entries()) {
|
|
1755
|
+
const position = item.position ?? item.ordinalPosition;
|
|
1756
|
+
if (position !== void 0 && previous !== void 0 && position <= previous) diagnostics.push(issue("non-canonical", "Positioned entries must be sorted by strictly increasing position", [
|
|
1757
|
+
...path,
|
|
1758
|
+
index,
|
|
1759
|
+
item.position === void 0 ? "ordinalPosition" : "position"
|
|
1760
|
+
]));
|
|
1761
|
+
if (position !== void 0) previous = position;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
function requireKeys(value, required, path, diagnostics, optional = []) {
|
|
1765
|
+
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
1766
|
+
for (const key of required) if (!optional.includes(key) && !(key in value)) diagnostics.push(issue("invalid-snapshot", `Missing required field "${key}"`, [...path, key]));
|
|
1767
|
+
for (const key of Object.keys(value)) if (!allowed.has(key)) diagnostics.push(issue("unknown-field", `Unknown snapshot field "${key}"`, [...path, key]));
|
|
1768
|
+
}
|
|
1769
|
+
function isRecord(value) {
|
|
1770
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1771
|
+
}
|
|
1772
|
+
function issue(code, message, path) {
|
|
1773
|
+
return {
|
|
1774
|
+
code,
|
|
1775
|
+
message,
|
|
1776
|
+
path: Object.freeze([...path])
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
function deepFreeze(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1780
|
+
if (value === null || typeof value !== "object") return value;
|
|
1781
|
+
if (seen.has(value)) return value;
|
|
1782
|
+
seen.add(value);
|
|
1783
|
+
if (Array.isArray(value)) for (const item of value) deepFreeze(item, seen);
|
|
1784
|
+
else for (const child of Object.values(value)) deepFreeze(child, seen);
|
|
1785
|
+
return Object.freeze(value);
|
|
1786
|
+
}
|
|
1787
|
+
//#endregion
|
|
1788
|
+
export { completeSchemaSnapshotVersion as _, canonicalizeCompleteSchemaSnapshot as a, schemaSnapshotVersion2 as b, decodeCompleteSchemaSnapshot as c, digestCompleteSchemaSnapshot as d, encodeCompleteSchemaSnapshot as f, completeSchemaSnapshotFormat as g, schemaSnapshotV2Digest as h, assertSchemaSnapshotV2 as i, decodeCompleteSnapshot as l, encodeSchemaSnapshotV2 as m, assertCompleteSchemaSnapshot as n, canonicalizeSchemaSnapshotV2 as o, encodeCompleteSnapshot as p, assertCompleteSnapshot as r, completeSchemaSnapshotDigest as s, CompleteSnapshotValidationError as t, decodeSchemaSnapshotV2 as u, schemaSnapshotCompleteVersion as v, schemaSnapshotV2Version as y };
|