@b9g/zen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +1044 -0
- package/chunk-2IEEEMRN.js +38 -0
- package/chunk-56M5Z3A6.js +1346 -0
- package/chunk-QXGEP5PB.js +310 -0
- package/ddl-NAJM37GQ.js +9 -0
- package/package.json +102 -0
- package/src/bun.d.ts +50 -0
- package/src/bun.js +906 -0
- package/src/mysql.d.ts +62 -0
- package/src/mysql.js +573 -0
- package/src/postgres.d.ts +62 -0
- package/src/postgres.js +555 -0
- package/src/sqlite.d.ts +43 -0
- package/src/sqlite.js +447 -0
- package/src/zen.d.ts +14 -0
- package/src/zen.js +2143 -0
package/src/sqlite.js
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/// <reference types="./sqlite.d.ts" />
|
|
2
|
+
import {
|
|
3
|
+
quoteIdent,
|
|
4
|
+
renderDDL
|
|
5
|
+
} from "../chunk-2IEEEMRN.js";
|
|
6
|
+
import {
|
|
7
|
+
generateColumnDDL,
|
|
8
|
+
generateDDL
|
|
9
|
+
} from "../chunk-QXGEP5PB.js";
|
|
10
|
+
import {
|
|
11
|
+
ConstraintPreflightError,
|
|
12
|
+
EnsureError,
|
|
13
|
+
SchemaDriftError,
|
|
14
|
+
getTableMeta,
|
|
15
|
+
resolveSQLBuiltin
|
|
16
|
+
} from "../chunk-56M5Z3A6.js";
|
|
17
|
+
|
|
18
|
+
// src/sqlite.ts
|
|
19
|
+
import {
|
|
20
|
+
ConstraintViolationError,
|
|
21
|
+
isSQLBuiltin,
|
|
22
|
+
isSQLIdentifier
|
|
23
|
+
} from "./zen.js";
|
|
24
|
+
import Database from "better-sqlite3";
|
|
25
|
+
var DIALECT = "sqlite";
|
|
26
|
+
function quoteIdent2(name) {
|
|
27
|
+
return quoteIdent(name, DIALECT);
|
|
28
|
+
}
|
|
29
|
+
function buildSQL(strings, values) {
|
|
30
|
+
let sql = strings[0];
|
|
31
|
+
const params = [];
|
|
32
|
+
for (let i = 0; i < values.length; i++) {
|
|
33
|
+
let value = values[i];
|
|
34
|
+
if (isSQLBuiltin(value)) {
|
|
35
|
+
sql += resolveSQLBuiltin(value) + strings[i + 1];
|
|
36
|
+
} else if (isSQLIdentifier(value)) {
|
|
37
|
+
sql += quoteIdent2(value.name) + strings[i + 1];
|
|
38
|
+
} else {
|
|
39
|
+
sql += "?" + strings[i + 1];
|
|
40
|
+
if (typeof value === "boolean") {
|
|
41
|
+
value = value ? 1 : 0;
|
|
42
|
+
}
|
|
43
|
+
params.push(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { sql, params };
|
|
47
|
+
}
|
|
48
|
+
var SQLiteDriver = class {
|
|
49
|
+
supportsReturning = true;
|
|
50
|
+
#db;
|
|
51
|
+
constructor(url) {
|
|
52
|
+
const path = url.startsWith("file:") ? url.slice(5) : url;
|
|
53
|
+
this.#db = new Database(path);
|
|
54
|
+
this.#db.pragma("journal_mode = WAL");
|
|
55
|
+
this.#db.pragma("foreign_keys = ON");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Convert SQLite errors to Zealot errors.
|
|
59
|
+
*/
|
|
60
|
+
#handleError(error) {
|
|
61
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
62
|
+
const code = error.code;
|
|
63
|
+
const message = error.message || String(error);
|
|
64
|
+
if (code === "SQLITE_CONSTRAINT" || code === "SQLITE_CONSTRAINT_UNIQUE") {
|
|
65
|
+
const match = message.match(/constraint failed: (\w+)\.(\w+)/i);
|
|
66
|
+
const table = match ? match[1] : void 0;
|
|
67
|
+
const column = match ? match[2] : void 0;
|
|
68
|
+
const constraint = match ? `${table}.${column}` : void 0;
|
|
69
|
+
let kind = "unknown";
|
|
70
|
+
if (code === "SQLITE_CONSTRAINT_UNIQUE")
|
|
71
|
+
kind = "unique";
|
|
72
|
+
else if (message.includes("UNIQUE"))
|
|
73
|
+
kind = "unique";
|
|
74
|
+
else if (message.includes("FOREIGN KEY"))
|
|
75
|
+
kind = "foreign_key";
|
|
76
|
+
else if (message.includes("NOT NULL"))
|
|
77
|
+
kind = "not_null";
|
|
78
|
+
else if (message.includes("CHECK"))
|
|
79
|
+
kind = "check";
|
|
80
|
+
throw new ConstraintViolationError(
|
|
81
|
+
message,
|
|
82
|
+
{
|
|
83
|
+
kind,
|
|
84
|
+
constraint,
|
|
85
|
+
table,
|
|
86
|
+
column
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
cause: error
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
async all(strings, values) {
|
|
97
|
+
try {
|
|
98
|
+
const { sql, params } = buildSQL(strings, values);
|
|
99
|
+
return this.#db.prepare(sql).all(...params);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return this.#handleError(error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async get(strings, values) {
|
|
105
|
+
try {
|
|
106
|
+
const { sql, params } = buildSQL(strings, values);
|
|
107
|
+
return this.#db.prepare(sql).get(...params) ?? null;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
return this.#handleError(error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async run(strings, values) {
|
|
113
|
+
try {
|
|
114
|
+
const { sql, params } = buildSQL(strings, values);
|
|
115
|
+
const result = this.#db.prepare(sql).run(...params);
|
|
116
|
+
return result.changes;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
return this.#handleError(error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async val(strings, values) {
|
|
122
|
+
try {
|
|
123
|
+
const { sql, params } = buildSQL(strings, values);
|
|
124
|
+
return this.#db.prepare(sql).pluck().get(...params);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
return this.#handleError(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async close() {
|
|
130
|
+
this.#db.close();
|
|
131
|
+
}
|
|
132
|
+
async transaction(fn) {
|
|
133
|
+
this.#db.exec("BEGIN");
|
|
134
|
+
try {
|
|
135
|
+
const result = await fn(this);
|
|
136
|
+
this.#db.exec("COMMIT");
|
|
137
|
+
return result;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
this.#db.exec("ROLLBACK");
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async withMigrationLock(fn) {
|
|
144
|
+
this.#db.exec("BEGIN EXCLUSIVE");
|
|
145
|
+
try {
|
|
146
|
+
const result = await fn();
|
|
147
|
+
this.#db.exec("COMMIT");
|
|
148
|
+
return result;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
this.#db.exec("ROLLBACK");
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// ==========================================================================
|
|
155
|
+
// Schema Management
|
|
156
|
+
// ==========================================================================
|
|
157
|
+
async ensureTable(table) {
|
|
158
|
+
const tableName = table.name;
|
|
159
|
+
let step = 0;
|
|
160
|
+
let applied = false;
|
|
161
|
+
try {
|
|
162
|
+
const exists = await this.#tableExists(tableName);
|
|
163
|
+
if (!exists) {
|
|
164
|
+
step = 1;
|
|
165
|
+
const ddlTemplate = generateDDL(table, { dialect: DIALECT });
|
|
166
|
+
const ddlSQL = renderDDL(ddlTemplate[0], ddlTemplate.slice(1), DIALECT);
|
|
167
|
+
for (const stmt of ddlSQL.split(";").filter((s) => s.trim())) {
|
|
168
|
+
this.#db.exec(stmt.trim());
|
|
169
|
+
}
|
|
170
|
+
applied = true;
|
|
171
|
+
} else {
|
|
172
|
+
step = 2;
|
|
173
|
+
const columnsApplied = await this.#ensureMissingColumns(table);
|
|
174
|
+
applied = applied || columnsApplied;
|
|
175
|
+
step = 3;
|
|
176
|
+
const indexesApplied = await this.#ensureMissingIndexes(table);
|
|
177
|
+
applied = applied || indexesApplied;
|
|
178
|
+
step = 4;
|
|
179
|
+
await this.#checkMissingConstraints(table);
|
|
180
|
+
}
|
|
181
|
+
return { applied };
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof SchemaDriftError || error instanceof EnsureError) {
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
throw new EnsureError(
|
|
187
|
+
`ensureTable failed at step ${step}: ${error instanceof Error ? error.message : String(error)}`,
|
|
188
|
+
{ operation: "ensureTable", table: tableName, step },
|
|
189
|
+
{ cause: error }
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async ensureConstraints(table) {
|
|
194
|
+
const tableName = table.name;
|
|
195
|
+
let step = 0;
|
|
196
|
+
let applied = false;
|
|
197
|
+
try {
|
|
198
|
+
const exists = await this.#tableExists(tableName);
|
|
199
|
+
if (!exists) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Table "${tableName}" does not exist. Run ensureTable() first.`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
step = 1;
|
|
205
|
+
const existingConstraints = await this.#getConstraints(tableName);
|
|
206
|
+
step = 2;
|
|
207
|
+
const uniquesApplied = await this.#ensureUniqueConstraints(
|
|
208
|
+
table,
|
|
209
|
+
existingConstraints
|
|
210
|
+
);
|
|
211
|
+
applied = applied || uniquesApplied;
|
|
212
|
+
step = 3;
|
|
213
|
+
const fksApplied = await this.#ensureForeignKeys(
|
|
214
|
+
table,
|
|
215
|
+
existingConstraints
|
|
216
|
+
);
|
|
217
|
+
applied = applied || fksApplied;
|
|
218
|
+
return { applied };
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (error instanceof ConstraintPreflightError || error instanceof EnsureError) {
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
throw new EnsureError(
|
|
224
|
+
`ensureConstraints failed at step ${step}: ${error instanceof Error ? error.message : String(error)}`,
|
|
225
|
+
{ operation: "ensureConstraints", table: tableName, step },
|
|
226
|
+
{ cause: error }
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// ==========================================================================
|
|
231
|
+
// Introspection Helpers (private)
|
|
232
|
+
// ==========================================================================
|
|
233
|
+
async #tableExists(tableName) {
|
|
234
|
+
const result = this.#db.prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name=?`).all(tableName);
|
|
235
|
+
return result.length > 0;
|
|
236
|
+
}
|
|
237
|
+
async #getColumns(tableName) {
|
|
238
|
+
const result = this.#db.prepare(`PRAGMA table_info(${quoteIdent2(tableName)})`).all();
|
|
239
|
+
return result.map((row) => ({
|
|
240
|
+
name: row.name,
|
|
241
|
+
type: row.type,
|
|
242
|
+
notnull: row.notnull === 1
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
async #getIndexes(tableName) {
|
|
246
|
+
const indexList = this.#db.prepare(`PRAGMA index_list(${quoteIdent2(tableName)})`).all();
|
|
247
|
+
const indexes = [];
|
|
248
|
+
for (const idx of indexList) {
|
|
249
|
+
if (idx.origin === "pk")
|
|
250
|
+
continue;
|
|
251
|
+
const indexInfo = this.#db.prepare(`PRAGMA index_info(${quoteIdent2(idx.name)})`).all();
|
|
252
|
+
indexes.push({
|
|
253
|
+
name: idx.name,
|
|
254
|
+
columns: indexInfo.map((col) => col.name),
|
|
255
|
+
unique: idx.unique === 1
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return indexes;
|
|
259
|
+
}
|
|
260
|
+
async #getConstraints(tableName) {
|
|
261
|
+
const constraints = [];
|
|
262
|
+
const indexes = await this.#getIndexes(tableName);
|
|
263
|
+
for (const idx of indexes) {
|
|
264
|
+
if (idx.unique) {
|
|
265
|
+
constraints.push({
|
|
266
|
+
name: idx.name,
|
|
267
|
+
type: "unique",
|
|
268
|
+
columns: idx.columns
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const fks = this.#db.prepare(`PRAGMA foreign_key_list(${quoteIdent2(tableName)})`).all();
|
|
273
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
274
|
+
for (const fk of fks) {
|
|
275
|
+
if (!fkMap.has(fk.id)) {
|
|
276
|
+
fkMap.set(fk.id, { table: fk.table, from: [], to: [] });
|
|
277
|
+
}
|
|
278
|
+
const entry = fkMap.get(fk.id);
|
|
279
|
+
entry.from.push(fk.from);
|
|
280
|
+
entry.to.push(fk.to);
|
|
281
|
+
}
|
|
282
|
+
for (const [id, fk] of fkMap) {
|
|
283
|
+
constraints.push({
|
|
284
|
+
name: `fk_${tableName}_${id}`,
|
|
285
|
+
type: "foreign_key",
|
|
286
|
+
columns: fk.from,
|
|
287
|
+
referencedTable: fk.table,
|
|
288
|
+
referencedColumns: fk.to
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return constraints;
|
|
292
|
+
}
|
|
293
|
+
// ==========================================================================
|
|
294
|
+
// Schema Ensure Helpers (private)
|
|
295
|
+
// ==========================================================================
|
|
296
|
+
async #ensureMissingColumns(table) {
|
|
297
|
+
const existingCols = await this.#getColumns(table.name);
|
|
298
|
+
const existingColNames = new Set(existingCols.map((c) => c.name));
|
|
299
|
+
const schemaFields = Object.keys(table.schema.shape);
|
|
300
|
+
let applied = false;
|
|
301
|
+
for (const fieldName of schemaFields) {
|
|
302
|
+
if (!existingColNames.has(fieldName)) {
|
|
303
|
+
await this.#addColumn(table, fieldName);
|
|
304
|
+
applied = true;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return applied;
|
|
308
|
+
}
|
|
309
|
+
async #addColumn(table, fieldName) {
|
|
310
|
+
const zodType = table.schema.shape[fieldName];
|
|
311
|
+
const fieldMeta = getTableMeta(table).fields[fieldName] || {};
|
|
312
|
+
const colTemplate = generateColumnDDL(
|
|
313
|
+
fieldName,
|
|
314
|
+
zodType,
|
|
315
|
+
fieldMeta,
|
|
316
|
+
DIALECT
|
|
317
|
+
);
|
|
318
|
+
const colSQL = renderDDL(colTemplate[0], colTemplate.slice(1), DIALECT);
|
|
319
|
+
const sql = `ALTER TABLE ${quoteIdent2(table.name)} ADD COLUMN ${colSQL}`;
|
|
320
|
+
this.#db.exec(sql);
|
|
321
|
+
}
|
|
322
|
+
async #ensureMissingIndexes(table) {
|
|
323
|
+
const existingIndexes = await this.#getIndexes(table.name);
|
|
324
|
+
const existingIndexNames = new Set(existingIndexes.map((i) => i.name));
|
|
325
|
+
const meta = getTableMeta(table);
|
|
326
|
+
let applied = false;
|
|
327
|
+
for (const fieldName of meta.indexed) {
|
|
328
|
+
const indexName = `idx_${table.name}_${fieldName}`;
|
|
329
|
+
if (!existingIndexNames.has(indexName)) {
|
|
330
|
+
await this.#createIndex(table.name, [fieldName], false);
|
|
331
|
+
applied = true;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
for (const indexCols of table.indexes) {
|
|
335
|
+
const indexName = `idx_${table.name}_${indexCols.join("_")}`;
|
|
336
|
+
if (!existingIndexNames.has(indexName)) {
|
|
337
|
+
await this.#createIndex(table.name, indexCols, false);
|
|
338
|
+
applied = true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return applied;
|
|
342
|
+
}
|
|
343
|
+
async #createIndex(tableName, columns, unique) {
|
|
344
|
+
const prefix = unique ? "uniq" : "idx";
|
|
345
|
+
const indexName = `${prefix}_${tableName}_${columns.join("_")}`;
|
|
346
|
+
const uniqueClause = unique ? "UNIQUE " : "";
|
|
347
|
+
const columnList = columns.map(quoteIdent2).join(", ");
|
|
348
|
+
const sql = `CREATE ${uniqueClause}INDEX IF NOT EXISTS ${quoteIdent2(indexName)} ON ${quoteIdent2(tableName)} (${columnList})`;
|
|
349
|
+
this.#db.exec(sql);
|
|
350
|
+
return indexName;
|
|
351
|
+
}
|
|
352
|
+
async #checkMissingConstraints(table) {
|
|
353
|
+
const existingConstraints = await this.#getConstraints(table.name);
|
|
354
|
+
const meta = getTableMeta(table);
|
|
355
|
+
for (const fieldName of Object.keys(meta.fields)) {
|
|
356
|
+
const fieldMeta = meta.fields[fieldName];
|
|
357
|
+
if (fieldMeta.unique) {
|
|
358
|
+
const hasUnique = existingConstraints.some(
|
|
359
|
+
(c) => c.type === "unique" && c.columns.length === 1 && c.columns[0] === fieldName
|
|
360
|
+
);
|
|
361
|
+
if (!hasUnique) {
|
|
362
|
+
throw new SchemaDriftError(
|
|
363
|
+
`Table "${table.name}" is missing UNIQUE constraint on column "${fieldName}"`,
|
|
364
|
+
{
|
|
365
|
+
table: table.name,
|
|
366
|
+
drift: `missing unique:${fieldName}`,
|
|
367
|
+
suggestion: `Run ensureConstraints() to apply constraints`
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
for (const ref of meta.references) {
|
|
374
|
+
const hasFk = existingConstraints.some(
|
|
375
|
+
(c) => c.type === "foreign_key" && c.columns.length === 1 && c.columns[0] === ref.fieldName && c.referencedTable === ref.table.name && c.referencedColumns?.[0] === ref.referencedField
|
|
376
|
+
);
|
|
377
|
+
if (!hasFk) {
|
|
378
|
+
throw new SchemaDriftError(
|
|
379
|
+
`Table "${table.name}" is missing FOREIGN KEY on column "${ref.fieldName}" -> "${ref.table.name}"."${ref.referencedField}"`,
|
|
380
|
+
{
|
|
381
|
+
table: table.name,
|
|
382
|
+
drift: `missing fk:${ref.fieldName}`,
|
|
383
|
+
suggestion: `Run ensureConstraints() to apply constraints`
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
// ==========================================================================
|
|
390
|
+
// Constraint Application Helpers (private)
|
|
391
|
+
// ==========================================================================
|
|
392
|
+
async #ensureUniqueConstraints(table, existingConstraints) {
|
|
393
|
+
const meta = getTableMeta(table);
|
|
394
|
+
let applied = false;
|
|
395
|
+
for (const fieldName of Object.keys(meta.fields)) {
|
|
396
|
+
const fieldMeta = meta.fields[fieldName];
|
|
397
|
+
if (fieldMeta.unique) {
|
|
398
|
+
const hasUnique = existingConstraints.some(
|
|
399
|
+
(c) => c.type === "unique" && c.columns.length === 1 && c.columns[0] === fieldName
|
|
400
|
+
);
|
|
401
|
+
if (!hasUnique) {
|
|
402
|
+
await this.#preflightUnique(table.name, [fieldName]);
|
|
403
|
+
await this.#createIndex(table.name, [fieldName], true);
|
|
404
|
+
applied = true;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return applied;
|
|
409
|
+
}
|
|
410
|
+
async #ensureForeignKeys(table, existingConstraints) {
|
|
411
|
+
const meta = getTableMeta(table);
|
|
412
|
+
for (const ref of meta.references) {
|
|
413
|
+
const hasFk = existingConstraints.some(
|
|
414
|
+
(c) => c.type === "foreign_key" && c.columns.length === 1 && c.columns[0] === ref.fieldName && c.referencedTable === ref.table.name && c.referencedColumns?.[0] === ref.referencedField
|
|
415
|
+
);
|
|
416
|
+
if (!hasFk) {
|
|
417
|
+
throw new Error(
|
|
418
|
+
`Adding foreign key constraints to existing SQLite tables requires table rebuild. Table "${table.name}" column "${ref.fieldName}" -> "${ref.table.name}"."${ref.referencedField}". Please use a manual migration.`
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
async #preflightUnique(tableName, columns) {
|
|
425
|
+
const columnList = columns.map(quoteIdent2).join(", ");
|
|
426
|
+
const sql = `SELECT ${columnList}, COUNT(*) as cnt FROM ${quoteIdent2(tableName)} GROUP BY ${columnList} HAVING COUNT(*) > 1 LIMIT 1`;
|
|
427
|
+
const result = this.#db.prepare(sql).all();
|
|
428
|
+
if (result.length > 0) {
|
|
429
|
+
const diagQuery = `SELECT ${columns.join(", ")}, COUNT(*) as cnt FROM ${tableName} GROUP BY ${columns.join(", ")} HAVING COUNT(*) > 1`;
|
|
430
|
+
const countSql = `SELECT COUNT(*) as total FROM (${sql.replace(" LIMIT 1", "")}) t`;
|
|
431
|
+
const countResult = this.#db.prepare(countSql).all();
|
|
432
|
+
const violationCount = countResult[0]?.total ?? 1;
|
|
433
|
+
throw new ConstraintPreflightError(
|
|
434
|
+
`Cannot add UNIQUE constraint on "${tableName}"(${columns.join(", ")}): duplicate values exist`,
|
|
435
|
+
{
|
|
436
|
+
table: tableName,
|
|
437
|
+
constraint: `unique:${columns.join(",")}`,
|
|
438
|
+
violationCount,
|
|
439
|
+
query: diagQuery
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
export {
|
|
446
|
+
SQLiteDriver as default
|
|
447
|
+
};
|
package/src/zen.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @b9g/zen - The simple database client
|
|
3
|
+
*
|
|
4
|
+
* Define tables. Write SQL. Get objects.
|
|
5
|
+
*/
|
|
6
|
+
import { z as zod } from "zod";
|
|
7
|
+
export { zod as z };
|
|
8
|
+
export { table, type Table, type TableOptions, type Row, type Insert, type Update, type FieldMeta, type FieldType, type Relation, type InferRefs, } from "./impl/table.js";
|
|
9
|
+
export { Database, Transaction, DatabaseUpgradeEvent, type Driver, } from "./impl/database.js";
|
|
10
|
+
export { CURRENT_TIMESTAMP, CURRENT_DATE, CURRENT_TIME, NOW, TODAY, isSQLBuiltin, } from "./impl/database.js";
|
|
11
|
+
export { ident, isSQLIdentifier, } from "./impl/template.js";
|
|
12
|
+
export { type SQLTemplate, isSQLTemplate, } from "./impl/template.js";
|
|
13
|
+
export { type EnsureResult, } from "./impl/database.js";
|
|
14
|
+
export { DatabaseError, ValidationError, TableDefinitionError, MigrationError, MigrationLockError, QueryError, NotFoundError, AlreadyExistsError, ConstraintViolationError, ConnectionError, TransactionError, EnsureError, SchemaDriftError, ConstraintPreflightError, isDatabaseError, hasErrorCode, type DatabaseErrorCode, type EnsureOperation, } from "./impl/errors.js";
|