@lobomfz/db 0.3.0 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobomfz/db",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Bun SQLite database with Arktype schemas and typed Kysely client",
5
5
  "keywords": [
6
6
  "arktype",
package/src/database.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Database as BunDatabase } from "bun:sqlite";
2
- import { Kysely } from "kysely";
2
+ import { Kysely, ParseJSONResultsPlugin } from "kysely";
3
3
  import { BunSqliteDialect } from "./dialect/dialect";
4
4
  import type { Type } from "arktype";
5
5
  import type { GeneratedPreset } from "./generated";
@@ -82,7 +82,7 @@ export class Database<T extends SchemaRecord> {
82
82
 
83
83
  this.kysely = new Kysely<TablesFromSchemas<T>>({
84
84
  dialect: new BunSqliteDialect({ database: this.sqlite }),
85
- plugins: [new DeserializePlugin(this.columns, validation)],
85
+ plugins: [new DeserializePlugin(this.columns, validation), new ParseJSONResultsPlugin()],
86
86
  });
87
87
  }
88
88
 
@@ -335,6 +335,7 @@ export class Database<T extends SchemaRecord> {
335
335
 
336
336
  const indexes = (schemaIndexes?.[name] ?? []).map((indexDef) => ({
337
337
  name: this.generateIndexName(name, indexDef.columns, indexDef.unique ?? false),
338
+ columns: indexDef.columns,
338
339
  sql: this.generateCreateIndexSQL(name, indexDef),
339
340
  }));
340
341
 
@@ -7,6 +7,7 @@ export interface DesiredColumn extends ColumnSchema {
7
7
 
8
8
  export type DesiredIndex = {
9
9
  name: string;
10
+ columns: string[];
10
11
  sql: string;
11
12
  };
12
13
 
@@ -162,7 +163,7 @@ export class Differ {
162
163
 
163
164
  if (this.rebuiltTables.has(table.name)) {
164
165
  for (const idx of tableIndexes) {
165
- this.ops.push({ type: "CreateIndex", sql: idx.sql });
166
+ this.ops.push({ type: "CreateIndex", table: table.name, columns: idx.columns, sql: idx.sql });
166
167
  }
167
168
 
168
169
  continue;
@@ -179,7 +180,7 @@ export class Differ {
179
180
 
180
181
  for (const idx of tableIndexes) {
181
182
  if (!existingNames.has(idx.name)) {
182
- this.ops.push({ type: "CreateIndex", sql: idx.sql });
183
+ this.ops.push({ type: "CreateIndex", table: table.name, columns: idx.columns, sql: idx.sql });
183
184
  }
184
185
  }
185
186
 
@@ -30,7 +30,11 @@ export class Executor {
30
30
  try {
31
31
  this.db.transaction(() => {
32
32
  for (const op of this.ops) {
33
- this.executeOp(op);
33
+ try {
34
+ this.executeOp(op);
35
+ } catch (e) {
36
+ throw this.parseError(e, op);
37
+ }
34
38
  }
35
39
 
36
40
  if (restoreFk) {
@@ -71,6 +75,22 @@ export class Executor {
71
75
  }
72
76
  }
73
77
 
78
+ private parseError(e: unknown, op: MigrationOp) {
79
+ if (
80
+ op.type === "CreateIndex" &&
81
+ e instanceof Error &&
82
+ e.message.includes("UNIQUE constraint failed")
83
+ ) {
84
+ const cols = op.columns.map((c) => `"${c}"`).join(", ");
85
+
86
+ return new Error(
87
+ `Cannot create unique index on table "${op.table}" (${cols}): duplicate values exist`,
88
+ );
89
+ }
90
+
91
+ return e;
92
+ }
93
+
74
94
  private rebuildTable(op: RebuildTableOp) {
75
95
  const tempName = `__new_${op.table}`;
76
96
  const tempSql = op.createSql.replace(
@@ -29,6 +29,8 @@ export type RebuildTableOp = {
29
29
 
30
30
  export type CreateIndexOp = {
31
31
  type: "CreateIndex";
32
+ table: string;
33
+ columns: string[];
32
34
  sql: string;
33
35
  };
34
36