qubu 0.6.0 → 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 (65) 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-r1Y4ivwt.mjs → column-BzN8KFJa.mjs} +39 -2
  5. package/dist/{column-Da37jYSD.mjs → column-CFvSbil0.mjs} +1 -1
  6. package/dist/{complete-types-CY0KbzNw.d.mts → complete-types-CNMWBWap.d.mts} +1 -1
  7. package/dist/{constraints-YGyNPQ_z.mjs → constraints-DM_tarXc.mjs} +2 -2
  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-B2rZf3-2.d.mts → index-CGui70hi.d.mts} +2 -2
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +58 -15
  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-DZQ85f1t.mjs → on-conflict-CnaY5qso.mjs} +76 -4
  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-CxnLCqZQ.mjs → relational-DSAJ-l58.mjs} +1 -2
  32. package/dist/schema.d.mts +1 -1
  33. package/dist/schema.mjs +7 -6
  34. package/dist/{serialize-BN07IK0v.mjs → serialize-CE-gw5_s.mjs} +3 -3
  35. package/dist/{serialize-CEIIlWhC.d.mts → serialize-OvXCLzjm.d.mts} +1 -1
  36. package/dist/snapshot/mysql.d.mts +2 -2
  37. package/dist/snapshot/mysql.mjs +28 -28
  38. package/dist/snapshot/postgres.d.mts +4 -4
  39. package/dist/snapshot/postgres.mjs +21 -21
  40. package/dist/snapshot/sqlite.d.mts +4 -4
  41. package/dist/snapshot/sqlite.mjs +27 -27
  42. package/dist/{snapshot-Xam8-q0j.mjs → snapshot-DgsOhf_8.mjs} +4 -42
  43. package/dist/snapshot.d.mts +4 -4
  44. package/dist/snapshot.mjs +1 -1
  45. package/dist/{source-SqrKWjFJ.mjs → source-BDuUXmAk.mjs} +2 -2
  46. package/dist/sqlite.d.mts +1 -1
  47. package/dist/sqlite.mjs +6 -6
  48. package/dist/{table-BwflqeAj.mjs → table-C1QGNe4P.mjs} +3 -3
  49. package/dist/{types-CTCqtFlS.d.mts → types-BEn0N_al.d.mts} +1 -1
  50. package/dist/{types-BIJsj2fJ.mjs → types-BLNRatG_.mjs} +2 -4
  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 +50 -12
  57. package/docs/migrations/operations.md +20 -6
  58. package/docs/reference/supported-surface.md +17 -6
  59. package/docs/schema/code-generation.md +3 -2
  60. package/docs/schema/introspection.md +3 -2
  61. package/docs/sql-semantic-types.md +8 -0
  62. package/package.json +13 -1
  63. package/dist/registry-BRcUuazJ.mjs +0 -256
  64. package/dist/standard-DfcZEVOj.mjs +0 -12
  65. package/dist/value-D14I_XgL.mjs +0 -29
@@ -0,0 +1,986 @@
1
+ import { n as createIntrospectionDiagnostic } from "../diagnostics-I9vVtXkc.mjs";
2
+ //#region src/introspection/sqlite.ts
3
+ const sqliteServerQuery = `SELECT sqlite_version() AS version, sqlite_source_id() AS source_id`;
4
+ const sqliteDatabaseListQuery = `
5
+ SELECT seq, name, file
6
+ FROM pragma_database_list()
7
+ ORDER BY seq
8
+ `;
9
+ const sqliteSchemaQuery = `
10
+ SELECT type, name, tbl_name, sql
11
+ FROM main.sqlite_schema
12
+ WHERE name NOT LIKE 'sqlite_%'
13
+ ORDER BY type, name
14
+ `;
15
+ const sqliteTempSchemaQuery = `
16
+ SELECT type, name, tbl_name, sql
17
+ FROM temp.sqlite_schema
18
+ WHERE name NOT LIKE 'sqlite_%'
19
+ ORDER BY type, name
20
+ `;
21
+ const sqliteTableListQuery = `
22
+ SELECT schema, name, type, ncol, wr, strict
23
+ FROM pragma_table_list
24
+ WHERE schema = ? AND name NOT LIKE 'sqlite_%'
25
+ ORDER BY name
26
+ `;
27
+ const sqliteTableInfoQuery = `
28
+ SELECT cid, name, type, "notnull" AS not_null, dflt_value, pk, hidden
29
+ FROM pragma_table_xinfo(?, ?)
30
+ ORDER BY cid
31
+ `;
32
+ const sqliteIndexListQuery = `
33
+ SELECT seq, name, "unique" AS unique_index, origin, partial
34
+ FROM pragma_index_list(?, ?)
35
+ ORDER BY seq
36
+ `;
37
+ const sqliteIndexInfoQuery = `
38
+ SELECT seqno, cid, name, "desc" AS descending, coll, key
39
+ FROM pragma_index_xinfo(?, ?)
40
+ ORDER BY seqno
41
+ `;
42
+ const sqliteForeignKeyQuery = `
43
+ SELECT id, seq, "table" AS target_table, "from" AS source_column,
44
+ "to" AS target_column, on_update, on_delete, match
45
+ FROM pragma_foreign_key_list(?, ?)
46
+ ORDER BY id, seq
47
+ `;
48
+ /** Read the selected SQLite database namespace into the normalized catalog. */
49
+ async function readCatalog(connection, options) {
50
+ const diagnostics = [];
51
+ if (connection.dialect !== "sqlite") {
52
+ diagnostics.push(createIntrospectionDiagnostic({
53
+ severity: "error",
54
+ code: "dialect-mismatch",
55
+ message: "SQLite catalog reading requires a SQLite CatalogConnection",
56
+ path: ["connection", "dialect"]
57
+ }));
58
+ return emptyCatalog(options.namespace, diagnostics);
59
+ }
60
+ const serverRows = await query(connection, sqliteServerQuery, [], options, diagnostics, "server");
61
+ const server = serverInfo(serverRows[0], diagnostics);
62
+ const databaseRows = await query(connection, sqliteDatabaseListQuery, [], options, diagnostics, "database-list");
63
+ const databaseNames = databaseRows.map((row) => text(row.name)).filter((name) => name !== void 0);
64
+ if (databaseNames.length > 0 && !databaseNames.includes(options.namespace)) diagnostics.push(createIntrospectionDiagnostic({
65
+ severity: "error",
66
+ code: "missing-catalog-row",
67
+ message: `SQLite database ${options.namespace} is not attached to the selected connection`,
68
+ path: ["namespace", options.namespace],
69
+ remediation: "Attach the database before starting introspection."
70
+ }));
71
+ const schemaRows = options.namespace === "main" || options.namespace === "temp" ? await query(connection, options.namespace === "temp" ? sqliteTempSchemaQuery : sqliteSchemaQuery, [], options, diagnostics, "schema") : [];
72
+ if (options.namespace !== "main" && options.namespace !== "temp" && databaseNames.includes(options.namespace)) diagnostics.push(createIntrospectionDiagnostic({
73
+ severity: "warning",
74
+ code: "partial-result",
75
+ message: `SQLite attached database ${options.namespace} exposes table PRAGMAs but its schema SQL is outside the fixed main/temp catalog statements`,
76
+ path: [
77
+ "namespace",
78
+ options.namespace,
79
+ "schema"
80
+ ],
81
+ remediation: "Use a driver adapter that exposes the attached schema through a fixed statement before relying on generated SQL."
82
+ }));
83
+ const tableRows = await query(connection, sqliteTableListQuery, [options.namespace], options, diagnostics, "table-list");
84
+ const tableSql = new Map(schemaRows.map((row) => [text(row.name), text(row.sql)]).filter((entry) => entry[0] !== void 0));
85
+ const tables = tableRows.filter((row) => normalizeType(row.type) === "table").map((row) => table(row, tableSql.get(text(row.name) ?? "") ?? void 0, options.namespace));
86
+ const deferredObjects = [];
87
+ const opaqueObjects = [];
88
+ for (const row of tableRows) {
89
+ const type = normalizeType(row.type);
90
+ if (type !== "virtual" && type !== "shadow") continue;
91
+ const physicalName = text(row.name) ?? "unnamed_object";
92
+ deferredObjects.push(deferred(type === "virtual" ? "virtual-table" : "shadow-table", physicalName, tableSql.get(physicalName), options.namespace));
93
+ diagnostics.push(createIntrospectionDiagnostic({
94
+ severity: "warning",
95
+ code: "unmodeled-object",
96
+ message: `SQLite ${type} table ${physicalName} is retained as a deferred object`,
97
+ path: ["deferredObjects", physicalName],
98
+ physicalReference: reference("deferred-object", physicalName, options.namespace, "pragma_table_list", "name"),
99
+ remediation: "Inspect the deferred record before using it as migration input."
100
+ }));
101
+ }
102
+ for (const row of databaseRows) {
103
+ const name = text(row.name);
104
+ if (!name || name === options.namespace || name === "main" || name === "temp") continue;
105
+ const boundary = attachedDatabaseObject(row, options.namespace);
106
+ opaqueObjects.push(boundary);
107
+ diagnostics.push(createIntrospectionDiagnostic({
108
+ severity: "info",
109
+ code: "partial-result",
110
+ message: `Attached SQLite database ${name} is outside the selected namespace`,
111
+ path: [
112
+ "namespace",
113
+ "attached",
114
+ name
115
+ ],
116
+ physicalReference: boundary.reference,
117
+ remediation: "Run a separate catalog read with this database name to inspect it."
118
+ }));
119
+ }
120
+ const views = [];
121
+ for (const row of tableRows.filter((row) => normalizeType(row.type) === "view")) {
122
+ const physicalName = text(row.name) ?? "unnamed_view";
123
+ const view = mapView(row, tableSql.get(physicalName), options.namespace, diagnostics);
124
+ if (view.kind === "deferred-object") deferredObjects.push(view);
125
+ else views.push(view);
126
+ }
127
+ const relationReferences = /* @__PURE__ */ new Map();
128
+ for (const table of tables) relationReferences.set(table.physicalName, {
129
+ kind: "table",
130
+ id: table.id
131
+ });
132
+ for (const view of views) relationReferences.set(view.physicalName, {
133
+ kind: view.kind,
134
+ id: view.id
135
+ });
136
+ const triggers = [];
137
+ for (const currentTable of tables) {
138
+ const tableName = currentTable.physicalName;
139
+ const rows = await query(connection, sqliteTableInfoQuery, [tableName, options.namespace], options, diagnostics, `table-xinfo:${tableName}`);
140
+ const sqlText = tableSql.get(tableName);
141
+ const rowidPrimaryKey = rows.filter((row) => (number(row.pk) ?? 0) > 0).length === 1;
142
+ const columns = rows.filter((row) => number(row.hidden) !== 1).map((row) => column(row, currentTable, options.namespace, sqlText, rowidPrimaryKey, diagnostics));
143
+ currentTable.columns = columns;
144
+ currentTable.constraints = tableConstraints(currentTable, rows, columns, sqlText, options.namespace);
145
+ const indexRows = await query(connection, sqliteIndexListQuery, [tableName, options.namespace], options, diagnostics, `index-list:${tableName}`);
146
+ const mappedIndexes = [];
147
+ const mappedConstraints = [...currentTable.constraints];
148
+ for (const indexRow of indexRows) {
149
+ const indexName = text(indexRow.name);
150
+ if (!indexName || indexName.startsWith("sqlite_autoindex_") && text(indexRow.origin)?.toLowerCase() !== "u") continue;
151
+ const index = mapIndex(currentTable, indexRow, await query(connection, sqliteIndexInfoQuery, [indexName, options.namespace], options, diagnostics, `index-info:${indexName}`), text(indexRow.origin)?.toLowerCase() === "u" ? sqlText : tableSql.get(indexName), options.namespace, diagnostics, opaqueObjects);
152
+ if (!index) continue;
153
+ if (index.kind === "index") mappedIndexes.push(index);
154
+ else mappedConstraints.push(index);
155
+ }
156
+ const foreignRows = await query(connection, sqliteForeignKeyQuery, [tableName, options.namespace], options, diagnostics, `foreign-key:${tableName}`);
157
+ mappedConstraints.push(...foreignKeys(currentTable, foreignRows, options.namespace));
158
+ currentTable.indexes = mappedIndexes;
159
+ currentTable.constraints = mappedConstraints;
160
+ }
161
+ for (const view of views) view.columns = (await query(connection, sqliteTableInfoQuery, [view.physicalName, options.namespace], options, diagnostics, `view-xinfo:${view.physicalName}`)).filter((row) => number(row.hidden) !== 1).map((row) => column(row, view, options.namespace, void 0, false, diagnostics));
162
+ for (const row of schemaRows.filter((row) => normalizeType(row.type) === "trigger")) {
163
+ const trigger = mapTrigger(row, options.namespace, relationReferences, diagnostics);
164
+ if (trigger.kind === "deferred-object") deferredObjects.push(trigger);
165
+ else triggers.push(trigger);
166
+ }
167
+ for (const row of schemaRows) {
168
+ const type = normalizeType(row.type);
169
+ if (type === "table" || type === "view" || type === "trigger" || type === "index") continue;
170
+ const physicalName = text(row.name) ?? "unnamed_object";
171
+ opaqueObjects.push(opaqueSchemaObject(row, options.namespace, diagnostics));
172
+ diagnostics.push(createIntrospectionDiagnostic({
173
+ severity: "warning",
174
+ code: "unmodeled-object",
175
+ message: `SQLite schema object ${physicalName} (${type || "unknown"}) is retained as opaque data`,
176
+ path: ["opaqueObjects", physicalName],
177
+ physicalReference: reference("opaque-object", physicalName, options.namespace, "sqlite_schema", "name")
178
+ }));
179
+ }
180
+ const visibility = databaseRows.length > 0 && options.namespace !== "main" && options.namespace !== "temp" ? "limited" : server.capabilities.visibility;
181
+ const capabilities = {
182
+ generatedColumns: server.capabilities.generatedColumns,
183
+ identityMetadata: server.capabilities.identityMetadata,
184
+ checkConstraints: server.capabilities.checkConstraints,
185
+ checkConstraintEnforcement: server.capabilities.checkConstraintEnforcement,
186
+ expressionDecompilation: server.capabilities.expressionDecompilation,
187
+ indexExpressions: server.capabilities.indexExpressions,
188
+ indexPredicates: server.capabilities.indexPredicates,
189
+ indexIncludedColumns: server.capabilities.indexIncludedColumns,
190
+ namespaces: server.capabilities.namespaces,
191
+ visibility
192
+ };
193
+ const serverCapabilities = {
194
+ ...server.capabilities,
195
+ attachedDatabases: true,
196
+ views: true,
197
+ triggers: true,
198
+ virtualTables: true,
199
+ shadowTables: true,
200
+ comments: false,
201
+ ownership: false,
202
+ typedExtensions: true,
203
+ affinityFacts: true,
204
+ generatedSql: true,
205
+ selectedNamespace: options.namespace,
206
+ visibility
207
+ };
208
+ return Object.freeze({
209
+ dialect: "sqlite",
210
+ server: {
211
+ ...server,
212
+ capabilities: serverCapabilities
213
+ },
214
+ namespace: {
215
+ kind: "sqlite-database",
216
+ name: options.namespace,
217
+ reference: reference("namespace", options.namespace, options.namespace, "sqlite_schema", "name"),
218
+ dialect: extension({
219
+ selectedNamespace: options.namespace,
220
+ sourceIdAvailable: serverSourceIdAvailable(serverRows[0]),
221
+ views: true,
222
+ triggers: true,
223
+ virtualTables: true,
224
+ shadowTables: true,
225
+ comments: false,
226
+ ownership: false,
227
+ typedExtensions: true,
228
+ affinityFacts: true,
229
+ generatedSql: true,
230
+ visibility,
231
+ attachedDatabases: databaseNames.filter((name) => name !== options.namespace)
232
+ })
233
+ },
234
+ tables: Object.freeze(tables),
235
+ views: Object.freeze(views),
236
+ triggers: Object.freeze(triggers),
237
+ deferredObjects: Object.freeze(deferredObjects),
238
+ opaqueObjects: Object.freeze(opaqueObjects),
239
+ capabilities,
240
+ diagnostics: Object.freeze(diagnostics)
241
+ });
242
+ }
243
+ async function query(connection, textValue, parameters, options, diagnostics, operation) {
244
+ try {
245
+ return await connection.query({
246
+ text: textValue,
247
+ parameters
248
+ }, { signal: options.signal });
249
+ } catch {
250
+ diagnostics.push(createIntrospectionDiagnostic({
251
+ severity: "error",
252
+ code: "query-failed",
253
+ message: `SQLite catalog query failed while reading ${operation}`,
254
+ path: [operation],
255
+ remediation: "Check SQLite metadata visibility and the selected database."
256
+ }));
257
+ return [];
258
+ }
259
+ }
260
+ function serverInfo(row, diagnostics) {
261
+ const rawVersion = text(row?.version) ?? "unknown";
262
+ const parts = rawVersion.split(".").map((item) => Number(item));
263
+ const supported = parts.length >= 2 && parts[0] === 3 && parts[1] >= 37;
264
+ if (!supported) diagnostics.push(createIntrospectionDiagnostic({
265
+ severity: "error",
266
+ code: "unsupported-server",
267
+ message: "SQLite introspection requires SQLite 3.37 or newer",
268
+ path: ["server", "version"],
269
+ remediation: "Use SQLite 3.37+ or provide a compatible adapter capability set."
270
+ }));
271
+ return {
272
+ product: "sqlite",
273
+ rawVersion,
274
+ parsedVersion: Number.isFinite(parts[0]) ? {
275
+ major: parts[0],
276
+ minor: parts[1],
277
+ patch: parts[2]
278
+ } : void 0,
279
+ capabilities: {
280
+ generatedColumns: supported,
281
+ identityMetadata: true,
282
+ checkConstraints: true,
283
+ checkConstraintEnforcement: "enforced",
284
+ expressionDecompilation: false,
285
+ indexExpressions: true,
286
+ indexPredicates: true,
287
+ indexIncludedColumns: false,
288
+ namespaces: false,
289
+ visibility: "complete",
290
+ sourceIdAvailable: text(row?.source_id) !== void 0
291
+ }
292
+ };
293
+ }
294
+ function serverSourceIdAvailable(row) {
295
+ return text(row?.source_id) !== void 0;
296
+ }
297
+ function normalizeType(value) {
298
+ return text(value)?.trim().toLowerCase() ?? "";
299
+ }
300
+ function mapView(row, sqlText, namespace, diagnostics) {
301
+ const physicalName = text(row.name) ?? "unnamed_view";
302
+ const physicalReference = reference("view", physicalName, namespace, "sqlite_schema", "name");
303
+ const definition = viewDefinition(sqlText);
304
+ if (!definition) {
305
+ diagnostics.push(createIntrospectionDiagnostic({
306
+ severity: "error",
307
+ code: "expression-parse-failed",
308
+ message: `SQLite view ${physicalName} has no recoverable SELECT definition`,
309
+ path: [
310
+ "views",
311
+ physicalName,
312
+ "definition"
313
+ ],
314
+ physicalReference,
315
+ remediation: "Preserve the CREATE VIEW SQL returned by sqlite_schema."
316
+ }));
317
+ return deferred("view", physicalName, sqlText, namespace);
318
+ }
319
+ return {
320
+ kind: "view",
321
+ id: stableId(physicalName),
322
+ identitySource: "physical-name",
323
+ physicalName,
324
+ columns: [],
325
+ definition: sql(definition, namespace, {
326
+ kind: "view",
327
+ physicalName,
328
+ reference: physicalReference
329
+ }, physicalName),
330
+ reference: physicalReference,
331
+ provenance: {
332
+ kind: "create-sql",
333
+ dialect: "sqlite",
334
+ reference: physicalReference
335
+ },
336
+ dialect: extension({ objectKind: "view" })
337
+ };
338
+ }
339
+ function viewDefinition(sqlText) {
340
+ if (!sqlText) return;
341
+ return sqlText.match(/\bAS\b([\s\S]*)$/i)?.[1]?.trim().replace(/;\s*$/, "") || void 0;
342
+ }
343
+ function attachedDatabaseObject(row, selectedNamespace) {
344
+ const physicalName = text(row.name) ?? "unnamed_database";
345
+ const physicalReference = reference("opaque-object", physicalName, selectedNamespace, "pragma_database_list", "name");
346
+ return {
347
+ kind: "opaque-object",
348
+ id: stableId(`attached:${physicalName}`),
349
+ identitySource: "physical-name",
350
+ objectKind: "attached-database",
351
+ physicalName,
352
+ data: {
353
+ ...number(row.seq) === void 0 ? {} : { sequence: number(row.seq) },
354
+ ...text(row.file) === void 0 ? {} : { file: text(row.file) },
355
+ selected: false
356
+ },
357
+ reference: physicalReference,
358
+ provenance: {
359
+ kind: "catalog",
360
+ dialect: "sqlite",
361
+ reference: physicalReference
362
+ },
363
+ dialect: extension({ selectedNamespace })
364
+ };
365
+ }
366
+ function opaqueSchemaObject(row, namespace, _diagnostics) {
367
+ const physicalName = text(row.name) ?? "unnamed_object";
368
+ const type = normalizeType(row.type) || "unknown";
369
+ const physicalReference = reference("opaque-object", physicalName, namespace, "sqlite_schema", "name");
370
+ const sqlText = text(row.sql);
371
+ return {
372
+ kind: "opaque-object",
373
+ id: stableId(`opaque:${type}:${physicalName}`),
374
+ identitySource: "physical-name",
375
+ objectKind: type,
376
+ physicalName,
377
+ data: {
378
+ type,
379
+ ...text(row.tbl_name) === void 0 ? {} : { tableName: text(row.tbl_name) }
380
+ },
381
+ ...sqlText === void 0 ? {} : { sql: {
382
+ kind: "sql",
383
+ dialect: "sqlite",
384
+ text: sqlText,
385
+ provenance: {
386
+ kind: "create-sql",
387
+ dialect: "sqlite",
388
+ reference: physicalReference
389
+ }
390
+ } },
391
+ reference: physicalReference,
392
+ provenance: {
393
+ kind: "catalog",
394
+ dialect: "sqlite",
395
+ reference: physicalReference
396
+ },
397
+ dialect: extension({ objectKind: type })
398
+ };
399
+ }
400
+ function mapTrigger(row, namespace, relations, diagnostics) {
401
+ const physicalName = text(row.name) ?? "unnamed_trigger";
402
+ const sqlText = text(row.sql);
403
+ const physicalReference = reference("trigger", physicalName, namespace, "sqlite_schema", "name");
404
+ const onMatch = sqlText?.match(/\bON\s+("(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|[A-Za-z_][A-Za-z0-9_$]*)/i);
405
+ const targetName = unquoteIdentifier(onMatch?.[1]) ?? text(row.tbl_name);
406
+ const target = targetName === void 0 ? void 0 : relations.get(targetName);
407
+ const beginIndex = sqlText?.search(/\bBEGIN\b/i) ?? -1;
408
+ const header = sqlText === void 0 || beginIndex < 0 ? void 0 : sqlText.slice(0, beginIndex);
409
+ const timing = triggerTiming(header);
410
+ const events = triggerEvents(header);
411
+ if (!sqlText || !target || !header || beginIndex < 0) {
412
+ diagnostics.push(createIntrospectionDiagnostic({
413
+ severity: "error",
414
+ code: "unresolved-reference",
415
+ message: `SQLite trigger ${physicalName} does not have a recoverable body or target`,
416
+ path: ["triggers", physicalName],
417
+ physicalReference,
418
+ remediation: "Retain the CREATE TRIGGER SQL and inspect the trigger after its target is visible."
419
+ }));
420
+ return deferred("trigger", physicalName, sqlText, namespace);
421
+ }
422
+ if (events.length === 0) diagnostics.push(createIntrospectionDiagnostic({
423
+ severity: "warning",
424
+ code: "unsupported-feature",
425
+ message: `SQLite trigger ${physicalName} has no recognized event`,
426
+ path: [
427
+ "triggers",
428
+ physicalName,
429
+ "events"
430
+ ],
431
+ physicalReference
432
+ }));
433
+ const bodyText = sqlText.slice(beginIndex + 5).replace(/END\s*;?\s*$/i, "").trim();
434
+ const condition = triggerCondition(sqlText, onMatch?.index, beginIndex);
435
+ return {
436
+ kind: "trigger",
437
+ id: stableId(physicalName),
438
+ identitySource: "physical-name",
439
+ physicalName,
440
+ table: target,
441
+ timing,
442
+ events,
443
+ orientation: /\bFOR\s+EACH\s+ROW\b/i.test(header) ? "row" : void 0,
444
+ ...condition === void 0 ? {} : { condition: sql(condition, namespace, {
445
+ kind: target.kind,
446
+ physicalName: target.id,
447
+ reference: physicalReference
448
+ }, physicalName) },
449
+ body: sql(bodyText || sqlText, namespace, {
450
+ kind: "trigger",
451
+ physicalName,
452
+ reference: physicalReference
453
+ }, physicalName),
454
+ reference: physicalReference,
455
+ provenance: {
456
+ kind: "create-sql",
457
+ dialect: "sqlite",
458
+ reference: physicalReference
459
+ },
460
+ dialect: extension({
461
+ objectKind: "trigger",
462
+ ...sqlText === void 0 ? {} : { rawSql: sqlText }
463
+ })
464
+ };
465
+ }
466
+ function triggerTiming(header) {
467
+ const value = header?.match(/\b(INSTEAD\s+OF|BEFORE|AFTER)\b/i)?.[1];
468
+ return value?.toLowerCase() === "before" ? "before" : value?.toLowerCase() === "after" ? "after" : value?.toLowerCase() === "instead of" ? "instead-of" : "unknown";
469
+ }
470
+ function triggerEvents(header) {
471
+ const values = header?.match(/\b(INSERT|UPDATE|DELETE)\b/gi) ?? [];
472
+ return [...new Set(values.map((value) => value.toLowerCase()))];
473
+ }
474
+ function triggerCondition(sqlText, _onIndex, beginIndex) {
475
+ return sqlText.slice(0, beginIndex).match(/\bWHEN\s+([\s\S]+)$/i)?.[1]?.trim();
476
+ }
477
+ function unquoteIdentifier(value) {
478
+ if (!value) return;
479
+ const trimmed = value.trim();
480
+ if (trimmed.length < 2) return trimmed;
481
+ if (trimmed.startsWith("\"") && trimmed.endsWith("\"") || trimmed.startsWith("`") && trimmed.endsWith("`")) return trimmed.slice(1, -1).replace(/(""|``)/g, (match) => match[0]);
482
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) return trimmed.slice(1, -1);
483
+ return trimmed;
484
+ }
485
+ function affinity(type) {
486
+ const normalized = type.trim().toUpperCase();
487
+ if (/INT/.test(normalized)) return "INTEGER";
488
+ if (/CHAR|CLOB|TEXT/.test(normalized)) return "TEXT";
489
+ if (/REAL|FLOA|DOUB/.test(normalized)) return "REAL";
490
+ if (normalized === "" || normalized === "BLOB") return "BLOB";
491
+ return "NUMERIC";
492
+ }
493
+ function extension(data) {
494
+ return {
495
+ dialect: "sqlite",
496
+ version: 1,
497
+ data
498
+ };
499
+ }
500
+ function indexExpressionFor(sqlText, position) {
501
+ if (!sqlText) return;
502
+ const open = sqlText.indexOf("(", sqlText.search(/\bON\b/i));
503
+ if (open < 0) return;
504
+ const close = matchingParen(sqlText, open);
505
+ if (close < 0) return;
506
+ const term = splitSqlList(sqlText.slice(open + 1, close))[position]?.trim();
507
+ return term && !isSimpleIdentifier(term) ? term : void 0;
508
+ }
509
+ function opaqueIndexExpression(table, indexName, position, info, sqlText, namespace) {
510
+ const physicalReference = reference("opaque-object", `${indexName}:${position}`, namespace, "pragma_index_xinfo", "seqno", position);
511
+ return {
512
+ kind: "opaque-object",
513
+ id: stableId(`index-expression:${table.physicalName}:${indexName}:${position}`),
514
+ identitySource: "deterministic-fallback",
515
+ objectKind: "index-expression-term",
516
+ physicalName: `${indexName}:${position}`,
517
+ data: {
518
+ index: indexName,
519
+ position,
520
+ cid: number(info.cid) ?? -2
521
+ },
522
+ ...sqlText === void 0 ? {} : { sql: sql(sqlText, namespace, table, indexName) },
523
+ reference: physicalReference,
524
+ provenance: {
525
+ kind: "catalog",
526
+ dialect: "sqlite",
527
+ reference: physicalReference
528
+ },
529
+ dialect: extension({ objectKind: "index-expression-term" })
530
+ };
531
+ }
532
+ function matchingParen(source, open) {
533
+ let depth = 0;
534
+ let quote;
535
+ for (let index = open; index < source.length; index++) {
536
+ const character = source[index];
537
+ if (quote === "single") {
538
+ if (character === "'" && source[index + 1] === "'") index++;
539
+ else if (character === "'") quote = void 0;
540
+ continue;
541
+ }
542
+ if (quote === "double") {
543
+ if (character === "\"" && source[index + 1] === "\"") index++;
544
+ else if (character === "\"") quote = void 0;
545
+ continue;
546
+ }
547
+ if (quote === "backtick") {
548
+ if (character === "`") quote = void 0;
549
+ continue;
550
+ }
551
+ if (quote === "bracket") {
552
+ if (character === "]") quote = void 0;
553
+ continue;
554
+ }
555
+ if (character === "'") quote = "single";
556
+ else if (character === "\"") quote = "double";
557
+ else if (character === "`") quote = "backtick";
558
+ else if (character === "[") quote = "bracket";
559
+ else if (character === "(") depth++;
560
+ else if (character === ")" && --depth === 0) return index;
561
+ }
562
+ return -1;
563
+ }
564
+ function splitSqlList(source) {
565
+ const values = [];
566
+ let start = 0;
567
+ let depth = 0;
568
+ let quote;
569
+ for (let index = 0; index < source.length; index++) {
570
+ const character = source[index];
571
+ if (quote === "single") {
572
+ if (character === "'" && source[index + 1] === "'") index++;
573
+ else if (character === "'") quote = void 0;
574
+ continue;
575
+ }
576
+ if (quote === "double") {
577
+ if (character === "\"" && source[index + 1] === "\"") index++;
578
+ else if (character === "\"") quote = void 0;
579
+ continue;
580
+ }
581
+ if (quote === "backtick") {
582
+ if (character === "`") quote = void 0;
583
+ continue;
584
+ }
585
+ if (quote === "bracket") {
586
+ if (character === "]") quote = void 0;
587
+ continue;
588
+ }
589
+ if (character === "'") quote = "single";
590
+ else if (character === "\"") quote = "double";
591
+ else if (character === "`") quote = "backtick";
592
+ else if (character === "[") quote = "bracket";
593
+ else if (character === "(") depth++;
594
+ else if (character === ")") depth--;
595
+ else if (character === "," && depth === 0) {
596
+ values.push(source.slice(start, index));
597
+ start = index + 1;
598
+ }
599
+ }
600
+ values.push(source.slice(start));
601
+ return values;
602
+ }
603
+ function isSimpleIdentifier(value) {
604
+ return /^(?:[A-Za-z_][A-Za-z0-9_$]*|"(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\])(?:\s+(?:ASC|DESC))?$/i.test(value);
605
+ }
606
+ function table(row, sqlText, namespace) {
607
+ const physicalName = text(row.name) ?? "unnamed_table";
608
+ const withoutRowid = boolean(row.wr);
609
+ const strict = boolean(row.strict);
610
+ return {
611
+ kind: "table",
612
+ id: stableId(physicalName),
613
+ identitySource: "physical-name",
614
+ physicalName,
615
+ reference: reference("table", physicalName, namespace, "sqlite_schema", "name"),
616
+ columns: [],
617
+ constraints: [],
618
+ indexes: [],
619
+ dialect: extension({
620
+ tableType: "table",
621
+ withoutRowid,
622
+ strict,
623
+ rowid: !withoutRowid
624
+ }),
625
+ unknownFields: [
626
+ ...withoutRowid ? [{
627
+ name: "withoutRowid",
628
+ value: true
629
+ }] : [],
630
+ ...strict ? [{
631
+ name: "strict",
632
+ value: true
633
+ }] : [],
634
+ ...sqlText ? [{
635
+ name: "createSql",
636
+ value: sqlText
637
+ }] : []
638
+ ]
639
+ };
640
+ }
641
+ function deferred(objectKind, physicalName, sqlText, namespace) {
642
+ return {
643
+ kind: "deferred-object",
644
+ id: stableId(`deferred:${objectKind}:${physicalName}`),
645
+ identitySource: "physical-name",
646
+ objectKind,
647
+ physicalName,
648
+ reference: reference("deferred-object", physicalName, namespace, "sqlite_schema", "name"),
649
+ dialect: extension({ objectKind }),
650
+ unknownFields: sqlText ? [{
651
+ name: "createSql",
652
+ value: sqlText
653
+ }] : void 0
654
+ };
655
+ }
656
+ function column(row, table, namespace, sqlText, rowidPrimaryKey, diagnostics) {
657
+ const physicalName = text(row.name) ?? "unnamed_column";
658
+ const hidden = number(row.hidden) ?? 0;
659
+ const type = text(row.type) ?? "";
660
+ const defaultValue = text(row.dflt_value);
661
+ const generatedExpression = hidden === 2 || hidden === 3 ? generatedExpressionFor(sqlText, physicalName) : void 0;
662
+ if ((hidden === 2 || hidden === 3) && !generatedExpression) diagnostics.push(createIntrospectionDiagnostic({
663
+ severity: "error",
664
+ code: "expression-parse-failed",
665
+ message: `SQLite generated expression for ${physicalName} could not be recovered`,
666
+ path: [
667
+ table.id,
668
+ "columns",
669
+ physicalName,
670
+ "generated"
671
+ ],
672
+ remediation: "Preserve the CREATE TABLE SQL or use lossy mode."
673
+ }));
674
+ const rowid = table.kind === "table" && rowidPrimaryKey && (number(row.pk) ?? 0) > 0 && type.toUpperCase() === "INTEGER" && !/WITHOUT\s+ROWID/i.test(sqlText ?? "");
675
+ const identity = rowid ? {
676
+ kind: "identity",
677
+ generation: "by-default",
678
+ options: {},
679
+ dialect: {
680
+ dialect: "sqlite",
681
+ version: 1,
682
+ data: {
683
+ rowidAlias: true,
684
+ autoIncrement: /AUTOINCREMENT/i.test(sqlText ?? ""),
685
+ withoutRowid: false
686
+ }
687
+ }
688
+ } : void 0;
689
+ return {
690
+ kind: "column",
691
+ id: stableId(physicalName),
692
+ identitySource: "physical-name",
693
+ physicalName,
694
+ ordinalPosition: number(row.cid) ?? 0,
695
+ nullable: !boolean(row.not_null) && !(rowid || (number(row.pk) ?? 0) > 0 && (/WITHOUT\s+ROWID/i.test(sqlText ?? "") || /\bSTRICT\b/i.test(sqlText ?? ""))),
696
+ storage: { nativeType: type || "BLOB" },
697
+ default: defaultValue !== void 0 && !generatedExpression ? {
698
+ kind: "expression",
699
+ expression: sql(defaultValue, namespace, table, physicalName)
700
+ } : void 0,
701
+ generated: generatedExpression ? {
702
+ kind: "generated",
703
+ mode: hidden === 2 ? "virtual" : "stored",
704
+ expression: sql(generatedExpression, namespace, table, physicalName)
705
+ } : void 0,
706
+ identity,
707
+ reference: reference("column", physicalName, namespace, "pragma_table_xinfo", "name"),
708
+ dialect: extension({
709
+ declaredType: type,
710
+ affinity: affinity(type),
711
+ hidden
712
+ })
713
+ };
714
+ }
715
+ function tableConstraints(table, rows, columns, sqlText, namespace) {
716
+ const primaryNames = new Map(rows.filter((row) => (number(row.pk) ?? 0) > 0).map((row) => [text(row.name), number(row.pk) ?? 0]));
717
+ const primaryColumns = columns.filter((column) => primaryNames.has(column.physicalName)).sort((left, right) => primaryNames.get(left.physicalName) - primaryNames.get(right.physicalName));
718
+ const constraints = [];
719
+ if (primaryColumns.length > 0) {
720
+ const declaredName = declaredConstraintName(sqlText, "PRIMARY\\s+KEY", primaryColumns.map((column) => column.physicalName));
721
+ const primaryName = declaredName ?? `primary_${table.physicalName}`;
722
+ const primary = {
723
+ kind: "primary-key",
724
+ id: stableId(primaryName),
725
+ identitySource: declaredName ? "physical-name" : "deterministic-fallback",
726
+ physicalName: primaryName,
727
+ columns: primaryColumns.map((column) => column.physicalName),
728
+ dialect: extension({ source: "pragma_table_xinfo" }),
729
+ reference: reference("constraint", primaryName, namespace, "sqlite_schema", "tbl_name")
730
+ };
731
+ constraints.push(primary);
732
+ }
733
+ [...sqlText?.matchAll(/(?:CONSTRAINT\s+("(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|[A-Za-z_][A-Za-z0-9_$]*)\s+)?CHECK\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)/gi) ?? []].forEach((match, index) => {
734
+ const name = unquoteIdentifier(match[1]) ?? `check_${index}_${table.physicalName}`;
735
+ const check = {
736
+ kind: "check",
737
+ id: stableId(name),
738
+ identitySource: "deterministic-fallback",
739
+ physicalName: name,
740
+ expression: sql(match[2] ?? "true", namespace, table, name),
741
+ dialect: extension({ source: "create-sql" })
742
+ };
743
+ constraints.push(check);
744
+ });
745
+ return constraints;
746
+ }
747
+ function mapIndex(table, row, infoRows, sqlText, namespace, diagnostics, opaqueObjects) {
748
+ const physicalName = text(row.name);
749
+ if (!physicalName) return;
750
+ const terms = [];
751
+ const collations = [];
752
+ for (const info of infoRows.filter((item) => boolean(item.key))) {
753
+ const position = number(info.seqno) ?? 0;
754
+ const cid = number(info.cid) ?? -1;
755
+ const collation = text(info.coll);
756
+ if (collation) collations.push(collation);
757
+ if (cid === -1) continue;
758
+ if (cid === -2) {
759
+ const expressionText = indexExpressionFor(sqlText, position);
760
+ if (expressionText) terms.push({
761
+ kind: "expression",
762
+ expression: sql(expressionText, namespace, table, physicalName),
763
+ position,
764
+ direction: boolean(info.descending) ? "DESC" : "ASC"
765
+ });
766
+ else {
767
+ opaqueObjects.push(opaqueIndexExpression(table, physicalName, position, info, sqlText, namespace));
768
+ diagnostics.push(createIntrospectionDiagnostic({
769
+ severity: "error",
770
+ code: "unsupported-feature",
771
+ message: `SQLite index ${physicalName} has an expression term that was not recovered`,
772
+ path: [
773
+ table.id,
774
+ "indexes",
775
+ physicalName,
776
+ "terms",
777
+ position
778
+ ],
779
+ physicalReference: reference("index", physicalName, namespace, "sqlite_schema", "name"),
780
+ remediation: "Preserve the CREATE INDEX SQL for expression terms."
781
+ }));
782
+ }
783
+ continue;
784
+ }
785
+ const columnName = text(info.name);
786
+ if (cid >= 0 && columnName) terms.push({
787
+ kind: "column",
788
+ column: columnName,
789
+ position,
790
+ direction: boolean(info.descending) ? "DESC" : "ASC"
791
+ });
792
+ else diagnostics.push(createIntrospectionDiagnostic({
793
+ severity: "error",
794
+ code: "unsupported-feature",
795
+ message: `SQLite index ${physicalName} has an expression term that was not recovered`,
796
+ path: [
797
+ table.id,
798
+ "indexes",
799
+ physicalName,
800
+ "terms",
801
+ position
802
+ ],
803
+ physicalReference: reference("index", physicalName, namespace, "sqlite_schema", "name")
804
+ }));
805
+ }
806
+ const unique = boolean(row.unique_index);
807
+ if (text(row.origin) === "u") {
808
+ const internalName = physicalName.startsWith("sqlite_autoindex_");
809
+ const termNames = terms.map((term) => term.kind === "column" ? term.column : `expression_${term.position}`);
810
+ const declaredName = declaredConstraintName(sqlText, "UNIQUE", termNames);
811
+ const constraintName = internalName ? declaredName ?? `unique_${table.physicalName}_${termNames.join("_") || "constraint"}` : physicalName;
812
+ return {
813
+ kind: "unique",
814
+ id: stableId(constraintName),
815
+ identitySource: internalName && !declaredName ? "deterministic-fallback" : "physical-name",
816
+ physicalName: constraintName,
817
+ columns: terms.flatMap((term) => term.kind === "column" ? [term.column] : []),
818
+ nulls: "distinct",
819
+ dialect: extension({
820
+ origin: text(row.origin) ?? "unknown",
821
+ collations,
822
+ ...internalName ? { internalName } : {}
823
+ }),
824
+ reference: reference("constraint", constraintName, namespace, "pragma_index_list", "name", physicalName)
825
+ };
826
+ }
827
+ return {
828
+ kind: "index",
829
+ id: stableId(physicalName),
830
+ identitySource: "physical-name",
831
+ physicalName,
832
+ unique,
833
+ terms,
834
+ dialect: extension({
835
+ origin: text(row.origin) ?? "unknown",
836
+ partial: boolean(row.partial),
837
+ collations
838
+ }),
839
+ predicate: boolean(row.partial) ? partialPredicate(sqlText, physicalName, namespace, table) : void 0,
840
+ reference: reference("index", physicalName, namespace, "sqlite_schema", "name")
841
+ };
842
+ }
843
+ function declaredConstraintName(sqlText, keyword, columns) {
844
+ if (!sqlText) return void 0;
845
+ const pattern = new RegExp(`CONSTRAINT\\s+("(?:[^"]|"")*"|\`[^\`]*\`|\\[[^\\]]*\\]|[A-Za-z_][A-Za-z0-9_\$]*)\\s+${keyword}\\s*\\(([^)]*)\\)`, "gi");
846
+ for (const match of sqlText.matchAll(pattern)) {
847
+ const found = (match[2] ?? "").split(",").map((value) => unquoteIdentifier(value.trim())).filter((value) => value !== void 0);
848
+ if (found.length === columns.length && found.every((value, index) => value === columns[index])) return unquoteIdentifier(match[1]);
849
+ }
850
+ }
851
+ function foreignKeys(table, rows, namespace) {
852
+ const grouped = /* @__PURE__ */ new Map();
853
+ for (const row of rows) {
854
+ const id = text(row.id) ?? "0";
855
+ const group = grouped.get(id) ?? [];
856
+ group.push(row);
857
+ grouped.set(id, group);
858
+ }
859
+ return [...grouped.entries()].map(([key, group]) => {
860
+ const first = group[0];
861
+ const physicalName = `foreign_key_${table.physicalName}_${key}`;
862
+ return {
863
+ kind: "foreign-key",
864
+ id: stableId(physicalName),
865
+ identitySource: "deterministic-fallback",
866
+ physicalName,
867
+ columns: group.sort((left, right) => (number(left.seq) ?? 0) - (number(right.seq) ?? 0)).map((row) => text(row.source_column) ?? "unknown"),
868
+ target: {
869
+ table: text(first.target_table) ?? "unknown",
870
+ columns: group.map((row) => text(row.target_column) ?? "unknown")
871
+ },
872
+ onUpdate: action(first.on_update),
873
+ onDelete: action(first.on_delete),
874
+ match: match(first.match),
875
+ dialect: extension({ foreignKeyId: key }),
876
+ reference: reference("constraint", physicalName, namespace, "pragma_foreign_key_list", "id", key)
877
+ };
878
+ });
879
+ }
880
+ function partialPredicate(sqlText, indexName, namespace, table) {
881
+ const predicate = (sqlText?.match(/\bWHERE\s+([\s\S]+)$/i))?.[1]?.trim().replace(/;\s*$/, "");
882
+ return predicate ? sql(predicate, namespace, table, indexName) : void 0;
883
+ }
884
+ function generatedExpressionFor(sqlText, columnName) {
885
+ if (!sqlText) return;
886
+ const open = sqlText.indexOf("(");
887
+ if (open < 0) return;
888
+ const close = matchingParen(sqlText, open);
889
+ if (close < 0) return;
890
+ const definitions = splitSqlList(sqlText.slice(open + 1, close));
891
+ for (const definition of definitions) {
892
+ const identifier = definition.trim().match(/^("(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|[A-Za-z_][A-Za-z0-9_$]*)/)?.[1];
893
+ if (unquoteIdentifier(identifier) !== columnName) continue;
894
+ const generated = definition.match(/\bAS\s*\(/i);
895
+ if (!generated || generated.index === void 0) return;
896
+ const generatedOpen = definition.indexOf("(", generated.index);
897
+ if (generatedOpen < 0) return;
898
+ const generatedClose = matchingParen(definition, generatedOpen);
899
+ return generatedClose < 0 ? void 0 : definition.slice(generatedOpen + 1, generatedClose).trim();
900
+ }
901
+ }
902
+ function sql(textValue, dialectNamespace, owner, name) {
903
+ const ownerReference = owner.reference ?? reference(owner.kind, owner.physicalName, dialectNamespace, "sqlite_schema", "name");
904
+ return {
905
+ kind: "sql",
906
+ dialect: "sqlite",
907
+ text: textValue,
908
+ provenance: {
909
+ kind: "create-sql",
910
+ dialect: "sqlite",
911
+ reference: reference(ownerReference.kind, name, dialectNamespace, ownerReference.catalog?.relation ?? "sqlite_schema", ownerReference.catalog?.key ?? "name", ownerReference.catalog?.value ?? ownerReference.name)
912
+ }
913
+ };
914
+ }
915
+ function reference(kind, name, namespace, relation, key, value = name) {
916
+ return {
917
+ kind,
918
+ name,
919
+ namespace,
920
+ catalog: {
921
+ relation,
922
+ key,
923
+ value
924
+ }
925
+ };
926
+ }
927
+ function emptyCatalog(namespace, diagnostics) {
928
+ return {
929
+ dialect: "sqlite",
930
+ server: {
931
+ product: "sqlite",
932
+ rawVersion: "unknown",
933
+ capabilities: {
934
+ generatedColumns: false,
935
+ identityMetadata: false,
936
+ checkConstraints: false,
937
+ checkConstraintEnforcement: "unknown",
938
+ expressionDecompilation: false,
939
+ indexExpressions: false,
940
+ indexPredicates: false,
941
+ indexIncludedColumns: false,
942
+ namespaces: false,
943
+ visibility: "unknown"
944
+ }
945
+ },
946
+ namespace: {
947
+ kind: "sqlite-database",
948
+ name: namespace
949
+ },
950
+ tables: [],
951
+ deferredObjects: [],
952
+ diagnostics
953
+ };
954
+ }
955
+ function stableId(value) {
956
+ if (value && !/[.\\\u0000-\u001f\u007f]/.test(value)) return value;
957
+ let hash = 2166136261;
958
+ for (const character of value) {
959
+ hash ^= character.charCodeAt(0);
960
+ hash = Math.imul(hash, 16777619);
961
+ }
962
+ return `introspected_${(hash >>> 0).toString(16)}`;
963
+ }
964
+ function text(value) {
965
+ return value === null || value === void 0 ? void 0 : String(value);
966
+ }
967
+ function number(value) {
968
+ if (typeof value === "number" && Number.isFinite(value)) return value;
969
+ if (typeof value === "string" && value.trim() !== "") {
970
+ const result = Number(value);
971
+ return Number.isFinite(result) ? result : void 0;
972
+ }
973
+ }
974
+ function boolean(value) {
975
+ return value === true || value === 1 || value === "1" || value === "t" || value === "true";
976
+ }
977
+ function action(value) {
978
+ const normalized = text(value)?.toLowerCase();
979
+ return normalized === "cascade" ? "cascade" : normalized === "restrict" ? "restrict" : normalized === "set null" ? "set-null" : normalized === "set default" ? "set-default" : "no-action";
980
+ }
981
+ function match(value) {
982
+ const normalized = text(value)?.toLowerCase();
983
+ return normalized === "full" ? "full" : normalized === "partial" ? "partial" : "simple";
984
+ }
985
+ //#endregion
986
+ export { readCatalog, sqliteDatabaseListQuery, sqliteForeignKeyQuery, sqliteIndexInfoQuery, sqliteIndexListQuery, sqliteSchemaQuery, sqliteServerQuery, sqliteTableInfoQuery, sqliteTableListQuery, sqliteTempSchemaQuery };