sqlmorpheus 0.2.0 → 0.2.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/dist/index.d.mts +60 -23
- package/dist/index.d.ts +60 -23
- package/dist/index.js +276 -109
- package/dist/index.mjs +272 -107
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -37,6 +37,47 @@ function getTableInfoFromMetadata(metadata) {
|
|
|
37
37
|
return metadata[TABLE_INFO_PROPERTY_NAME];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// src/lib/tableInfo/TableObj.ts
|
|
41
|
+
var TableObj = class _TableObj {
|
|
42
|
+
IS_TABLE_OBJ = true;
|
|
43
|
+
tableName;
|
|
44
|
+
columns;
|
|
45
|
+
tableInfo = {
|
|
46
|
+
primaryKey: void 0,
|
|
47
|
+
foreignKeys: [],
|
|
48
|
+
dataTypes: {}
|
|
49
|
+
};
|
|
50
|
+
constructor(tableName, columns) {
|
|
51
|
+
this.tableName = tableName;
|
|
52
|
+
this.columns = columns;
|
|
53
|
+
}
|
|
54
|
+
primaryKey(key) {
|
|
55
|
+
this.tableInfo.primaryKey = key.toString();
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
foreignKey(fromColumn, toTable, toColumn, options) {
|
|
59
|
+
this.tableInfo.foreignKeys.push({
|
|
60
|
+
fromTable: this.tableName,
|
|
61
|
+
fromColumn: fromColumn.toString(),
|
|
62
|
+
toTable: toTable.tableName,
|
|
63
|
+
toColumn: toColumn.toString(),
|
|
64
|
+
onUpdate: options?.onUpdate,
|
|
65
|
+
onDelete: options?.onDelete
|
|
66
|
+
});
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
dataType(column, type) {
|
|
70
|
+
this.tableInfo.dataTypes[column.toString()] = type;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
static create(tableName, columns) {
|
|
74
|
+
return new _TableObj(tableName, columns);
|
|
75
|
+
}
|
|
76
|
+
static isDbTable(obj) {
|
|
77
|
+
return !!obj?.IS_TABLE_OBJ;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
40
81
|
// src/lib/TableStructureGenerator.ts
|
|
41
82
|
var TableStructureGenerator = class {
|
|
42
83
|
dialect;
|
|
@@ -45,19 +86,21 @@ var TableStructureGenerator = class {
|
|
|
45
86
|
this.dialect = dialect;
|
|
46
87
|
this.dbInstructions = dbInstructions;
|
|
47
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Generates the structure of tables based on database instructions.
|
|
91
|
+
*
|
|
92
|
+
* @return An object where keys are table names, and values are their corresponding table structures.
|
|
93
|
+
*/
|
|
48
94
|
generateTableStructure() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
tableObjects[table.
|
|
95
|
+
const tableObjects = {};
|
|
96
|
+
for (const table of this.dbInstructions.tables) {
|
|
97
|
+
if (TableObj.isDbTable(table))
|
|
98
|
+
tableObjects[table.tableName] = table;
|
|
99
|
+
else {
|
|
100
|
+
const classTable = table;
|
|
101
|
+
tableObjects[classTable.name] = { columns: new classTable(), tableInfo: getTableInfo(classTable) };
|
|
53
102
|
}
|
|
54
|
-
return this.getExpectedStructure(tableObjects);
|
|
55
|
-
} else {
|
|
56
|
-
const tableObjects = this.dbInstructions.tables;
|
|
57
|
-
return this.getExpectedStructure(tableObjects);
|
|
58
103
|
}
|
|
59
|
-
}
|
|
60
|
-
getExpectedStructure(tableObjects) {
|
|
61
104
|
const tables = {};
|
|
62
105
|
for (const tableName in tableObjects) {
|
|
63
106
|
const obj = tableObjects[tableName];
|
|
@@ -65,46 +108,49 @@ var TableStructureGenerator = class {
|
|
|
65
108
|
tables[tableName] = {
|
|
66
109
|
table: tableName,
|
|
67
110
|
primaryKey: tableInfo?.primaryKey,
|
|
68
|
-
columns: this.getColumns(obj.columns, tableInfo
|
|
111
|
+
columns: this.getColumns(obj.columns, tableInfo),
|
|
69
112
|
foreignKeys: tableInfo?.foreignKeys
|
|
70
113
|
};
|
|
71
114
|
}
|
|
72
115
|
return tables;
|
|
73
116
|
}
|
|
74
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Retrieves the columns for a table
|
|
119
|
+
*
|
|
120
|
+
* @param obj - The table class interface object containing properties that represent the table's fields.
|
|
121
|
+
* @param tableInfo - Optional metadata about the table. Can be undefined.
|
|
122
|
+
* @return An array of {@link ColumnInfo} representing the detailed column information.
|
|
123
|
+
*/
|
|
124
|
+
getColumns(obj, tableInfo) {
|
|
75
125
|
const columns = [];
|
|
76
126
|
for (const property in obj) {
|
|
77
127
|
const propertyKey = property;
|
|
78
128
|
const value = obj[propertyKey];
|
|
79
129
|
const columnData = {
|
|
80
130
|
name: property,
|
|
81
|
-
isPrimaryKey: property == primaryKey,
|
|
82
|
-
type:
|
|
83
|
-
defaultValue: this.dialect.
|
|
131
|
+
isPrimaryKey: property == tableInfo?.primaryKey,
|
|
132
|
+
type: this.dialect.types.string,
|
|
133
|
+
defaultValue: this.dialect.types.null
|
|
84
134
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
columnData.type = this.dialect.typeString;
|
|
88
|
-
columnData.defaultValue = value === null ? this.dialect.typeNull : `"${this.dialect.formatValueToSql(value)}"`;
|
|
89
|
-
break;
|
|
90
|
-
case "bigint":
|
|
91
|
-
columnData.type = this.dialect.typeBigInt;
|
|
92
|
-
columnData.defaultValue = value === null ? this.dialect.typeNull : this.dialect.formatValueToSql(value);
|
|
93
|
-
break;
|
|
94
|
-
case "number":
|
|
95
|
-
columnData.type = this.dialect.typeInt;
|
|
96
|
-
columnData.defaultValue = value === null ? this.dialect.typeNull : this.dialect.formatValueToSql(value);
|
|
97
|
-
break;
|
|
98
|
-
case "boolean":
|
|
99
|
-
columnData.type = this.dialect.typeBoolean;
|
|
100
|
-
columnData.defaultValue = value === null ? this.dialect.typeNull : this.dialect.formatValueToSql(value);
|
|
101
|
-
break;
|
|
135
|
+
let dataType = tableInfo?.dataTypes?.[property] ?? typeof value;
|
|
136
|
+
switch (dataType) {
|
|
102
137
|
case "function":
|
|
103
138
|
continue;
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
case "object":
|
|
140
|
+
if (value instanceof Date) {
|
|
141
|
+
dataType = "date";
|
|
142
|
+
break;
|
|
143
|
+
} else {
|
|
144
|
+
Logger.warn(`${property} was skipped because its type (${typeof value}) is not supported`);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
case "undefined":
|
|
148
|
+
case "symbol":
|
|
149
|
+
Logger.warn(`${property} was skipped because its type (${typeof value}) is not supported`);
|
|
106
150
|
continue;
|
|
107
151
|
}
|
|
152
|
+
columnData.defaultValue = value === null ? this.dialect.types.null : this.dialect.formatValueToSql(value, dataType);
|
|
153
|
+
columnData.type = this.dialect.types[dataType];
|
|
108
154
|
columns.push(columnData);
|
|
109
155
|
}
|
|
110
156
|
return columns;
|
|
@@ -114,32 +160,37 @@ var TableStructureGenerator = class {
|
|
|
114
160
|
// src/lib/exceptions/NotAllowedException.ts
|
|
115
161
|
var NotAllowedException = class extends Error {
|
|
116
162
|
constructor(entries) {
|
|
117
|
-
let message = "Some destructive changes need to be confirmed
|
|
163
|
+
let message = "Some destructive changes need to be confirmed. In preMigration() run:\n";
|
|
118
164
|
for (const entry of entries) {
|
|
119
|
-
message += ` migrations.allowMigration(${entry.version},
|
|
165
|
+
message += ` migrations.allowMigration(${entry.version}, ${entry.tableName}, "${entry.type}");
|
|
120
166
|
`;
|
|
121
167
|
}
|
|
122
168
|
super(message);
|
|
123
169
|
}
|
|
124
170
|
};
|
|
125
171
|
|
|
126
|
-
// src/lib/
|
|
172
|
+
// src/lib/Migrations.ts
|
|
127
173
|
var Migrations = class {
|
|
128
|
-
toVersion = 0;
|
|
129
|
-
alwaysAllowed = {};
|
|
130
174
|
fromVersion = 0;
|
|
175
|
+
toVersion = 0;
|
|
176
|
+
lastUsedVersion = 0;
|
|
131
177
|
migrationData = {};
|
|
132
178
|
migrationDataForOldTableNames = {};
|
|
179
|
+
alwaysAllowed = {};
|
|
133
180
|
notAllowedChanges = [];
|
|
134
181
|
reset(dbInstructions, fromVersion) {
|
|
135
182
|
this.fromVersion = fromVersion;
|
|
136
|
-
this.migrationData = {};
|
|
137
183
|
this.toVersion = dbInstructions.version;
|
|
184
|
+
this.migrationData = {};
|
|
185
|
+
this.migrationDataForOldTableNames = {};
|
|
138
186
|
this.alwaysAllowed = dbInstructions.alwaysAllowedMigrations ?? {};
|
|
139
187
|
this.notAllowedChanges = [];
|
|
140
188
|
}
|
|
141
189
|
getEntry(table) {
|
|
142
190
|
const tableName = this.getTableName(table);
|
|
191
|
+
return this.getEntryFromTableName(tableName);
|
|
192
|
+
}
|
|
193
|
+
getEntryFromTableName(tableName) {
|
|
143
194
|
if (!this.migrationData.hasOwnProperty(tableName)) {
|
|
144
195
|
this.migrationData[tableName] = {
|
|
145
196
|
recreate: false,
|
|
@@ -151,17 +202,27 @@ var Migrations = class {
|
|
|
151
202
|
return this.migrationData[tableName];
|
|
152
203
|
}
|
|
153
204
|
getTableName(table) {
|
|
154
|
-
return
|
|
205
|
+
return TableObj.isDbTable(table) ? table.tableName : table.name;
|
|
206
|
+
}
|
|
207
|
+
versionIsRelevant(version) {
|
|
208
|
+
if (version < this.fromVersion || version > this.toVersion)
|
|
209
|
+
return false;
|
|
210
|
+
if (version < this.lastUsedVersion)
|
|
211
|
+
throw new Error("Migrations in preMigration() have to be ordered by version (beginning with the lowest version).");
|
|
212
|
+
this.lastUsedVersion = version;
|
|
213
|
+
return true;
|
|
155
214
|
}
|
|
156
215
|
verifyRenamingTasks(newTables) {
|
|
157
216
|
for (const tableName in this.migrationData) {
|
|
158
217
|
const migrationEntry = this.migrationData[tableName];
|
|
159
|
-
if (migrationEntry.tableRenaming
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
218
|
+
if (migrationEntry.tableRenaming) {
|
|
219
|
+
if (migrationEntry.tableRenaming.oldName == tableName)
|
|
220
|
+
return new Error(`You set table "${tableName}" to be renamed to itself!`);
|
|
221
|
+
if (migrationEntry.tableRenaming.newName != tableName)
|
|
222
|
+
return new Error(`You set table "${tableName}" to be renamed to a different name than the one in your structure (${migrationEntry.tableRenaming.newName})!`);
|
|
223
|
+
else if (!newTables[tableName])
|
|
224
|
+
return new Error(`You set table "${migrationEntry.tableRenaming}" migrations for "${tableName}". But "${tableName}" does not exist in your structure.`);
|
|
225
|
+
}
|
|
165
226
|
for (const renamingData of migrationEntry.renamedColumns) {
|
|
166
227
|
const oldColumnName = renamingData.oldName;
|
|
167
228
|
const newColumnName = renamingData.newName;
|
|
@@ -195,6 +256,33 @@ var Migrations = class {
|
|
|
195
256
|
} else if (migrationEntry)
|
|
196
257
|
migrationEntry.usedMigrations[type] = true;
|
|
197
258
|
}
|
|
259
|
+
getMigrationData() {
|
|
260
|
+
return this.migrationData;
|
|
261
|
+
}
|
|
262
|
+
loopRenamedColumns(tableName, callback) {
|
|
263
|
+
const migrationEntry = this.migrationData[tableName];
|
|
264
|
+
for (const renamingData of migrationEntry.renamedColumns) {
|
|
265
|
+
callback(renamingData.oldName, renamingData.newName);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
getNewestTableName(tableName) {
|
|
269
|
+
return this.migrationDataForOldTableNames[tableName]?.tableRenaming?.newName ?? tableName;
|
|
270
|
+
}
|
|
271
|
+
getOldTableName(tableName) {
|
|
272
|
+
return this.migrationData[tableName]?.tableRenaming?.oldName ?? tableName;
|
|
273
|
+
}
|
|
274
|
+
getNewestColumnName(tableName, oldColumnName) {
|
|
275
|
+
const columnNames = this.migrationData[tableName]?.renamedColumns.find((columns) => columns.oldName == oldColumnName);
|
|
276
|
+
return columnNames ? columnNames.newName : oldColumnName;
|
|
277
|
+
}
|
|
278
|
+
willBeRecreated(tableName) {
|
|
279
|
+
return this.migrationData[tableName]?.recreate;
|
|
280
|
+
}
|
|
281
|
+
internalRecreate(tableName, reason) {
|
|
282
|
+
const entry = this.getEntryFromTableName(tableName);
|
|
283
|
+
entry.recreate = true;
|
|
284
|
+
Logger.log(`Table ${tableName} will be recreated(${reason})!`);
|
|
285
|
+
}
|
|
198
286
|
allowMigration(version, table, ...allowedMigrations) {
|
|
199
287
|
if (version < this.fromVersion || version > this.toVersion)
|
|
200
288
|
return;
|
|
@@ -204,13 +292,9 @@ var Migrations = class {
|
|
|
204
292
|
}
|
|
205
293
|
}
|
|
206
294
|
renameTable(version, oldTableName, newTableName) {
|
|
207
|
-
if (
|
|
295
|
+
if (!this.versionIsRelevant(version))
|
|
208
296
|
return;
|
|
209
297
|
const newTableNameString = this.getTableName(newTableName);
|
|
210
|
-
if (this.migrationData.hasOwnProperty(oldTableName)) {
|
|
211
|
-
this.migrationData[newTableNameString] = this.getEntry(oldTableName);
|
|
212
|
-
delete this.migrationData[oldTableName];
|
|
213
|
-
}
|
|
214
298
|
const entry = this.getEntry(newTableName);
|
|
215
299
|
this.migrationDataForOldTableNames[oldTableName] = entry;
|
|
216
300
|
if (!entry.tableRenaming)
|
|
@@ -219,7 +303,7 @@ var Migrations = class {
|
|
|
219
303
|
entry.tableRenaming.newName = newTableNameString;
|
|
220
304
|
}
|
|
221
305
|
renameColumn(version, table, oldColumn, newColumn) {
|
|
222
|
-
if (
|
|
306
|
+
if (!this.versionIsRelevant(version))
|
|
223
307
|
return;
|
|
224
308
|
const entry = this.getEntry(table);
|
|
225
309
|
const existingColumnEntry = entry.renamedColumns.find((entry2) => entry2.newName == oldColumn);
|
|
@@ -228,36 +312,12 @@ var Migrations = class {
|
|
|
228
312
|
else
|
|
229
313
|
entry.renamedColumns.push({ oldName: oldColumn, newName: newColumn });
|
|
230
314
|
}
|
|
231
|
-
recreateTableImp(table) {
|
|
232
|
-
const entry = this.getEntry(table);
|
|
233
|
-
entry.recreate = true;
|
|
234
|
-
}
|
|
235
315
|
recreateTable(version, table) {
|
|
236
|
-
if (
|
|
316
|
+
if (!this.versionIsRelevant(version))
|
|
237
317
|
return;
|
|
238
|
-
this.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return this.migrationData;
|
|
242
|
-
}
|
|
243
|
-
loopRenamedColumns(tableName, callback) {
|
|
244
|
-
const migrationEntry = this.migrationData[tableName];
|
|
245
|
-
for (const renamingData of migrationEntry.renamedColumns) {
|
|
246
|
-
callback(renamingData.oldName, renamingData.newName);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
getNewestTableName(tableName) {
|
|
250
|
-
return this.migrationDataForOldTableNames[tableName]?.tableRenaming?.newName ?? tableName;
|
|
251
|
-
}
|
|
252
|
-
getOldTableName(tableName) {
|
|
253
|
-
return this.migrationData[tableName]?.tableRenaming?.oldName ?? tableName;
|
|
254
|
-
}
|
|
255
|
-
getNewestColumnName(tableName, oldColumnName) {
|
|
256
|
-
const columnNames = this.migrationData[tableName]?.renamedColumns.find((columns) => columns.oldName == oldColumnName);
|
|
257
|
-
return columnNames ? columnNames.newName : oldColumnName;
|
|
258
|
-
}
|
|
259
|
-
willBeRecreated(tableName) {
|
|
260
|
-
return this.migrationData[tableName]?.recreate;
|
|
318
|
+
const entry = this.getEntry(table);
|
|
319
|
+
entry.recreate = true;
|
|
320
|
+
Logger.log(`Table ${this.getTableName(table)} will be recreated!`);
|
|
261
321
|
}
|
|
262
322
|
};
|
|
263
323
|
|
|
@@ -474,7 +534,6 @@ ${changes.up}
|
|
|
474
534
|
const migrationEntry = migrationData[tableName];
|
|
475
535
|
if (!migrationEntry.recreate)
|
|
476
536
|
continue;
|
|
477
|
-
Logger.log(`Table ${tableName} will be recreated!`);
|
|
478
537
|
this.migrations.compareWithAllowedMigration(tableName, "recreateTable");
|
|
479
538
|
if (!this.dialect.canInspectForeignKeys || !this.dialect.canInspectPrimaryKey)
|
|
480
539
|
this.migrations.compareWithAllowedMigration(tableName, "continueWithoutRollback");
|
|
@@ -521,7 +580,7 @@ ${changes.up}
|
|
|
521
580
|
this.dialect.foreignKey(oldForeignKey.fromColumn, oldForeignKey.toTable, oldForeignKey.toColumn, oldForeignKey.onUpdate, oldForeignKey.onDelete)
|
|
522
581
|
);
|
|
523
582
|
} else {
|
|
524
|
-
this.migrations.
|
|
583
|
+
this.migrations.internalRecreate(structure.table, "Dialect does not support altering foreign keys");
|
|
525
584
|
checkForNewForeignKeys = false;
|
|
526
585
|
}
|
|
527
586
|
} else {
|
|
@@ -538,7 +597,7 @@ ${changes.up}
|
|
|
538
597
|
this.dialect.foreignKey(oldForeignKey.fromColumn, oldForeignKey.toTable, oldForeignKey.toColumn, oldForeignKey.onUpdate, oldForeignKey.onDelete)
|
|
539
598
|
) + this.dialect.removeForeignKey(newForeignKey.fromTable, newForeignKey.fromColumn);
|
|
540
599
|
} else {
|
|
541
|
-
this.migrations.
|
|
600
|
+
this.migrations.internalRecreate(structure.table, "Dialect does not support altering foreign keys");
|
|
542
601
|
checkForNewForeignKeys = false;
|
|
543
602
|
}
|
|
544
603
|
}
|
|
@@ -557,7 +616,7 @@ ${changes.up}
|
|
|
557
616
|
);
|
|
558
617
|
changes.down += this.dialect.removeForeignKey(newForeignKey.fromTable, newForeignKey.fromColumn);
|
|
559
618
|
} else {
|
|
560
|
-
this.migrations.
|
|
619
|
+
this.migrations.internalRecreate(structure.table, "Dialect does not support altering foreign keys");
|
|
561
620
|
break;
|
|
562
621
|
}
|
|
563
622
|
}
|
|
@@ -595,7 +654,7 @@ ${changes.up}
|
|
|
595
654
|
changes.down += this.dialect.removePrimaryKey(tableName, newPrimaryKey.toString());
|
|
596
655
|
}
|
|
597
656
|
} else
|
|
598
|
-
this.migrations.
|
|
657
|
+
this.migrations.internalRecreate(newTableDefinition.table, "Dialect does not support altering primary keys");
|
|
599
658
|
continue;
|
|
600
659
|
}
|
|
601
660
|
for (const newColumn of newColumnList) {
|
|
@@ -606,7 +665,7 @@ ${changes.up}
|
|
|
606
665
|
changes.up += this.dialect.createColumn(tableName, this.dialect.columnDefinition(newColumn.name, newColumn.type, newColumn.defaultValue, newColumn.isPrimaryKey)) + "\n";
|
|
607
666
|
changes.down += this.dialect.dropColumn(tableName, newColumn.name) + "\n";
|
|
608
667
|
} else if (newColumn.type != oldColumn.type || newColumn.defaultValue != oldColumn.defaultValue) {
|
|
609
|
-
this.migrations.
|
|
668
|
+
this.migrations.internalRecreate(newTableDefinition.table, "Table structure was changed");
|
|
610
669
|
}
|
|
611
670
|
}
|
|
612
671
|
for (const oldColumn of oldColumnList) {
|
|
@@ -715,24 +774,37 @@ ${changes.down}`, { encoding: "utf-8" });
|
|
|
715
774
|
}
|
|
716
775
|
};
|
|
717
776
|
|
|
718
|
-
// src/lib/tableInfo/decorators/
|
|
777
|
+
// src/lib/tableInfo/decorators/TableClass.ts
|
|
719
778
|
import "polyfill-symbol-metadata";
|
|
720
|
-
function
|
|
779
|
+
function TableClass(tableName, primaryKey) {
|
|
721
780
|
return (table, context) => {
|
|
722
|
-
Object.defineProperty(table, "name", { value: tableName, writable: false });
|
|
723
781
|
const tableInfo = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
|
|
724
782
|
tableInfo.primaryKey = primaryKey?.toString();
|
|
725
783
|
if (tableInfo.foreignKeys) {
|
|
726
784
|
for (const foreignKey of tableInfo.foreignKeys) {
|
|
727
785
|
foreignKey.fromTable = tableName;
|
|
786
|
+
if (foreignKey.toTable == table.name)
|
|
787
|
+
foreignKey.toTable = tableName;
|
|
728
788
|
}
|
|
729
789
|
}
|
|
790
|
+
Object.defineProperty(table, "name", { value: tableName, writable: false });
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// src/lib/tableInfo/decorators/DataType.ts
|
|
795
|
+
import "polyfill-symbol-metadata";
|
|
796
|
+
function DataType(type) {
|
|
797
|
+
return (table, context) => {
|
|
798
|
+
const metadata = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
|
|
799
|
+
if (!metadata.dataTypes)
|
|
800
|
+
metadata.dataTypes = {};
|
|
801
|
+
metadata.dataTypes[context.name ?? context] = type;
|
|
730
802
|
};
|
|
731
803
|
}
|
|
732
804
|
|
|
733
805
|
// src/lib/tableInfo/decorators/ForeignKey.ts
|
|
734
806
|
import "polyfill-symbol-metadata";
|
|
735
|
-
function ForeignKey(toTable, toColumn,
|
|
807
|
+
function ForeignKey(toTable, toColumn, options) {
|
|
736
808
|
return (table, context) => {
|
|
737
809
|
const metadata = context?.metadata ? getTableInfoFromMetadata(context.metadata) : getTableInfo(table);
|
|
738
810
|
if (!metadata.foreignKeys)
|
|
@@ -743,8 +815,8 @@ function ForeignKey(toTable, toColumn, onDelete, onUpdate) {
|
|
|
743
815
|
//to stay compatible with old decorator structure (see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#decorator-metadata)
|
|
744
816
|
toTable: toTable.name,
|
|
745
817
|
toColumn: toColumn.toString(),
|
|
746
|
-
onDelete,
|
|
747
|
-
onUpdate
|
|
818
|
+
onDelete: options?.onDelete,
|
|
819
|
+
onUpdate: options?.onUpdate
|
|
748
820
|
});
|
|
749
821
|
};
|
|
750
822
|
}
|
|
@@ -757,32 +829,108 @@ var DefaultSql = class {
|
|
|
757
829
|
canAlterPrimaryKey = false;
|
|
758
830
|
canInspectForeignKeys = false;
|
|
759
831
|
canInspectPrimaryKey = false;
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
832
|
+
types = {
|
|
833
|
+
string: "TEXT",
|
|
834
|
+
number: "INTEGER",
|
|
835
|
+
bigint: "BIGINT",
|
|
836
|
+
boolean: "BOOLEAN",
|
|
837
|
+
date: "DATE",
|
|
838
|
+
time: "TIME",
|
|
839
|
+
dateTime: "DATETIME",
|
|
840
|
+
null: "NULL"
|
|
841
|
+
};
|
|
765
842
|
constructor(db) {
|
|
766
843
|
this.db = db;
|
|
767
844
|
}
|
|
768
|
-
|
|
769
|
-
|
|
845
|
+
/**
|
|
846
|
+
* Formats a given value to a SQL-equivalent string based on the provided data type.
|
|
847
|
+
*
|
|
848
|
+
* @param value - The value to be formatted.
|
|
849
|
+
* @param type - The data type of the value. Either determined through typeof or {@link TableInfo} setting
|
|
850
|
+
* @return A string representation of the value formatted for SQL.
|
|
851
|
+
*/
|
|
852
|
+
formatValueToSql(value, type) {
|
|
853
|
+
function toDate(value2) {
|
|
854
|
+
return value2 instanceof Date ? value2 : new Date(value2);
|
|
855
|
+
}
|
|
856
|
+
switch (type) {
|
|
857
|
+
case "string":
|
|
858
|
+
return `"${value}"`;
|
|
859
|
+
case "time":
|
|
860
|
+
return toDate(value).toISOString().slice(11, 19);
|
|
861
|
+
case "date":
|
|
862
|
+
return toDate(value).toISOString().slice(0, 10);
|
|
863
|
+
case "dateTime":
|
|
864
|
+
return toDate(value).toISOString().slice(0, 19).replace("T", " ");
|
|
865
|
+
default:
|
|
866
|
+
return value.toString();
|
|
867
|
+
}
|
|
770
868
|
}
|
|
869
|
+
/**
|
|
870
|
+
* Query to enable / disable foreign keys in the database.
|
|
871
|
+
* Is dialect specific.
|
|
872
|
+
*
|
|
873
|
+
* @param enabled - A boolean indicating whether to enable or disable foreign key constraints.
|
|
874
|
+
* @return The query
|
|
875
|
+
*/
|
|
771
876
|
changeForeignKeysState(enabled) {
|
|
772
877
|
return "";
|
|
773
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Query to add a foreign key to a specified table.
|
|
881
|
+
* Is only used if {@link canAlterForeignKeys} is true.
|
|
882
|
+
*
|
|
883
|
+
* @param fromTableName - The name of the table to which the foreign key will be added.
|
|
884
|
+
* @param foreignKey - The foreign key definition to be added, see {@link foreignKey()}.
|
|
885
|
+
* @return The SQL statement that adds the foreign key to the specified table.
|
|
886
|
+
*/
|
|
774
887
|
addForeignKey(fromTableName, foreignKey) {
|
|
775
888
|
throw new Error("Adding foreign keys is not supported!");
|
|
776
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* Query to remove a foreign key from a specified table.
|
|
892
|
+
* Is only used if {@link canAlterForeignKeys} is true.
|
|
893
|
+
*
|
|
894
|
+
* @param tableName - The name of the table to which the foreign key will be added.
|
|
895
|
+
* @param foreignKeyName - The name of the foreign key definition.
|
|
896
|
+
* @return The SQL statement that removes the foreign key from the specified table.
|
|
897
|
+
*/
|
|
777
898
|
removeForeignKey(tableName, foreignKeyName) {
|
|
778
899
|
throw new Error("Foreign key removal is not supported!");
|
|
779
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Query to add a primary key to the specified table.
|
|
903
|
+
* Is only used if {@link canAlterPrimaryKey} is true.
|
|
904
|
+
*
|
|
905
|
+
* @param tableName - The name of the table to which the primary key will be added.
|
|
906
|
+
* @param columnName - The name of the column that will be set as the primary key.
|
|
907
|
+
* @return A SQL statement to add a primary key to the specified table and column.
|
|
908
|
+
*/
|
|
780
909
|
addPrimaryKey(tableName, columnName) {
|
|
781
910
|
throw new Error("Adding foreign keys is not supported!");
|
|
782
911
|
}
|
|
912
|
+
/**
|
|
913
|
+
* Query to remove a primary key from the specified table.
|
|
914
|
+
* Is only used if {@link canAlterPrimaryKey} is true.
|
|
915
|
+
*
|
|
916
|
+
* @param tableName - The name of the table to which the primary key will be added.
|
|
917
|
+
* @param columnName - The name of the column that will be set as the primary key.
|
|
918
|
+
* @return A SQL statement to remove a primary key from the specified table and column.
|
|
919
|
+
*/
|
|
783
920
|
removePrimaryKey(tableName, columnName) {
|
|
784
921
|
throw new Error("Foreign key removal is not supported!");
|
|
785
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Constructs a SQL FOREIGN KEY constraint clause.
|
|
925
|
+
* Used in combination with {@link addForeignKey} or {@link createTable}
|
|
926
|
+
*
|
|
927
|
+
* @param column - The name of the column in the current table to apply the foreign key constraint.
|
|
928
|
+
* @param foreignTable - The name of the referenced table.
|
|
929
|
+
* @param foreignColumn - The name of the referenced column in the foreign table.
|
|
930
|
+
* @param onUpdate - Optional action to specify the behavior on update (e.g., CASCADE, SET NULL).
|
|
931
|
+
* @param onDelete - Optional action to specify the behavior on delete (e.g., CASCADE, SET NULL).
|
|
932
|
+
* @return The SQL string representing the foreign key constraint.
|
|
933
|
+
*/
|
|
786
934
|
foreignKey(column, foreignTable, foreignColumn, onUpdate, onDelete) {
|
|
787
935
|
let query = `FOREIGN KEY (${column}) REFERENCES ${foreignTable} (${foreignColumn})`;
|
|
788
936
|
if (onUpdate)
|
|
@@ -832,7 +980,7 @@ var DefaultSql = class {
|
|
|
832
980
|
}
|
|
833
981
|
migrationTableQuery() {
|
|
834
982
|
return this.createTable(MIGRATION_DATA_TABLE_NAME, [
|
|
835
|
-
this.columnDefinition("version", this.
|
|
983
|
+
this.columnDefinition("version", this.types.number, "0", false)
|
|
836
984
|
]);
|
|
837
985
|
}
|
|
838
986
|
async getForeignKeys(tableName) {
|
|
@@ -861,8 +1009,16 @@ UPDATE ${MIGRATION_DATA_TABLE_NAME} SET version = ${newVersion} WHERE EXISTS (SE
|
|
|
861
1009
|
|
|
862
1010
|
// src/lib/dialects/SqliteDialect.ts
|
|
863
1011
|
var SqliteDialect = class extends DefaultSql {
|
|
864
|
-
|
|
865
|
-
|
|
1012
|
+
types = {
|
|
1013
|
+
string: "TEXT",
|
|
1014
|
+
number: "INTEGER",
|
|
1015
|
+
bigint: "INTEGER",
|
|
1016
|
+
boolean: "INTEGER",
|
|
1017
|
+
date: "DATE",
|
|
1018
|
+
time: "TIME",
|
|
1019
|
+
dateTime: "DATETIME",
|
|
1020
|
+
null: "NULL"
|
|
1021
|
+
};
|
|
866
1022
|
canAlterForeignKeys = false;
|
|
867
1023
|
canAlterPrimaryKey = false;
|
|
868
1024
|
canInspectForeignKeys = true;
|
|
@@ -884,12 +1040,19 @@ var SqliteDialect = class extends DefaultSql {
|
|
|
884
1040
|
};
|
|
885
1041
|
});
|
|
886
1042
|
}
|
|
887
|
-
formatValueToSql(value) {
|
|
888
|
-
|
|
1043
|
+
formatValueToSql(value, type) {
|
|
1044
|
+
function toDate(value2) {
|
|
1045
|
+
return value2 instanceof Date ? value2 : new Date(value2);
|
|
1046
|
+
}
|
|
1047
|
+
switch (type) {
|
|
889
1048
|
case "boolean":
|
|
890
1049
|
return value ? "1" : "0";
|
|
1050
|
+
case "date":
|
|
1051
|
+
case "time":
|
|
1052
|
+
case "dateTime":
|
|
1053
|
+
return toDate(value).getTime().toString();
|
|
891
1054
|
default:
|
|
892
|
-
return
|
|
1055
|
+
return super.formatValueToSql(value, type);
|
|
893
1056
|
}
|
|
894
1057
|
}
|
|
895
1058
|
async getForeignKeys(tableName) {
|
|
@@ -1126,8 +1289,10 @@ async function rollback(db, dbInstructions, toVersion) {
|
|
|
1126
1289
|
await dialect.setVersion(toVersion);
|
|
1127
1290
|
}
|
|
1128
1291
|
export {
|
|
1129
|
-
|
|
1292
|
+
DataType,
|
|
1130
1293
|
ForeignKey,
|
|
1294
|
+
TableClass,
|
|
1295
|
+
TableObj,
|
|
1131
1296
|
prepareAndRunMigration,
|
|
1132
1297
|
prepareMigration,
|
|
1133
1298
|
rollback,
|