@type32/tauri-sqlite-orm 0.2.9 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -289,6 +289,9 @@ declare class TauriORM {
289
289
  migrate(options?: {
290
290
  performDestructiveActions?: boolean;
291
291
  }): Promise<void>;
292
+ private canAddColumnWithAlter;
293
+ private hasColumnDefinitionChanged;
294
+ private recreateTable;
292
295
  select<T extends AnyTable, C extends (keyof T['_']['columns'])[] | undefined = undefined>(table: T, columns?: C): SelectQueryBuilder<T, C>;
293
296
  insert<T extends AnyTable>(table: T): InsertQueryBuilder<T>;
294
297
  update<T extends AnyTable>(table: T): UpdateQueryBuilder<T>;
package/dist/index.d.ts CHANGED
@@ -289,6 +289,9 @@ declare class TauriORM {
289
289
  migrate(options?: {
290
290
  performDestructiveActions?: boolean;
291
291
  }): Promise<void>;
292
+ private canAddColumnWithAlter;
293
+ private hasColumnDefinitionChanged;
294
+ private recreateTable;
292
295
  select<T extends AnyTable, C extends (keyof T['_']['columns'])[] | undefined = undefined>(table: T, columns?: C): SelectQueryBuilder<T, C>;
293
296
  insert<T extends AnyTable>(table: T): InsertQueryBuilder<T>;
294
297
  update<T extends AnyTable>(table: T): UpdateQueryBuilder<T>;
package/dist/index.js CHANGED
@@ -1269,30 +1269,62 @@ var TauriORM = class {
1269
1269
  const tableExists = dbTableNames.has(tableName);
1270
1270
  if (!tableExists) {
1271
1271
  const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
1272
- const createSql = `CREATE TABLE ${tableName}
1273
- (
1274
- ${columnsSql}
1275
- )`;
1272
+ const createSql = `CREATE TABLE ${tableName} (${columnsSql})`;
1276
1273
  await this.db.execute(createSql);
1277
1274
  } else {
1278
1275
  const existingTableInfo = await this.db.select(`PRAGMA table_info('${tableName}')`);
1279
- const existingColumnNames = new Set(existingTableInfo.map((c) => c.name));
1280
- const schemaColumnNames = new Set(Object.keys(table._.columns));
1281
- for (const column of Object.values(table._.columns)) {
1282
- if (!existingColumnNames.has(column._.name)) {
1283
- const columnSql = this.buildColumnDefinition(column, true);
1284
- const alterSql = `ALTER TABLE ${tableName}
1285
- ADD COLUMN ${columnSql}`;
1286
- await this.db.execute(alterSql);
1276
+ const existingIndexes = await this.db.select(`PRAGMA index_list('${tableName}')`);
1277
+ const uniqueColumns = /* @__PURE__ */ new Set();
1278
+ for (const index of existingIndexes) {
1279
+ if (index.unique === 1 && index.origin === "u") {
1280
+ const indexInfo = await this.db.select(`PRAGMA index_info('${index.name}')`);
1281
+ if (indexInfo.length === 1) {
1282
+ uniqueColumns.add(indexInfo[0].name);
1283
+ }
1284
+ }
1285
+ }
1286
+ const existingColumns = new Map(existingTableInfo.map((c) => [c.name, c]));
1287
+ const schemaColumns = table._.columns;
1288
+ let needsRecreate = false;
1289
+ const columnsToAdd = [];
1290
+ for (const [colName, column] of Object.entries(schemaColumns)) {
1291
+ const existing = existingColumns.get(colName);
1292
+ if (!existing) {
1293
+ if (this.canAddColumnWithAlter(column)) {
1294
+ columnsToAdd.push(column);
1295
+ } else {
1296
+ needsRecreate = true;
1297
+ break;
1298
+ }
1299
+ } else {
1300
+ const hasUniqueInDB = uniqueColumns.has(colName);
1301
+ const wantsUnique = !!column.options.unique;
1302
+ if (hasUniqueInDB !== wantsUnique) {
1303
+ needsRecreate = true;
1304
+ break;
1305
+ }
1306
+ if (this.hasColumnDefinitionChanged(column, existing)) {
1307
+ needsRecreate = true;
1308
+ break;
1309
+ }
1287
1310
  }
1288
1311
  }
1289
1312
  if (options?.performDestructiveActions) {
1290
- for (const colName of existingColumnNames) {
1291
- if (!schemaColumnNames.has(colName)) {
1292
- await this.dropColumn(tableName, colName);
1313
+ for (const existingCol of existingColumns.keys()) {
1314
+ if (!schemaColumns[existingCol]) {
1315
+ needsRecreate = true;
1316
+ break;
1293
1317
  }
1294
1318
  }
1295
1319
  }
1320
+ if (needsRecreate) {
1321
+ await this.recreateTable(tableName, table);
1322
+ } else if (columnsToAdd.length > 0) {
1323
+ for (const column of columnsToAdd) {
1324
+ const columnSql = this.buildColumnDefinition(column, true);
1325
+ await this.db.execute(`ALTER TABLE ${tableName} ADD COLUMN ${columnSql}`);
1326
+ }
1327
+ }
1296
1328
  }
1297
1329
  }
1298
1330
  if (options?.performDestructiveActions) {
@@ -1303,6 +1335,38 @@ var TauriORM = class {
1303
1335
  }
1304
1336
  }
1305
1337
  }
1338
+ canAddColumnWithAlter(column) {
1339
+ if (column.options.primaryKey) return false;
1340
+ if (column.options.unique) return false;
1341
+ if (column._.notNull && column.options.default === void 0 && !column.options.$defaultFn) return false;
1342
+ return true;
1343
+ }
1344
+ hasColumnDefinitionChanged(column, existing) {
1345
+ if (column.type.toUpperCase() !== existing.type.toUpperCase()) return true;
1346
+ if (column._.notNull !== (existing.notnull === 1)) return true;
1347
+ if (!!column.options.primaryKey !== (existing.pk === 1)) return true;
1348
+ const hasDefault = column.options.default !== void 0;
1349
+ const existingHasDefault = existing.dflt_value !== null;
1350
+ if (hasDefault !== existingHasDefault) return true;
1351
+ return false;
1352
+ }
1353
+ async recreateTable(tableName, table) {
1354
+ const tempTableName = `${tableName}_new_${Date.now()}`;
1355
+ const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
1356
+ await this.db.execute(`CREATE TABLE ${tempTableName} (${columnsSql})`);
1357
+ const oldColumns = await this.db.select(`PRAGMA table_info('${tableName}')`);
1358
+ const oldColumnNames = oldColumns.map((c) => c.name);
1359
+ const newColumnNames = Object.keys(table._.columns);
1360
+ const commonColumns = oldColumnNames.filter((name) => newColumnNames.includes(name));
1361
+ if (commonColumns.length > 0) {
1362
+ const columnsList = commonColumns.join(", ");
1363
+ await this.db.execute(
1364
+ `INSERT INTO ${tempTableName} (${columnsList}) SELECT ${columnsList} FROM ${tableName}`
1365
+ );
1366
+ }
1367
+ await this.db.execute(`DROP TABLE ${tableName}`);
1368
+ await this.db.execute(`ALTER TABLE ${tempTableName} RENAME TO ${tableName}`);
1369
+ }
1306
1370
  select(table, columns) {
1307
1371
  const internalTable = this.tables.get(table._.name);
1308
1372
  if (!internalTable) {
package/dist/index.mjs CHANGED
@@ -1170,30 +1170,62 @@ var TauriORM = class {
1170
1170
  const tableExists = dbTableNames.has(tableName);
1171
1171
  if (!tableExists) {
1172
1172
  const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
1173
- const createSql = `CREATE TABLE ${tableName}
1174
- (
1175
- ${columnsSql}
1176
- )`;
1173
+ const createSql = `CREATE TABLE ${tableName} (${columnsSql})`;
1177
1174
  await this.db.execute(createSql);
1178
1175
  } else {
1179
1176
  const existingTableInfo = await this.db.select(`PRAGMA table_info('${tableName}')`);
1180
- const existingColumnNames = new Set(existingTableInfo.map((c) => c.name));
1181
- const schemaColumnNames = new Set(Object.keys(table._.columns));
1182
- for (const column of Object.values(table._.columns)) {
1183
- if (!existingColumnNames.has(column._.name)) {
1184
- const columnSql = this.buildColumnDefinition(column, true);
1185
- const alterSql = `ALTER TABLE ${tableName}
1186
- ADD COLUMN ${columnSql}`;
1187
- await this.db.execute(alterSql);
1177
+ const existingIndexes = await this.db.select(`PRAGMA index_list('${tableName}')`);
1178
+ const uniqueColumns = /* @__PURE__ */ new Set();
1179
+ for (const index of existingIndexes) {
1180
+ if (index.unique === 1 && index.origin === "u") {
1181
+ const indexInfo = await this.db.select(`PRAGMA index_info('${index.name}')`);
1182
+ if (indexInfo.length === 1) {
1183
+ uniqueColumns.add(indexInfo[0].name);
1184
+ }
1185
+ }
1186
+ }
1187
+ const existingColumns = new Map(existingTableInfo.map((c) => [c.name, c]));
1188
+ const schemaColumns = table._.columns;
1189
+ let needsRecreate = false;
1190
+ const columnsToAdd = [];
1191
+ for (const [colName, column] of Object.entries(schemaColumns)) {
1192
+ const existing = existingColumns.get(colName);
1193
+ if (!existing) {
1194
+ if (this.canAddColumnWithAlter(column)) {
1195
+ columnsToAdd.push(column);
1196
+ } else {
1197
+ needsRecreate = true;
1198
+ break;
1199
+ }
1200
+ } else {
1201
+ const hasUniqueInDB = uniqueColumns.has(colName);
1202
+ const wantsUnique = !!column.options.unique;
1203
+ if (hasUniqueInDB !== wantsUnique) {
1204
+ needsRecreate = true;
1205
+ break;
1206
+ }
1207
+ if (this.hasColumnDefinitionChanged(column, existing)) {
1208
+ needsRecreate = true;
1209
+ break;
1210
+ }
1188
1211
  }
1189
1212
  }
1190
1213
  if (options?.performDestructiveActions) {
1191
- for (const colName of existingColumnNames) {
1192
- if (!schemaColumnNames.has(colName)) {
1193
- await this.dropColumn(tableName, colName);
1214
+ for (const existingCol of existingColumns.keys()) {
1215
+ if (!schemaColumns[existingCol]) {
1216
+ needsRecreate = true;
1217
+ break;
1194
1218
  }
1195
1219
  }
1196
1220
  }
1221
+ if (needsRecreate) {
1222
+ await this.recreateTable(tableName, table);
1223
+ } else if (columnsToAdd.length > 0) {
1224
+ for (const column of columnsToAdd) {
1225
+ const columnSql = this.buildColumnDefinition(column, true);
1226
+ await this.db.execute(`ALTER TABLE ${tableName} ADD COLUMN ${columnSql}`);
1227
+ }
1228
+ }
1197
1229
  }
1198
1230
  }
1199
1231
  if (options?.performDestructiveActions) {
@@ -1204,6 +1236,38 @@ var TauriORM = class {
1204
1236
  }
1205
1237
  }
1206
1238
  }
1239
+ canAddColumnWithAlter(column) {
1240
+ if (column.options.primaryKey) return false;
1241
+ if (column.options.unique) return false;
1242
+ if (column._.notNull && column.options.default === void 0 && !column.options.$defaultFn) return false;
1243
+ return true;
1244
+ }
1245
+ hasColumnDefinitionChanged(column, existing) {
1246
+ if (column.type.toUpperCase() !== existing.type.toUpperCase()) return true;
1247
+ if (column._.notNull !== (existing.notnull === 1)) return true;
1248
+ if (!!column.options.primaryKey !== (existing.pk === 1)) return true;
1249
+ const hasDefault = column.options.default !== void 0;
1250
+ const existingHasDefault = existing.dflt_value !== null;
1251
+ if (hasDefault !== existingHasDefault) return true;
1252
+ return false;
1253
+ }
1254
+ async recreateTable(tableName, table) {
1255
+ const tempTableName = `${tableName}_new_${Date.now()}`;
1256
+ const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
1257
+ await this.db.execute(`CREATE TABLE ${tempTableName} (${columnsSql})`);
1258
+ const oldColumns = await this.db.select(`PRAGMA table_info('${tableName}')`);
1259
+ const oldColumnNames = oldColumns.map((c) => c.name);
1260
+ const newColumnNames = Object.keys(table._.columns);
1261
+ const commonColumns = oldColumnNames.filter((name) => newColumnNames.includes(name));
1262
+ if (commonColumns.length > 0) {
1263
+ const columnsList = commonColumns.join(", ");
1264
+ await this.db.execute(
1265
+ `INSERT INTO ${tempTableName} (${columnsList}) SELECT ${columnsList} FROM ${tableName}`
1266
+ );
1267
+ }
1268
+ await this.db.execute(`DROP TABLE ${tableName}`);
1269
+ await this.db.execute(`ALTER TABLE ${tempTableName} RENAME TO ${tableName}`);
1270
+ }
1207
1271
  select(table, columns) {
1208
1272
  const internalTable = this.tables.get(table._.name);
1209
1273
  if (!internalTable) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@type32/tauri-sqlite-orm",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "A Drizzle-like ORM for Tauri v2's SQL JS API plugin.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",