qubu 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +112 -0
  2. package/dist/codegen.d.mts +1 -1
  3. package/dist/codegen.mjs +1 -1
  4. package/dist/column-BzN8KFJa.mjs +364 -0
  5. package/dist/column-CFvSbil0.mjs +309 -0
  6. package/dist/{complete-types-CY0KbzNw.d.mts → complete-types-CNMWBWap.d.mts} +1 -1
  7. package/dist/constraints-DM_tarXc.mjs +208 -0
  8. package/dist/core.d.mts +1 -1
  9. package/dist/core.mjs +2 -3
  10. package/dist/diagnostics-I9vVtXkc.mjs +40 -0
  11. package/dist/diff.d.mts +2 -2
  12. package/dist/expressions-BCjc08zw.mjs +129 -0
  13. package/dist/index-CGui70hi.d.mts +32 -0
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +58 -13
  16. package/dist/introspection/mysql.d.mts +26 -0
  17. package/dist/introspection/mysql.mjs +1145 -0
  18. package/dist/introspection/postgres.d.mts +40 -0
  19. package/dist/introspection/postgres.mjs +1554 -0
  20. package/dist/introspection/sqlite.d.mts +15 -0
  21. package/dist/introspection/sqlite.mjs +986 -0
  22. package/dist/introspection.d.mts +3 -78
  23. package/dist/introspection.mjs +5 -3683
  24. package/dist/mysql.d.mts +1 -1
  25. package/dist/mysql.mjs +2 -2
  26. package/dist/{on-conflict-jPsl9l0K.mjs → on-conflict-CnaY5qso.mjs} +76 -3
  27. package/dist/postgres-Dey7QXPL.mjs +69 -0
  28. package/dist/postgres.d.mts +3 -3
  29. package/dist/postgres.mjs +3 -52
  30. package/dist/registry-oWDiqD7i.mjs +127 -0
  31. package/dist/{relational-x3BDVX9e.mjs → relational-DSAJ-l58.mjs} +1 -2
  32. package/dist/schema.d.mts +1 -1
  33. package/dist/schema.mjs +7 -4
  34. package/dist/{sqlite-CsIUtZ2Q.mjs → serialize-CE-gw5_s.mjs} +4 -318
  35. package/dist/serialize-OvXCLzjm.d.mts +66 -0
  36. package/dist/snapshot/mysql.d.mts +17 -0
  37. package/dist/snapshot/mysql.mjs +356 -0
  38. package/dist/snapshot/postgres.d.mts +17 -0
  39. package/dist/snapshot/postgres.mjs +237 -0
  40. package/dist/snapshot/sqlite.d.mts +25 -0
  41. package/dist/snapshot/sqlite.mjs +321 -0
  42. package/dist/{snapshot-BSraiLtH.mjs → snapshot-DgsOhf_8.mjs} +4 -42
  43. package/dist/snapshot.d.mts +5 -4
  44. package/dist/snapshot.mjs +2 -583
  45. package/dist/{source-C4Vmu5bb.mjs → source-BDuUXmAk.mjs} +2 -1
  46. package/dist/sqlite.d.mts +1 -1
  47. package/dist/sqlite.mjs +6 -6
  48. package/dist/{table-DLQ7YWth.mjs → table-C1QGNe4P.mjs} +3 -2
  49. package/dist/{types-CTCqtFlS.d.mts → types-BEn0N_al.d.mts} +1 -1
  50. package/dist/{types-CTENnDh9.mjs → types-BLNRatG_.mjs} +2 -3
  51. package/dist/{types-C0VkiwpR.d.mts → types-DUe6eeI0.d.mts} +57 -28
  52. package/docs/guides/compose-queries.md +22 -0
  53. package/docs/guides/drizzle.md +11 -11
  54. package/docs/guides/mutations.md +89 -0
  55. package/docs/guides/valtio-sync.md +113 -0
  56. package/docs/migrations/index.md +57 -19
  57. package/docs/migrations/operations.md +20 -6
  58. package/docs/reference/mysql-snapshot.md +5 -5
  59. package/docs/reference/postgres-snapshot.md +7 -7
  60. package/docs/reference/sqlite-snapshot.md +5 -5
  61. package/docs/reference/supported-surface.md +20 -6
  62. package/docs/schema/code-generation.md +5 -4
  63. package/docs/schema/ddl-emission.md +1 -1
  64. package/docs/schema/introspection.md +3 -2
  65. package/docs/schema/snapshots.md +12 -0
  66. package/docs/sql-semantic-types.md +8 -0
  67. package/package.json +25 -1
  68. package/dist/column-DmazTL67.mjs +0 -633
  69. package/dist/index-C-480HmV.d.mts +0 -146
  70. package/dist/registry-BGqa05et.mjs +0 -461
  71. package/dist/standard-DfcZEVOj.mjs +0 -12
  72. package/dist/value-BEEj_Ayd.mjs +0 -29
@@ -0,0 +1,309 @@
1
+ import { S as isSchemaExpression, m as freezeSchemaMetadata, z as resultValue } from "./column-BzN8KFJa.mjs";
2
+ //#region src/schema/column-behavior.ts
3
+ /** A column behavior error with a stable code and optional property path. */
4
+ var ColumnBehaviorError = class extends TypeError {
5
+ code;
6
+ path;
7
+ constructor(code, message, path) {
8
+ super(message);
9
+ this.name = "ColumnBehaviorError";
10
+ this.code = code;
11
+ this.path = path;
12
+ }
13
+ };
14
+ /** Build a canonical literal node from a supported JavaScript scalar. */
15
+ function canonicalLiteral(value) {
16
+ if (value === null) return Object.freeze({ kind: "null" });
17
+ if (typeof value === "boolean") return Object.freeze({
18
+ kind: "boolean",
19
+ value
20
+ });
21
+ if (typeof value === "string") return Object.freeze({
22
+ kind: "string",
23
+ value
24
+ });
25
+ if (typeof value === "bigint") return Object.freeze({
26
+ kind: "bigint",
27
+ value: String(value)
28
+ });
29
+ if (!Number.isFinite(value)) throw new ColumnBehaviorError("invalid-default", "Default literal numbers must be finite", "default.value");
30
+ return Object.freeze({
31
+ kind: "number",
32
+ value: Object.is(value, -0) ? "0" : String(value)
33
+ });
34
+ }
35
+ function literalDefault(value) {
36
+ return Object.freeze({
37
+ kind: "literal",
38
+ value: canonicalLiteral(value)
39
+ });
40
+ }
41
+ /** Normalize a public default input into its canonical snapshot descriptor. */
42
+ function normalizeDefault(value) {
43
+ if (isSchemaExpression(value)) return Object.freeze({
44
+ kind: "expression",
45
+ expression: value
46
+ });
47
+ if (isExternalDefaultDescriptor(value)) return externalDefault();
48
+ return literalDefault(value);
49
+ }
50
+ /** Mark a legacy or externally managed database default explicitly. */
51
+ function externalDefault() {
52
+ return Object.freeze({ kind: "external" });
53
+ }
54
+ /** Create an immutable generated-column descriptor. */
55
+ function generatedColumn(expression, mode) {
56
+ assertSchemaExpression(expression, "generatedColumn.expression", "invalid-generated-column");
57
+ const resolvedMode = typeof mode === "string" ? mode : mode?.mode ?? "stored";
58
+ if (resolvedMode !== "stored" && resolvedMode !== "virtual") throw new ColumnBehaviorError("invalid-generated-column", `Generated-column mode must be "stored" or "virtual", received "${String(resolvedMode)}"`, "generatedColumn.mode");
59
+ return Object.freeze({
60
+ kind: "expression",
61
+ expression,
62
+ mode: resolvedMode
63
+ });
64
+ }
65
+ /** Mark a legacy or externally managed generated column explicitly. */
66
+ function externalGeneratedColumn() {
67
+ return Object.freeze({ kind: "external" });
68
+ }
69
+ /** Describe a database identity column without inventing a generated SQL expression. */
70
+ function identityColumn(generation, options) {
71
+ const resolvedGeneration = generation ?? "by-default";
72
+ if (resolvedGeneration !== "always" && resolvedGeneration !== "by-default") throw new ColumnBehaviorError("invalid-identity", `Identity generation must be "always" or "by-default", received "${String(resolvedGeneration)}"`, "identity.generation");
73
+ return Object.freeze({
74
+ kind: "identity",
75
+ generation: resolvedGeneration,
76
+ ...options?.dialect === void 0 ? {} : { dialect: freezeSchemaMetadata(options.dialect) }
77
+ });
78
+ }
79
+ /** Normalize complete and legacy column behavior into immutable metadata. */
80
+ function resolveColumnBehavior(options) {
81
+ const hasDefaultFlag = options.hasDefault === true;
82
+ const defaultFn = options.defaultFn;
83
+ const generatedFlag = options.generated === true;
84
+ const defaultDescriptor = options.default === void 0 ? void 0 : normalizeDefault(options.default);
85
+ const generatedDescriptor = options.generatedColumn;
86
+ const identityDescriptor = options.identity;
87
+ const onUpdateExpression = options.onUpdate;
88
+ if (defaultFn !== void 0 && typeof defaultFn !== "function") throw new ColumnBehaviorError("invalid-runtime-default", "Column defaultFn must be a function", "defaultFn");
89
+ if (defaultFn !== void 0 && (generatedFlag || generatedDescriptor !== void 0 || identityDescriptor !== void 0)) throw new ColumnBehaviorError("runtime-default-generated-conflict", "A runtime default cannot be combined with generated-column or identity metadata", "defaultFn");
90
+ if (onUpdateExpression !== void 0 && !isSchemaExpression(onUpdateExpression)) throw new ColumnBehaviorError("invalid-on-update", "Column onUpdate metadata must carry the deterministic schema-expression brand", "onUpdate");
91
+ if (defaultDescriptor !== void 0) {
92
+ assertDefaultDescriptor(defaultDescriptor);
93
+ if (options.hasDefault === false) throw new ColumnBehaviorError("default-flag-conflict", "A complete default descriptor cannot be combined with hasDefault: false", "hasDefault");
94
+ if (generatedDescriptor !== void 0 || identityDescriptor !== void 0) throw new ColumnBehaviorError("default-generated-conflict", "A column cannot declare a complete default together with generated-column or identity metadata", "default");
95
+ if (generatedFlag) throw new ColumnBehaviorError("default-generated-conflict", "A complete default descriptor cannot be combined with generated: true", "default");
96
+ }
97
+ if (generatedDescriptor !== void 0) {
98
+ assertGeneratedColumnDescriptor(generatedDescriptor);
99
+ if (options.generated === false) throw new ColumnBehaviorError("generated-flag-conflict", "A complete generated-column descriptor cannot be combined with generated: false", "generated");
100
+ if (identityDescriptor !== void 0) throw new ColumnBehaviorError("identity-generated-conflict", "A column cannot declare both generated-column and identity metadata", "generatedColumn");
101
+ if (hasDefaultFlag) throw new ColumnBehaviorError("default-generated-conflict", "A complete generated-column descriptor cannot be combined with hasDefault: true", "generatedColumn");
102
+ }
103
+ if (identityDescriptor !== void 0) {
104
+ assertIdentityDescriptor(identityDescriptor);
105
+ if (options.generated === false) throw new ColumnBehaviorError("generated-flag-conflict", "Identity metadata cannot be combined with generated: false", "generated");
106
+ if (hasDefaultFlag) throw new ColumnBehaviorError("identity-generated-conflict", "Identity metadata cannot be combined with hasDefault: true", "identity");
107
+ }
108
+ const normalizedDefault = defaultDescriptor === void 0 ? void 0 : freezeDefaultDescriptor(defaultDescriptor);
109
+ const normalizedGenerated = generatedDescriptor === void 0 ? void 0 : freezeGeneratedColumnDescriptor(generatedDescriptor);
110
+ const normalizedIdentity = identityDescriptor === void 0 ? void 0 : freezeIdentityDescriptor(identityDescriptor);
111
+ return Object.freeze({
112
+ hasDefault: hasDefaultFlag || normalizedDefault !== void 0,
113
+ hasRuntimeDefault: defaultFn !== void 0,
114
+ generated: generatedFlag || normalizedGenerated !== void 0 || normalizedIdentity !== void 0,
115
+ default: normalizedDefault ?? (hasDefaultFlag ? externalDefault() : void 0),
116
+ defaultFn,
117
+ generatedColumn: normalizedGenerated ?? (generatedFlag && normalizedIdentity === void 0 ? externalGeneratedColumn() : void 0),
118
+ identity: normalizedIdentity,
119
+ onUpdate: onUpdateExpression
120
+ });
121
+ }
122
+ function freezeDefaultDescriptor(value) {
123
+ if (value.kind === "external") return externalDefault();
124
+ if (value.kind === "expression") return Object.freeze({
125
+ kind: "expression",
126
+ expression: value.expression
127
+ });
128
+ return Object.freeze({
129
+ kind: "literal",
130
+ value: Object.freeze({ ...value.value })
131
+ });
132
+ }
133
+ function isExternalDefaultDescriptor(value) {
134
+ return typeof value === "object" && value !== null && value.kind === "external";
135
+ }
136
+ function freezeGeneratedColumnDescriptor(value) {
137
+ if (value.kind === "external") return externalGeneratedColumn();
138
+ return Object.freeze({
139
+ kind: "expression",
140
+ expression: value.expression,
141
+ mode: value.mode
142
+ });
143
+ }
144
+ function freezeIdentityDescriptor(value) {
145
+ return Object.freeze({
146
+ kind: "identity",
147
+ generation: value.generation,
148
+ ...value.dialect === void 0 ? {} : { dialect: freezeSchemaMetadata(value.dialect) }
149
+ });
150
+ }
151
+ function assertSchemaExpression(expression, path, code = "invalid-default") {
152
+ if (!isSchemaExpression(expression)) throw new ColumnBehaviorError(code, "Schema behavior expressions must carry the deterministic schema-expression brand", path);
153
+ }
154
+ function assertDefaultDescriptor(value) {
155
+ if (!value || typeof value !== "object") throw new ColumnBehaviorError("invalid-default", "Column default metadata must be an object", "default");
156
+ if (value.kind === "external") return;
157
+ if (value.kind === "expression") {
158
+ assertSchemaExpression(value.expression, "default.expression");
159
+ return;
160
+ }
161
+ if (value.kind === "literal") {
162
+ assertCanonicalLiteral(value.value);
163
+ return;
164
+ }
165
+ throw new ColumnBehaviorError("invalid-default", "Unknown column default descriptor kind", "default.kind");
166
+ }
167
+ function assertGeneratedColumnDescriptor(value) {
168
+ if (!value || typeof value !== "object") throw new ColumnBehaviorError("invalid-generated-column", "Generated-column metadata must be an object", "generatedColumn");
169
+ if (value.kind === "external") return;
170
+ if (value.kind === "expression") {
171
+ assertSchemaExpression(value.expression, "generatedColumn.expression", "invalid-generated-column");
172
+ if (value.mode !== "stored" && value.mode !== "virtual") throw new ColumnBehaviorError("invalid-generated-column", "Generated-column mode must be \"stored\" or \"virtual\"", "generatedColumn.mode");
173
+ return;
174
+ }
175
+ throw new ColumnBehaviorError("invalid-generated-column", "Unknown generated-column descriptor kind", "generatedColumn.kind");
176
+ }
177
+ function assertIdentityDescriptor(value) {
178
+ if (!value || typeof value !== "object" || value.kind !== "identity" || value.generation !== "always" && value.generation !== "by-default") throw new ColumnBehaviorError("invalid-identity", "Identity metadata must use generation \"always\" or \"by-default\"", "identity.generation");
179
+ if (value.dialect !== void 0) {
180
+ if (typeof value.dialect !== "object" || value.dialect === null || typeof value.dialect.dialect !== "string" || value.dialect.dialect.length === 0) throw new ColumnBehaviorError("invalid-identity", "Identity dialect metadata must contain a non-empty dialect tag", "identity.dialect");
181
+ }
182
+ }
183
+ function assertCanonicalLiteral(value) {
184
+ if (!value || typeof value !== "object") throw new ColumnBehaviorError("invalid-default", "Literal defaults must contain a canonical literal node", "default.value");
185
+ switch (value.kind) {
186
+ case "null": return;
187
+ case "boolean":
188
+ if (typeof value.value === "boolean") return;
189
+ break;
190
+ case "string":
191
+ if (typeof value.value === "string") return;
192
+ break;
193
+ case "number":
194
+ if (typeof value.value === "string" && value.value.length > 0) return;
195
+ break;
196
+ case "bigint": if (/^-?(0|[1-9][0-9]*)$/.test(value.value)) return;
197
+ }
198
+ throw new ColumnBehaviorError("invalid-default", "Literal defaults must contain a valid canonical literal node", "default.value");
199
+ }
200
+ //#endregion
201
+ //#region src/schema/column.ts
202
+ /** Create an immutable portable physical storage descriptor. */
203
+ function portableStorage(type) {
204
+ return Object.freeze({
205
+ kind: "portable",
206
+ type
207
+ });
208
+ }
209
+ function nativeStorage(dialectOrOptions, type) {
210
+ const dialect = typeof dialectOrOptions === "string" ? dialectOrOptions : dialectOrOptions.dialect;
211
+ const declaration = typeof dialectOrOptions === "string" ? type : "type" in dialectOrOptions ? dialectOrOptions.type : dialectOrOptions.declaration;
212
+ return Object.freeze({
213
+ kind: "native",
214
+ dialect,
215
+ type: declaration
216
+ });
217
+ }
218
+ function narrowColumnType() {
219
+ return this;
220
+ }
221
+ function withPortableCast(definition, type) {
222
+ return Object.freeze({
223
+ ...definition,
224
+ castTarget: Object.freeze({
225
+ kind: "portable-cast",
226
+ type
227
+ })
228
+ });
229
+ }
230
+ function withPortableStorage(definition, type) {
231
+ return Object.freeze({
232
+ ...definition,
233
+ storage: portableStorage(type)
234
+ });
235
+ }
236
+ function column(options) {
237
+ return Object.freeze({
238
+ definitionKind: "column",
239
+ nullable: options?.nullable === true,
240
+ ...resolveColumnBehavior(options ?? {}),
241
+ sqlName: options?.sqlName,
242
+ storage: options?.storage ? Object.freeze({ ...options.storage }) : void 0,
243
+ ...options?.decode === void 0 && options?.codec === void 0 ? {} : { resultDecoder: options?.decode ?? options?.codec?.fromDriver },
244
+ ...options?.codec === void 0 ? {} : {
245
+ parameterEncoder: options.codec.toDriver,
246
+ columnCodec: Object.freeze({ ...options.codec })
247
+ },
248
+ $type: narrowColumnType,
249
+ castTarget: options?.castType ? Object.freeze({
250
+ kind: "named-cast",
251
+ typeName: options.castType
252
+ }) : void 0
253
+ });
254
+ }
255
+ /** Resolve the runtime result metadata carried by a column definition. */
256
+ function columnResultValue(definition) {
257
+ const storage = definition.storage;
258
+ const type = storage?.kind === "portable" && (storage.type === "boolean" || storage.type === "date" || storage.type === "timestamp" || storage.type === "json") ? storage.type : void 0;
259
+ return resultValue(type, definition.resultDecoder);
260
+ }
261
+ /** Apply a live column codec while preserving SQL NULL unchanged. */
262
+ function encodeColumnParameter(definition, value) {
263
+ return value === null || definition.parameterEncoder === void 0 ? value : definition.parameterEncoder(value);
264
+ }
265
+ function nativeColumn(storageOrDialect, typeOrOptions, maybeOptions) {
266
+ const storage = typeof storageOrDialect === "string" ? nativeStorage(storageOrDialect, typeOrOptions) : storageOrDialect;
267
+ return column({
268
+ ...typeof storageOrDialect === "string" ? maybeOptions : typeOrOptions,
269
+ storage
270
+ });
271
+ }
272
+ function nullable(definition) {
273
+ return Object.freeze({
274
+ ...definition,
275
+ nullable: true
276
+ });
277
+ }
278
+ function integer(options) {
279
+ return withPortableStorage(withPortableCast(column(options), "integer"), "integer");
280
+ }
281
+ function numeric(options) {
282
+ return withPortableStorage(withPortableCast(column(options), "decimal"), "numeric");
283
+ }
284
+ function text(options) {
285
+ return withPortableStorage(withPortableCast(column(options), "text"), "text");
286
+ }
287
+ function boolean(options) {
288
+ return withPortableStorage(withPortableCast(column(options), "boolean"), "boolean");
289
+ }
290
+ function date(options) {
291
+ return withPortableStorage(withPortableCast(column(options), "date"), "date");
292
+ }
293
+ function timestamp(options) {
294
+ return withPortableStorage(withPortableCast(column(options), "timestamp"), "timestamp");
295
+ }
296
+ function uuid(options) {
297
+ return withPortableStorage(withPortableCast(column(options), "uuid"), "uuid");
298
+ }
299
+ function json(options) {
300
+ return withPortableStorage(withPortableCast(column(options), "json"), "json");
301
+ }
302
+ function bigint(options) {
303
+ return withPortableStorage(withPortableCast(column(options), "bigint"), "bigint");
304
+ }
305
+ function binary(options) {
306
+ return withPortableStorage(withPortableCast(column(options), "binary"), "binary");
307
+ }
308
+ //#endregion
309
+ export { identityColumn as C, generatedColumn as S, uuid as _, columnResultValue as a, externalDefault as b, integer as c, nativeStorage as d, nullable as f, timestamp as g, text as h, column as i, json as l, portableStorage as m, binary as n, date as o, numeric as p, boolean as r, encodeColumnParameter as s, bigint as t, nativeColumn as u, ColumnBehaviorError as v, resolveColumnBehavior as w, externalGeneratedColumn as x, canonicalLiteral as y };
@@ -1,4 +1,4 @@
1
- import { A as SnapshotStorage, D as SnapshotLiteral, O as SnapshotNamingPolicy, T as SnapshotJsonValue, b as SnapshotGeneratedColumn, d as SnapshotDefault, f as SnapshotDiagnostic, g as SnapshotExpression, h as SnapshotDialectExtension, i as SchemaSnapshotInput, m as SnapshotDialect } from "./types-C0VkiwpR.mjs";
1
+ import { A as SnapshotStorage, D as SnapshotLiteral, O as SnapshotNamingPolicy, T as SnapshotJsonValue, b as SnapshotGeneratedColumn, d as SnapshotDefault, f as SnapshotDiagnostic, g as SnapshotExpression, h as SnapshotDialectExtension, i as SchemaSnapshotInput, m as SnapshotDialect } from "./types-DUe6eeI0.mjs";
2
2
  //#region src/snapshot/complete-types.d.ts
3
3
  /** The stable envelope tag shared by Snapshot v1 and the complete model. */
4
4
  declare const completeSchemaSnapshotFormat: "qubu-schema";
@@ -0,0 +1,208 @@
1
+ import { m as freezeSchemaMetadata, p as dialectMismatchDiagnostic, r as isColumnReference } from "./column-BzN8KFJa.mjs";
2
+ import { c as unsafeSchemaSql } from "./expressions-BCjc08zw.mjs";
3
+ //#region src/schema/indexes.ts
4
+ /**
5
+ * Validate portable and dialect-owned index facts for one target adapter. Unsupported features are
6
+ * reported as data so a serializer can aggregate diagnostics instead of failing during traversal
7
+ * with an opaque exception.
8
+ */
9
+ function validateIndexDialect(indexMetadata, dialect, path = ["index"]) {
10
+ const diagnostics = [];
11
+ const extension = indexMetadata.dialect;
12
+ if (extension !== void 0) {
13
+ const mismatch = dialectMismatchDiagnostic(extension, dialect, [...path, "dialect"]);
14
+ if (mismatch !== void 0) diagnostics.push(mismatch);
15
+ }
16
+ if ((dialect === "sqlite" || dialect === "mysql") && indexMetadata.includedColumns !== void 0 && indexMetadata.includedColumns.length > 0) diagnostics.push({
17
+ code: "unsupported-dialect-option",
18
+ message: `${dialect} indexes do not support included columns`,
19
+ path: [...path, "includedColumns"],
20
+ dialect
21
+ });
22
+ const mysqlKeyBlockSize = extension?.dialect === "mysql" ? extension.keyBlockSize : void 0;
23
+ if (mysqlKeyBlockSize !== void 0 && (!Number.isInteger(mysqlKeyBlockSize) || mysqlKeyBlockSize <= 0)) diagnostics.push({
24
+ code: "unsupported-dialect-option",
25
+ message: "MySQL index keyBlockSize must be a positive integer",
26
+ path: [
27
+ ...path,
28
+ "dialect",
29
+ "keyBlockSize"
30
+ ],
31
+ dialect
32
+ });
33
+ return Object.freeze(diagnostics);
34
+ }
35
+ /** Declare a portable column or expression index. */
36
+ function index(terms, options) {
37
+ const resolvedOptions = options ?? {};
38
+ const candidateKey = resolvedOptions.unique === true && resolvedOptions.where === void 0 && terms.every((term) => {
39
+ return ("orderKind" in term ? term.expression : term).expressionKind === "column";
40
+ });
41
+ return Object.freeze({
42
+ kind: "index",
43
+ terms: Object.freeze([...terms]),
44
+ unique: resolvedOptions.unique === true,
45
+ predicate: resolvedOptions.where,
46
+ ...resolvedOptions.include !== void 0 ? { includedColumns: Object.freeze([...resolvedOptions.include]) } : {},
47
+ ...resolvedOptions.physicalName !== void 0 ? { physicalName: resolvedOptions.physicalName } : {},
48
+ ...resolvedOptions.dialect !== void 0 ? { dialect: freezeSchemaMetadata(resolvedOptions.dialect) } : {},
49
+ candidateKey
50
+ });
51
+ }
52
+ //#endregion
53
+ //#region src/schema/constraints.ts
54
+ /**
55
+ * Validate one constraint against a schema adapter dialect. This is kept separate from construction
56
+ * because the same declaration can be inspected for more than one target dialect before a
57
+ * serializer is selected.
58
+ */
59
+ function validateConstraintDialect(constraint, dialect, path = ["constraint"]) {
60
+ const diagnostics = [];
61
+ const extension = constraint.dialect;
62
+ if (extension !== void 0) {
63
+ const mismatch = dialectMismatchDiagnostic(extension, dialect, [...path, "dialect"]);
64
+ if (mismatch !== void 0) diagnostics.push(mismatch);
65
+ if (extension.dialect === "postgresql" && "notValid" in extension && extension.notValid === true && (constraint.kind === "primary-key" || constraint.kind === "unique" || constraint.kind === "unique-constraint")) diagnostics.push({
66
+ code: "unsupported-dialect-option",
67
+ message: "PostgreSQL NOT VALID is not supported for key constraints",
68
+ path: [
69
+ ...path,
70
+ "dialect",
71
+ "notValid"
72
+ ],
73
+ dialect
74
+ });
75
+ if (extension.dialect === "sqlite" && "onConflict" in extension && extension.onConflict !== void 0 && constraint.kind === "foreign-key") diagnostics.push({
76
+ code: "unsupported-dialect-option",
77
+ message: "SQLite conflict policies do not apply to foreign keys",
78
+ path: [
79
+ ...path,
80
+ "dialect",
81
+ "onConflict"
82
+ ],
83
+ dialect
84
+ });
85
+ }
86
+ if (constraint.kind === "foreign-key" && constraint.match === "partial" && dialect === "mysql") diagnostics.push({
87
+ code: "unsupported-dialect-option",
88
+ message: "MySQL does not support MATCH PARTIAL foreign keys",
89
+ path: [...path, "match"],
90
+ dialect
91
+ });
92
+ if (constraint.kind === "foreign-key" && constraint.deferrable === true && dialect === "mysql") diagnostics.push({
93
+ code: "unsupported-dialect-option",
94
+ message: "MySQL foreign keys cannot be declared DEFERRABLE",
95
+ path: [...path, "deferrable"],
96
+ dialect
97
+ });
98
+ if (constraint.initially !== void 0 && constraint.deferrable !== true) diagnostics.push({
99
+ code: "unsupported-dialect-option",
100
+ message: "An initial constraint timing requires deferrable: true",
101
+ path: [...path, "initially"],
102
+ dialect
103
+ });
104
+ return Object.freeze(diagnostics);
105
+ }
106
+ function primaryKey(...columnsAndOptions) {
107
+ const last = columnsAndOptions.at(-1);
108
+ const options = last && typeof last === "object" && !("expressionKind" in last) ? last : void 0;
109
+ return freezeConstraint("primary-key", options ? columnsAndOptions.slice(0, -1) : columnsAndOptions, options);
110
+ }
111
+ function unique(...columnsAndOptions) {
112
+ const last = columnsAndOptions.at(-1);
113
+ const options = last && typeof last === "object" && !("expressionKind" in last) ? last : void 0;
114
+ return freezeConstraint("unique", options ? columnsAndOptions.slice(0, -1) : columnsAndOptions, options);
115
+ }
116
+ function uniqueConstraint(...columnsAndOptions) {
117
+ const last = columnsAndOptions.at(-1);
118
+ const options = last && typeof last === "object" && !("expressionKind" in last) ? last : void 0;
119
+ const columns = options ? columnsAndOptions.slice(0, -1) : columnsAndOptions;
120
+ const resolvedOptions = options ?? {};
121
+ return freezeConstraint("unique-constraint", columns, resolvedOptions, resolvedOptions.nulls ?? "distinct");
122
+ }
123
+ /** Pair a table with the exact columns targeted by a foreign key. */
124
+ function references(table, ...columns) {
125
+ return Object.freeze({
126
+ table,
127
+ columns: Object.freeze([...columns])
128
+ });
129
+ }
130
+ /** Declare a single-column or composite foreign key. */
131
+ function foreignKey(columns, target, options) {
132
+ return freezeConstraint("foreign-key", columns, options, target);
133
+ }
134
+ /**
135
+ * Reconstruct a foreign key proved by database catalog metadata.
136
+ *
137
+ * @remarks
138
+ * Use this helper for generated or introspection-owned declarations when one or both native SQL
139
+ * domains are unresolved. It accepts unresolved domains, but still rejects known domain
140
+ * mismatches, unequal tuple arity, and local columns from different sources. The enclosing
141
+ * `table()` declaration continues to verify target-column ownership and candidate-key metadata.
142
+ * Resolved targets also receive runtime shape, ownership, and arity checks. The returned value
143
+ * serializes as an ordinary foreign-key constraint.
144
+ */
145
+ function catalogForeignKey(columns, target, options) {
146
+ assertCatalogForeignKeyColumns(columns, "local");
147
+ return freezeConstraint("foreign-key", columns, options, validateCatalogForeignKeyTargetInput(target, columns.length));
148
+ }
149
+ /** Declare a boolean table invariant. */
150
+ function check(expression, options) {
151
+ return freezeConstraint("check", void 0, options, expression);
152
+ }
153
+ /**
154
+ * Reconstruct a boolean check from opaque SQL recovered from a database catalog.
155
+ *
156
+ * @remarks
157
+ * This helper records catalog origin as a narrow type-level proof. It gives the opaque expression
158
+ * the {@link SqlBoolean} semantic type without changing the ordinary {@link check} contract. Qubu
159
+ * does not parse or infer dependencies from the SQL. It preserves the text apart from normalizing
160
+ * line endings and retains the dialect tag in serialized schema metadata.
161
+ */
162
+ function catalogCheck(input, options) {
163
+ assertCatalogCheckSql(input);
164
+ return freezeConstraint("check", void 0, options, unsafeSchemaSql(input.dialect, input.sql));
165
+ }
166
+ function assertCatalogCheckSql(value) {
167
+ if (typeof value !== "object" || value === null) throw new TypeError("catalogCheck() requires dialect-tagged SQL data");
168
+ const input = value;
169
+ if (input.dialect !== "postgresql" && input.dialect !== "sqlite" && input.dialect !== "mysql") throw new TypeError(`catalogCheck() requires a supported catalog dialect, received "${String(input.dialect)}"`);
170
+ if (typeof input.sql !== "string" || input.sql.trim().length === 0) throw new TypeError("catalogCheck() requires non-empty SQL text");
171
+ }
172
+ function assertCatalogForeignKeyColumns(value, side) {
173
+ if (!Array.isArray(value) || value.length === 0) throw new TypeError(`catalogForeignKey() requires at least one ${side} column`);
174
+ if (!value.every(isColumnReference)) throw new TypeError(`catalogForeignKey() requires ${side} columns to be column references`);
175
+ }
176
+ function validateCatalogForeignKeyTargetInput(value, localArity) {
177
+ return typeof value === "function" ? () => validateCatalogForeignKeyTarget(value(), localArity) : validateCatalogForeignKeyTarget(value, localArity);
178
+ }
179
+ function validateCatalogForeignKeyTarget(value, localArity) {
180
+ if (typeof value !== "object" || value === null) throw new TypeError("catalogForeignKey() requires a foreign-key target");
181
+ const target = value;
182
+ assertCatalogForeignKeyColumns(target.columns, "target");
183
+ if (target.columns.length !== localArity) throw new TypeError(`catalogForeignKey() column arity differs: ${localArity} local and ${target.columns.length} target`);
184
+ const table = target.table;
185
+ if (typeof table !== "object" || table === null || typeof table.columns !== "object" || table.columns === null) throw new TypeError("catalogForeignKey() target must reference a table");
186
+ for (const column of target.columns) if (table.columns[column.fieldName] !== column) throw new TypeError(`catalogForeignKey() target column "${column.fieldName}" does not belong to its table`);
187
+ return target;
188
+ }
189
+ function freezeConstraint(kind, columns, options, extra) {
190
+ const value = { kind };
191
+ const optionValues = options;
192
+ if (columns !== void 0) value.columns = Object.freeze([...columns]);
193
+ if (kind === "check") value.expression = extra;
194
+ else if (kind === "foreign-key") value.target = extra;
195
+ else if (kind === "unique-constraint") value.nulls = extra;
196
+ if (optionValues?.physicalName !== void 0) value.physicalName = optionValues.physicalName;
197
+ if (optionValues?.dialect !== void 0) value.dialect = freezeSchemaMetadata(optionValues.dialect);
198
+ if (optionValues?.deferrable !== void 0) value.deferrable = optionValues.deferrable;
199
+ if (optionValues?.initially !== void 0) value.initially = optionValues.initially;
200
+ if (kind === "foreign-key") {
201
+ if (optionValues?.onUpdate !== void 0) value.onUpdate = optionValues.onUpdate;
202
+ if (optionValues?.onDelete !== void 0) value.onDelete = optionValues.onDelete;
203
+ if (optionValues?.match !== void 0) value.match = optionValues.match;
204
+ }
205
+ return Object.freeze(value);
206
+ }
207
+ //#endregion
208
+ export { primaryKey as a, uniqueConstraint as c, validateIndexDialect as d, foreignKey as i, validateConstraintDialect as l, catalogForeignKey as n, references as o, check as r, unique as s, catalogCheck as t, index as u };
package/dist/core.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as PaginationKind, $l as AggregateMeta, $u as SqlNumericLike, Au as RequiresOuterMetadataOf, B as CastTarget, Bl as withDialectCapability, Bu as isFragment, Ca as SelectClause, Cu as ProvidesOuterSourceMeta, Du as RenderFunction, Eu as RenderContext, Fu as SqlTypeOf, G as DialectJson, Ga as typedCall, Gu as SqlBinary, H as DialectCapability, Hu as sequence, Iu as SubqueryMeta, J as DialectRowLocking, Ju as SqlDecimal, K as DialectOptions, Ku as SqlBoolean, Ll as isExpression, Lu as VisibleDependenciesOf, Mu as RequiresOuterSourceMeta, No as typedCast, Nu as RequiresSourceMeta, Ol as Expression, Ou as RequiresCapabilityMeta, Pu as ResultMeta, Q as NamedCastTarget, Ql as AggregateDependenciesOf, Qu as SqlJson, Rl as makeExpression, Ru as WindowMeta, Sa as ClausePlacement, Su as ProvidesOuterOf, Tl as expressionFragment, Tu as QueryCardinality, U as DialectCastTypes, Uu as AnySqlType, V as Dialect, Vu as parenthesize, W as DialectExplain, Wu as SqlBigInt, X as ExplainRenderOptions, Xu as SqlEqualityCompatible, Y as ExplainFormat, Yu as SqlEqualityComparable, Z as JsonScalarKind, Zu as SqlInteger, _l as RenderedQuery, _u as MetadataOf, ad as SqlTimestamp, at as SchemaLiteralRenderer, au as DependenciesOf, bu as NullableSourcesOf, cd as SqlUuid, ct as resolveCastTarget, cu as FragmentMeta, du as GroupingMeta, ed as SqlOrderCompatible, et as PaginationPart, eu as AnyFragment, fu as HasAggregate, gl as RenderOptions, gu as InheritedMetadataOf, hl as RenderCapabilityValidation, hu as InheritedMetadata, id as SqlTextLike, it as RowLockWaitPolicy, iu as CardinalityOf, ju as RequiresOuterOf, ko as typedValue, ku as RequiresOf, lu as GroupingDependenciesOf, mu as HasWindow, nd as SqlSemanticType, nt as PortableCastType, nu as CapabilityMetadataOf, od as SqlTypeSatisfies, ot as assertDialectCapability, ou as ExpressionMeta, pu as HasSubquery, q as DialectPagination, qu as SqlDate, rd as SqlText, rt as RowLockMode, ru as CardinalityMeta, sd as SqlUnknown, st as createDialect, su as Fragment, td as SqlOrderable, tt as PortableCastTarget, tu as CapabilitiesOf, uu as GroupingKeysOf, vl as render, vu as NullabilityOf, wu as ProvidesSourceMeta, xu as OutputOf, yu as NullableSourceMeta, zl as markExpressionCategory, zu as fragment } from "./types-C0VkiwpR.mjs";
1
+ import { $ as PaginationKind, $u as SqlDecimal, Al as expressionFragment, Au as QueryCardinality, B as CastTarget, Bu as SqlTypeOf, Cl as render, Cu as NullabilityOf, Da as ClausePlacement, Du as ProvidesOuterOf, Eu as OutputOf, Fu as RequiresOuterMetadataOf, G as DialectJson, Gl as withDialectCapability, Gu as isFragment, H as DialectCapability, Hl as isExpression, Hu as VisibleDependenciesOf, Iu as RequiresOuterOf, J as DialectRowLocking, Ju as AnySqlType, K as DialectOptions, Ku as parenthesize, Lu as RequiresOuterSourceMeta, Mu as RenderFunction, Nl as Expression, Nu as RequiresCapabilityMeta, Oa as SelectClause, Ou as ProvidesOuterSourceMeta, Po as typedValue, Pu as RequiresOf, Q as NamedCastTarget, Qu as SqlDate, Ro as typedCast, Ru as RequiresSourceMeta, Sl as RenderedQuery, Su as MetadataOf, Tu as NullableSourcesOf, U as DialectCastTypes, Ul as makeExpression, Uu as WindowMeta, V as Dialect, Vu as SubqueryMeta, W as DialectExplain, Wl as markExpressionCategory, Wu as fragment, X as ExplainRenderOptions, Xa as typedCall, Xu as SqlBinary, Y as ExplainFormat, Yu as SqlBigInt, Z as JsonScalarKind, Zu as SqlBoolean, _u as HasAggregate, ad as SqlOrderCompatible, at as SchemaLiteralRenderer, au as AnyFragment, bl as RenderCapabilityValidation, bu as InheritedMetadata, cd as SqlText, ct as resolveCastTarget, cu as CardinalityMeta, dd as SqlTypeSatisfies, du as ExpressionMeta, ed as SqlEqualityComparable, et as PaginationPart, fd as SqlUnknown, fu as Fragment, gu as GroupingMeta, hu as GroupingKeysOf, id as SqlNumericLike, it as RowLockWaitPolicy, iu as AggregateMeta, ju as RenderContext, ku as ProvidesSourceMeta, ld as SqlTextLike, lu as CardinalityOf, mu as GroupingDependenciesOf, nd as SqlInteger, nt as PortableCastType, od as SqlOrderable, ot as assertDialectCapability, ou as CapabilitiesOf, pd as SqlUuid, pu as FragmentMeta, q as DialectPagination, qu as sequence, rd as SqlJson, rt as RowLockMode, ru as AggregateDependenciesOf, sd as SqlSemanticType, st as createDialect, su as CapabilityMetadataOf, td as SqlEqualityCompatible, tt as PortableCastTarget, ud as SqlTimestamp, uu as DependenciesOf, vu as HasSubquery, wu as NullableSourceMeta, xl as RenderOptions, xu as InheritedMetadataOf, yu as HasWindow, zu as ResultMeta } from "./types-DUe6eeI0.mjs";
2
2
  //#region src/core/primitives/compose.d.ts
3
3
  declare function commaSeparated<const TParts extends readonly AnyFragment[]>(parts: TParts): Fragment<InheritedMetadata<TParts[number]>>;
4
4
  declare function keyword<TPart extends AnyFragment | undefined>(value: string, part?: TPart): Fragment<TPart extends AnyFragment ? InheritedMetadata<TPart> : never>;
package/dist/core.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import { a as assertDialectCapability, o as createDialect, s as resolveCastTarget } from "./json-Db7XRD91.mjs";
2
- import { a as routineName, c as render, i as typedCall, s as typedCast, t as createClause } from "./types-CTENnDh9.mjs";
3
- import { B as isExpression, H as makeExpression, J as isFragment, K as withDialectCapability, W as markExpressionCategory, X as sequence, Y as parenthesize, a as qualifiedIdentifier, i as identifier, n as expressionFragment, q as fragment } from "./column-DmazTL67.mjs";
4
- import { a as parameter, r as typedValue } from "./value-BEEj_Ayd.mjs";
2
+ import { A as parenthesize, C as makeExpression, D as withDialectCapability, O as fragment, T as markExpressionCategory, a as qualifiedIdentifier, c as typedValue, i as identifier, j as sequence, k as isFragment, n as expressionFragment, u as parameter, x as isExpression } from "./column-BzN8KFJa.mjs";
3
+ import { a as routineName, c as render, i as typedCall, s as typedCast, t as createClause } from "./types-BLNRatG_.mjs";
5
4
  //#region src/core/primitives/compose.ts
6
5
  function commaSeparated(parts) {
7
6
  return sequence(parts, ", ");
@@ -0,0 +1,40 @@
1
+ //#region src/introspection/diagnostics.ts
2
+ /**
3
+ * Create one immutable diagnostic without interpreting catalog text or copying driver error details
4
+ * into the structured fields.
5
+ */
6
+ function createIntrospectionDiagnostic(diagnostic) {
7
+ return freezeDiagnostic(diagnostic);
8
+ }
9
+ /** Return whether a diagnostic list prevents strict introspection output. */
10
+ function hasIntrospectionErrors(diagnostics) {
11
+ return diagnostics.some((diagnostic) => diagnostic.severity === "error");
12
+ }
13
+ /** Error raised by a throwing introspection operation after collecting findings. */
14
+ var IntrospectionError = class extends Error {
15
+ name = "IntrospectionError";
16
+ diagnostics;
17
+ issues;
18
+ constructor(diagnostics) {
19
+ const frozenDiagnostics = Object.freeze(diagnostics.map((diagnostic) => freezeDiagnostic(diagnostic)));
20
+ super(frozenDiagnostics.map((diagnostic) => diagnostic.message).join("\n"));
21
+ this.diagnostics = frozenDiagnostics;
22
+ this.issues = frozenDiagnostics;
23
+ }
24
+ };
25
+ function freezeDiagnostic(diagnostic) {
26
+ return Object.freeze({
27
+ ...diagnostic,
28
+ path: Object.freeze([...diagnostic.path]),
29
+ physicalReference: diagnostic.physicalReference ? freezeReference(diagnostic.physicalReference) : void 0,
30
+ relatedReferences: diagnostic.relatedReferences ? Object.freeze(diagnostic.relatedReferences.map((reference) => freezeReference(reference))) : void 0
31
+ });
32
+ }
33
+ function freezeReference(reference) {
34
+ return Object.freeze({
35
+ ...reference,
36
+ catalog: reference.catalog ? Object.freeze({ ...reference.catalog }) : void 0
37
+ });
38
+ }
39
+ //#endregion
40
+ export { createIntrospectionDiagnostic as n, hasIntrospectionErrors as r, IntrospectionError as t };
package/dist/diff.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as SnapshotJsonValue, m as SnapshotDialect, n as SchemaSnapshot } from "./types-C0VkiwpR.mjs";
2
- import { S as CompleteSnapshotObjectKind, t as CompleteSchemaSnapshot } from "./complete-types-CY0KbzNw.mjs";
1
+ import { T as SnapshotJsonValue, m as SnapshotDialect, n as SchemaSnapshot } from "./types-DUe6eeI0.mjs";
2
+ import { S as CompleteSnapshotObjectKind, t as CompleteSchemaSnapshot } from "./complete-types-CNMWBWap.mjs";
3
3
  //#region src/diff/types.d.ts
4
4
  /** Object families understood by the snapshot diff engine. */
5
5
  type SnapshotDiffObjectKind = CompleteSnapshotObjectKind;