sqlmorpheus 0.1.2 → 0.1.4

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 (55) hide show
  1. package/dist/index.d.mts +17 -1
  2. package/dist/index.d.ts +126 -9
  3. package/dist/index.js +947 -47
  4. package/dist/index.mjs +3 -1
  5. package/package.json +3 -3
  6. package/dist/lib/Logger.d.ts +0 -10
  7. package/dist/lib/Logger.js +0 -24
  8. package/dist/lib/MigrationHistoryManager.d.ts +0 -12
  9. package/dist/lib/MigrationHistoryManager.js +0 -47
  10. package/dist/lib/MigrationManager.d.ts +0 -27
  11. package/dist/lib/MigrationManager.js +0 -331
  12. package/dist/lib/TableStructureGenerator.d.ts +0 -10
  13. package/dist/lib/TableStructureGenerator.js +0 -69
  14. package/dist/lib/dialects/DefaultSql.d.ts +0 -34
  15. package/dist/lib/dialects/DefaultSql.js +0 -79
  16. package/dist/lib/dialects/MsSqlDialect.d.ts +0 -18
  17. package/dist/lib/dialects/MsSqlDialect.js +0 -53
  18. package/dist/lib/dialects/MySqlDialect.d.ts +0 -18
  19. package/dist/lib/dialects/MySqlDialect.js +0 -53
  20. package/dist/lib/dialects/PostgresDialect.d.ts +0 -16
  21. package/dist/lib/dialects/PostgresDialect.js +0 -42
  22. package/dist/lib/dialects/SqliteDialect.d.ts +0 -16
  23. package/dist/lib/dialects/SqliteDialect.js +0 -53
  24. package/dist/lib/exceptions/NotAllowedException.d.ts +0 -4
  25. package/dist/lib/exceptions/NotAllowedException.js +0 -31
  26. package/dist/lib/tableInfo/TableInfo.d.ts +0 -9
  27. package/dist/lib/tableInfo/TableInfo.js +0 -20
  28. package/dist/lib/tableInfo/TableObjects.d.ts +0 -6
  29. package/dist/lib/tableInfo/TableObjects.js +0 -2
  30. package/dist/lib/tableInfo/decorators/DbTable.d.ts +0 -2
  31. package/dist/lib/tableInfo/decorators/DbTable.js +0 -16
  32. package/dist/lib/tableInfo/decorators/ForeignKey.d.ts +0 -4
  33. package/dist/lib/tableInfo/decorators/ForeignKey.js +0 -20
  34. package/dist/lib/typings/AllowedMigrations.d.ts +0 -9
  35. package/dist/lib/typings/AllowedMigrations.js +0 -2
  36. package/dist/lib/typings/BackendTable.d.ts +0 -7
  37. package/dist/lib/typings/BackendTable.js +0 -2
  38. package/dist/lib/typings/ColumnInfo.d.ts +0 -6
  39. package/dist/lib/typings/ColumnInfo.js +0 -2
  40. package/dist/lib/typings/DatabaseAccess.d.ts +0 -5
  41. package/dist/lib/typings/DatabaseAccess.js +0 -2
  42. package/dist/lib/typings/DatabaseInstructions.d.ts +0 -26
  43. package/dist/lib/typings/DatabaseInstructions.js +0 -2
  44. package/dist/lib/typings/ForeignKeyInfo.d.ts +0 -9
  45. package/dist/lib/typings/ForeignKeyInfo.js +0 -2
  46. package/dist/lib/typings/MigrationHistory.d.ts +0 -7
  47. package/dist/lib/typings/MigrationHistory.js +0 -15
  48. package/dist/lib/typings/MigrationInstructions.d.ts +0 -10
  49. package/dist/lib/typings/MigrationInstructions.js +0 -2
  50. package/dist/lib/typings/Migrations.d.ts +0 -20
  51. package/dist/lib/typings/Migrations.js +0 -83
  52. package/dist/lib/typings/SqlChanges.d.ts +0 -4
  53. package/dist/lib/typings/SqlChanges.js +0 -2
  54. package/dist/lib/typings/TableStructure.d.ts +0 -8
  55. package/dist/lib/typings/TableStructure.js +0 -2
package/dist/index.mjs CHANGED
@@ -218,7 +218,7 @@ var MigrationHistoryManager = class {
218
218
  lastVersion = 0;
219
219
  constructor(configPath) {
220
220
  this.configPath = configPath;
221
- this.migrationsPath = `${configPath}/migrations/`;
221
+ this.migrationsPath = `${configPath}/migrations`;
222
222
  mkdirSync(this.configPath, { recursive: true });
223
223
  mkdirSync(this.migrationsPath, { recursive: true });
224
224
  }
@@ -240,6 +240,7 @@ var MigrationHistoryManager = class {
240
240
  throw new Error(`Migration ${upPath} already exists!`);
241
241
  else if (existsSync(downPath) && !overwriteExisting)
242
242
  throw new Error(`Migration ${downPath} already exists!`);
243
+ Logger.log(`Save migrations to ${this.migrationsPath}`);
243
244
  writeFileSync(`${this.migrationsPath}/${FILENAME_UP_PREFIX}${toVersion}.sql`, `-- From: Version ${fromVersion}
244
245
  -- To: Version ${toVersion}
245
246
  ${changes.up}`, { encoding: "utf-8" });
@@ -840,6 +841,7 @@ ${foreignKeyOnQuery}`;
840
841
  };
841
842
 
842
843
  // src/lib/tableInfo/decorators/DbTable.ts
844
+ import "polyfill-symbol-metadata";
843
845
  function DbTable(tableName, primaryKey) {
844
846
  return (table, context) => {
845
847
  Object.defineProperty(table, "name", { value: tableName, writable: false });
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "sqlmorpheus",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "author": "JodliDev",
5
5
  "keywords": [],
6
6
  "license": "MIT",
7
7
  "description": "",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/JodliDev/SqlMorpheus"
10
+ "url": "git://github.com/JodliDev/SqlMorpheus.git"
11
11
  },
12
12
  "bugs": {
13
13
  "url": "https://github.com/JodliDev/SqlMorpheus/issues"
@@ -23,7 +23,7 @@
23
23
  "dev": "tsup --watch",
24
24
  "test": "vitest run",
25
25
  "test:watch": "vitest",
26
- "publish": "tsc && npm publish"
26
+ "publish": "npm publish"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/better-sqlite3": "^7.6.13",
@@ -1,10 +0,0 @@
1
- export type LoggerMode = "silent" | "noLog" | "normal" | "debug";
2
- declare class LoggerClass {
3
- mode: LoggerMode;
4
- setMode(mode?: LoggerMode): void;
5
- debug(text: string): void;
6
- log(text: string): void;
7
- warn(text: string): void;
8
- }
9
- export declare const Logger: LoggerClass;
10
- export {};
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Logger = void 0;
4
- class LoggerClass {
5
- mode = "normal";
6
- setMode(mode) {
7
- this.mode = mode ?? "normal";
8
- }
9
- debug(text) {
10
- if (this.mode == "debug")
11
- console.log(text);
12
- }
13
- log(text) {
14
- if (this.mode == "silent" || this.mode == "noLog")
15
- return;
16
- console.log(text);
17
- }
18
- warn(text) {
19
- if (this.mode == "silent")
20
- return;
21
- console.warn(text);
22
- }
23
- }
24
- exports.Logger = new LoggerClass();
@@ -1,12 +0,0 @@
1
- import { SqlChanges } from "./typings/SqlChanges";
2
- export default class MigrationHistoryManager {
3
- private readonly configPath;
4
- private readonly migrationsPath;
5
- private lastVersion;
6
- constructor(configPath: string);
7
- getLastHistoryVersion(): number;
8
- setLastHistoryVersion(version: number): void;
9
- createMigrationHistory(toVersion: number, changes: SqlChanges, overwriteExisting?: boolean): void;
10
- getUpMigration(toVersion?: number): string;
11
- getDownMigration(version: number): string;
12
- }
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const node_fs_1 = require("node:fs");
4
- const fs_1 = require("fs");
5
- const FILENAME_UP_PREFIX = "up_to_";
6
- const FILENAME_DOWN_PREFIX = "down_to_";
7
- class MigrationHistoryManager {
8
- configPath;
9
- migrationsPath;
10
- lastVersion = 0;
11
- constructor(configPath) {
12
- this.configPath = configPath;
13
- this.migrationsPath = `${configPath}/migrations/`;
14
- (0, node_fs_1.mkdirSync)(this.configPath, { recursive: true });
15
- (0, node_fs_1.mkdirSync)(this.migrationsPath, { recursive: true });
16
- }
17
- getLastHistoryVersion() {
18
- if (this.lastVersion)
19
- return this.lastVersion;
20
- const path = `${this.configPath}/last_version.txt`;
21
- this.lastVersion = (0, node_fs_1.existsSync)(path)
22
- ? parseInt((0, fs_1.readFileSync)(`${this.configPath}/last_version.txt`, { encoding: 'utf-8' })) ?? 0
23
- : 0;
24
- return this.lastVersion;
25
- }
26
- setLastHistoryVersion(version) {
27
- (0, node_fs_1.writeFileSync)(`${this.configPath}/last_version.txt`, version.toString(), { encoding: 'utf-8' });
28
- }
29
- createMigrationHistory(toVersion, changes, overwriteExisting) {
30
- const fromVersion = this.getLastHistoryVersion();
31
- const upPath = `${this.migrationsPath}/${FILENAME_UP_PREFIX}${toVersion}.sql`;
32
- const downPath = `${this.migrationsPath}/${FILENAME_DOWN_PREFIX}${fromVersion}.sql`;
33
- if ((0, node_fs_1.existsSync)(upPath) && !overwriteExisting)
34
- throw new Error(`Migration ${upPath} already exists!`);
35
- else if ((0, node_fs_1.existsSync)(downPath) && !overwriteExisting)
36
- throw new Error(`Migration ${downPath} already exists!`);
37
- (0, node_fs_1.writeFileSync)(`${this.migrationsPath}/${FILENAME_UP_PREFIX}${toVersion}.sql`, `-- From: Version ${fromVersion}\n-- To: Version ${toVersion}\n${changes.up}`, { encoding: 'utf-8' });
38
- (0, node_fs_1.writeFileSync)(`${this.migrationsPath}/${FILENAME_DOWN_PREFIX}${fromVersion}.sql`, `-- From: Version ${toVersion}\n-- To: Version ${fromVersion}\n${changes.down}`, { encoding: 'utf-8' });
39
- }
40
- getUpMigration(toVersion) {
41
- return (0, fs_1.readFileSync)(`${this.migrationsPath}/${FILENAME_UP_PREFIX}${toVersion ?? this.getLastHistoryVersion()}.sql`, { encoding: 'utf-8' });
42
- }
43
- getDownMigration(version) {
44
- return (0, fs_1.readFileSync)(`${this.migrationsPath}/${FILENAME_DOWN_PREFIX}${version}.sql`, { encoding: 'utf-8' });
45
- }
46
- }
47
- exports.default = MigrationHistoryManager;
@@ -1,27 +0,0 @@
1
- import DatabaseInstructions from "./typings/DatabaseInstructions";
2
- import { DatabaseAccess } from "./typings/DatabaseAccess";
3
- import { SqlChanges } from "./typings/SqlChanges";
4
- export declare class MigrationManager {
5
- private migrations;
6
- private readonly tableStructureGenerator;
7
- private existingTables;
8
- private readonly db;
9
- private readonly dbInstructions;
10
- private readonly migrationHistoryManager;
11
- private readonly dialect;
12
- constructor(db: DatabaseAccess, dbInstructions: DatabaseInstructions);
13
- getMigrateSql(): Promise<SqlChanges | null>;
14
- prepareMigration(overwriteExisting?: boolean): Promise<void>;
15
- private createAndDropTables;
16
- private createTableSql;
17
- private tableDoesNotExists;
18
- private recreateTables;
19
- private migrateForeignKeys;
20
- /**
21
- * Checks all columns of all tables, creates them if they do not exist in the database and modifies them if needed.
22
- * If types, default values or primary key change, the table is recreated
23
- */
24
- private migrateColumns;
25
- private getPrimaryKeyColumn;
26
- private renameColumns;
27
- }
@@ -1,331 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MigrationManager = void 0;
7
- const TableStructureGenerator_1 = __importDefault(require("./TableStructureGenerator"));
8
- const Migrations_1 = require("./typings/Migrations");
9
- const MigrationHistoryManager_1 = __importDefault(require("./MigrationHistoryManager"));
10
- const SqliteDialect_1 = __importDefault(require("./dialects/SqliteDialect"));
11
- const PostgresDialect_1 = __importDefault(require("./dialects/PostgresDialect"));
12
- const MsSqlDialect_1 = __importDefault(require("./dialects/MsSqlDialect"));
13
- const MySqlDialect_1 = __importDefault(require("./dialects/MySqlDialect"));
14
- const Logger_1 = require("./Logger");
15
- class MigrationManager {
16
- migrations = new Migrations_1.Migrations();
17
- tableStructureGenerator;
18
- existingTables = [];
19
- db;
20
- dbInstructions;
21
- migrationHistoryManager;
22
- dialect;
23
- constructor(db, dbInstructions) {
24
- switch (dbInstructions.dialect) {
25
- case "Sqlite":
26
- this.dialect = new SqliteDialect_1.default();
27
- break;
28
- case "Postgres":
29
- this.dialect = new PostgresDialect_1.default();
30
- break;
31
- case "MsSql":
32
- this.dialect = new MsSqlDialect_1.default();
33
- break;
34
- case "MySql":
35
- this.dialect = new MySqlDialect_1.default();
36
- break;
37
- default:
38
- throw new Error(`Unknown dialect ${dbInstructions.dialect}`);
39
- }
40
- this.db = db;
41
- this.dbInstructions = dbInstructions;
42
- this.tableStructureGenerator = new TableStructureGenerator_1.default(dbInstructions, this.dialect);
43
- this.migrationHistoryManager = new MigrationHistoryManager_1.default(this.dbInstructions.configPath);
44
- }
45
- async getMigrateSql() {
46
- if (this.dbInstructions.version <= 0)
47
- throw new Error("Cannot migrate to version 0 or lower");
48
- const fromVersion = this.migrationHistoryManager.getLastHistoryVersion();
49
- if (fromVersion == 0) {
50
- Logger_1.Logger.log(`Creating initial migration to version ${this.dbInstructions.version}`);
51
- return this.createAndDropTables();
52
- }
53
- if (fromVersion == this.dbInstructions.version) {
54
- Logger_1.Logger.log("Version has not changed. No migrations needed.");
55
- return null;
56
- }
57
- if (fromVersion > this.dbInstructions.version)
58
- throw new Error(`You cannot create new migrations with a lower version (from ${fromVersion} to ${this.dbInstructions.version})`);
59
- Logger_1.Logger.log(`Creating migration SQL from version ${fromVersion} to ${this.dbInstructions.version}`);
60
- const db = this.db;
61
- await db.createBackup?.(`from_${fromVersion}_to_${this.dbInstructions.version}`);
62
- this.existingTables = await this.dialect.getTableNames(this.db);
63
- const foreignKeyOffQuery = this.dialect.changeForeignKeysState(false);
64
- const changes = {
65
- up: foreignKeyOffQuery,
66
- down: foreignKeyOffQuery
67
- };
68
- //Run pre-migrations:
69
- const preSQL = this.dbInstructions.preMigration?.(this.migrations, fromVersion, this.dbInstructions.version);
70
- if (preSQL) {
71
- changes.up += `\n\n-- Custom SQL from preMigration()\n${preSQL.up}`;
72
- changes.down += `\n\n-- Custom SQL from preMigration()\n${preSQL.down}`;
73
- }
74
- [
75
- await this.createAndDropTables(),
76
- await this.migrateForeignKeys(),
77
- await this.migrateColumns(),
78
- this.renameColumns(),
79
- await this.recreateTables()
80
- ].forEach(entry => {
81
- changes.up += entry.up;
82
- changes.down += entry.down;
83
- });
84
- //Run post-migrations:
85
- const postSql = this.dbInstructions.postMigration?.(fromVersion, this.dbInstructions.version);
86
- if (postSql) {
87
- changes.up += `\n\n-- Custom SQL from postMigration()\n${postSql.up}`;
88
- changes.down += `\n\n-- Custom SQL from postMigration()\n${postSql.down}`;
89
- }
90
- //Enable foreign key constraints again:
91
- const foreignKeyOnQuery = this.dialect.changeForeignKeysState(true);
92
- changes.up += `\n\n${foreignKeyOnQuery}`;
93
- changes.down += `\n\n${foreignKeyOnQuery}`;
94
- return changes;
95
- }
96
- async prepareMigration(overwriteExisting) {
97
- const changes = await this.getMigrateSql();
98
- if (!changes)
99
- return;
100
- this.migrationHistoryManager.createMigrationHistory(this.dbInstructions.version, changes, overwriteExisting);
101
- }
102
- async createAndDropTables() {
103
- let changes = {
104
- up: "\n\n-- Create tables\n",
105
- down: "\n\n-- Create tables\n"
106
- };
107
- for (const tableName in this.tableStructureGenerator.tables) {
108
- if (this.tableDoesNotExists(tableName)) {
109
- const structure = this.tableStructureGenerator.tables[tableName];
110
- changes.up += `${this.createTableSql(tableName, structure.columns, structure.foreignKeys)}\n`;
111
- changes.down += `${this.dialect.dropTable(tableName)}\n`;
112
- }
113
- }
114
- for (const tableName of this.existingTables) {
115
- if (!this.tableStructureGenerator.tables[tableName]) {
116
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "dropTable");
117
- if (!this.dialect.canInspectForeignKeys || !this.dialect.canInspectPrimaryKey)
118
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "continueWithoutRollback");
119
- changes.up += `${this.dialect.dropTable(tableName)}\n`;
120
- changes.down += this.dialect.canInspectForeignKeys && this.dialect.canInspectPrimaryKey
121
- ? this.createTableSql(tableName, await this.dialect.getColumnInformation(tableName, this.db), await this.dialect.getForeignKeys(tableName, this.db))
122
- : "\n\n-- Cannot recreate foreign keys or load primary keys with this database! Table will not be recreated!\n";
123
- }
124
- }
125
- return changes;
126
- }
127
- createTableSql(tableName, columns, foreignKeys) {
128
- //columns:
129
- const queryLines = [];
130
- for (const columnInfo of columns) {
131
- queryLines.push(this.dialect.columnDefinition(columnInfo.name, columnInfo.type, columnInfo.defaultValue, columnInfo.isPrimaryKey));
132
- }
133
- //foreign keys:
134
- if (foreignKeys) {
135
- for (const foreignKeyInfo of foreignKeys) {
136
- queryLines.push(this.dialect.foreignKey(foreignKeyInfo.fromColumn, foreignKeyInfo.toTable, foreignKeyInfo.toColumn.toString(), foreignKeyInfo.onUpdate, foreignKeyInfo.onDelete));
137
- }
138
- }
139
- return this.dialect.createTable(tableName, queryLines);
140
- }
141
- tableDoesNotExists(tableName) {
142
- return this.existingTables.indexOf(tableName) == -1;
143
- }
144
- async recreateTables() {
145
- const changes = {
146
- up: "\n\n-- Recreate tables\n",
147
- down: "\n\n-- Recreate tables\n"
148
- };
149
- const migrationData = this.migrations.getMigrationData();
150
- for (const tableName in migrationData) {
151
- const migrationEntry = migrationData[tableName];
152
- if (!migrationEntry.recreate)
153
- continue;
154
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "recreateTable");
155
- if (!this.dialect.canInspectForeignKeys || !this.dialect.canInspectPrimaryKey)
156
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "continueWithoutRollback");
157
- const oldColumnList = await this.dialect.getColumnInformation(tableName, this.db);
158
- const newColumnList = this.tableStructureGenerator.tables[tableName].columns;
159
- const moveableColumns = newColumnList
160
- .filter(entry => oldColumnList.find(oldEntry => oldEntry.name == entry.name) != undefined)
161
- .map(entry => entry.name);
162
- const backupTableName = `${tableName}__backup`;
163
- const insertQuery = this.dialect.insert(backupTableName, this.dialect.insertValues(moveableColumns, this.dialect.select(tableName, moveableColumns)));
164
- const moveDataQuery = insertQuery
165
- + "\n"
166
- + this.dialect.dropTable(tableName)
167
- + "\n"
168
- + this.dialect.renameTable(backupTableName, tableName);
169
- const structure = this.tableStructureGenerator.tables[tableName];
170
- changes.up += this.createTableSql(backupTableName, structure.columns, structure.foreignKeys)
171
- + "\n"
172
- + moveDataQuery;
173
- changes.down += this.dialect.canInspectForeignKeys && this.dialect.canInspectPrimaryKey
174
- ? this.createTableSql(backupTableName, await this.dialect.getColumnInformation(tableName, this.db), await this.dialect.getForeignKeys(tableName, this.db))
175
- + "\n"
176
- + moveDataQuery
177
- : "\n\n-- Cannot recreate foreign keys or load primary keys with this database! Table will not be recreated!\n";
178
- }
179
- return changes;
180
- }
181
- async migrateForeignKeys() {
182
- if (!this.dialect.canAlterForeignKeys)
183
- return { up: "", down: "" };
184
- let changes = {
185
- up: "\n\n-- Foreign keys\n",
186
- down: "\n\n-- Foreign keys\n"
187
- };
188
- for (const tableName in this.tableStructureGenerator.tables) {
189
- if (this.migrations.willBeRecreated(tableName) || this.tableDoesNotExists(tableName))
190
- continue;
191
- const structure = this.tableStructureGenerator.tables[tableName];
192
- const newForeignKeys = structure.foreignKeys ?? [];
193
- const oldForeignKeys = await this.dialect.getForeignKeys(tableName, this.db);
194
- let checkForNewForeignKeys = true;
195
- for (const oldForeignKey of oldForeignKeys) {
196
- const newForeignKey = newForeignKeys.find(entry => entry.fromColumn == oldForeignKey.fromColumn);
197
- //Check for removed foreign key:
198
- if (!newForeignKey) {
199
- Logger_1.Logger.log(`Foreign key ${oldForeignKey.toTable}.${oldForeignKey.toColumn} to ${oldForeignKey.toTable}.${oldForeignKey.toColumn} was removed!`);
200
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "removeForeignKey");
201
- if (this.dialect.canAlterForeignKeys) {
202
- changes.up += this.dialect.removeForeignKey(oldForeignKey.fromTable, oldForeignKey.fromColumn);
203
- changes.down += this.dialect.addForeignKey(oldForeignKey.fromTable, this.dialect.foreignKey(oldForeignKey.fromColumn, oldForeignKey.toTable, oldForeignKey.toColumn, oldForeignKey.onUpdate, oldForeignKey.onDelete));
204
- }
205
- else {
206
- this.migrations.recreateTable(structure.table);
207
- checkForNewForeignKeys = false;
208
- }
209
- }
210
- //Check for altered foreign key:
211
- else {
212
- if (!newForeignKey
213
- || oldForeignKey.toColumn != newForeignKey.toColumn
214
- || ((oldForeignKey.onUpdate ?? "NO ACTION") != (newForeignKey.onUpdate ?? "NO ACTION"))
215
- || ((oldForeignKey.onDelete ?? "NO ACTION") != (newForeignKey.onDelete ?? "NO ACTION"))) {
216
- Logger_1.Logger.log(`Foreign key ${oldForeignKey.toTable}.${oldForeignKey.toColumn} to ${oldForeignKey.toTable}.${oldForeignKey.toColumn} was changed!`);
217
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "alterForeignKey");
218
- if (this.dialect.canAlterForeignKeys) {
219
- changes.up += this.dialect.removeForeignKey(oldForeignKey.fromTable, oldForeignKey.fromColumn)
220
- + this.dialect.addForeignKey(newForeignKey.fromTable, this.dialect.foreignKey(newForeignKey.fromColumn, newForeignKey.toTable, newForeignKey.toColumn, newForeignKey.onUpdate, newForeignKey.onDelete));
221
- changes.down += this.dialect.addForeignKey(oldForeignKey.fromTable, this.dialect.foreignKey(oldForeignKey.fromColumn, oldForeignKey.toTable, oldForeignKey.toColumn, oldForeignKey.onUpdate, oldForeignKey.onDelete)) + this.dialect.removeForeignKey(newForeignKey.fromTable, newForeignKey.fromColumn);
222
- }
223
- else {
224
- this.migrations.recreateTable(structure.table);
225
- checkForNewForeignKeys = false;
226
- }
227
- }
228
- }
229
- }
230
- //Check for new foreign keys:
231
- if (checkForNewForeignKeys) {
232
- for (const newForeignKey of newForeignKeys) {
233
- const oldForeignKey = oldForeignKeys.find(entry => entry.fromColumn == newForeignKey.fromColumn);
234
- if (oldForeignKey)
235
- continue;
236
- Logger_1.Logger.log(`Foreign key ${newForeignKey.toTable}.${newForeignKey.toColumn} to ${newForeignKey.toTable}.${newForeignKey.toColumn} is new!`);
237
- if (this.dialect.canAlterForeignKeys) {
238
- changes.up += this.dialect.addForeignKey(newForeignKey.toTable, this.dialect.foreignKey(newForeignKey.fromColumn, newForeignKey.toTable, newForeignKey.toColumn, newForeignKey.onUpdate, newForeignKey.onDelete));
239
- changes.down += this.dialect.removeForeignKey(newForeignKey.fromTable, newForeignKey.fromColumn);
240
- }
241
- else {
242
- this.migrations.recreateTable(structure.table);
243
- break;
244
- }
245
- }
246
- }
247
- }
248
- return changes;
249
- }
250
- /**
251
- * Checks all columns of all tables, creates them if they do not exist in the database and modifies them if needed.
252
- * If types, default values or primary key change, the table is recreated
253
- */
254
- async migrateColumns() {
255
- const changes = {
256
- up: "\n\n-- Migrate columns\n",
257
- down: "\n\n-- Migrate columns\n"
258
- };
259
- for (const tableName in this.tableStructureGenerator.tables) {
260
- if (this.migrations.willBeRecreated(tableName) || this.tableDoesNotExists(tableName))
261
- continue;
262
- const newTableDefinition = this.tableStructureGenerator.tables[tableName];
263
- const oldColumnList = await this.dialect.getColumnInformation(tableName, this.db);
264
- const oldPrimaryKey = this.dialect.canInspectPrimaryKey ? this.getPrimaryKeyColumn(oldColumnList) : false;
265
- const newColumnList = newTableDefinition.columns;
266
- const newPrimaryKey = newTableDefinition.primaryKey;
267
- //Search for changed primary key:
268
- if (this.dialect.canInspectPrimaryKey && oldPrimaryKey != newPrimaryKey) {
269
- Logger_1.Logger.log(`Primary key in ${tableName} was changed from ${oldPrimaryKey} to ${newPrimaryKey}!`);
270
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "alterPrimaryKey");
271
- if (this.dialect.canAlterPrimaryKey) {
272
- if (oldPrimaryKey) {
273
- changes.up += this.dialect.removePrimaryKey(tableName, oldPrimaryKey);
274
- changes.down += this.dialect.addPrimaryKey(tableName, oldPrimaryKey);
275
- }
276
- if (newPrimaryKey) {
277
- changes.up += this.dialect.addPrimaryKey(tableName, newPrimaryKey.toString());
278
- changes.down += this.dialect.removePrimaryKey(tableName, newPrimaryKey.toString());
279
- }
280
- }
281
- else
282
- this.migrations.recreateTable(newTableDefinition.table);
283
- continue;
284
- }
285
- //Search for added or changed columns:
286
- for (const newColumn of newColumnList) {
287
- const oldColumn = oldColumnList.find(entry => entry.name == newColumn.name);
288
- if (oldColumn == undefined) {
289
- changes.up += this.dialect.createColumn(tableName, this.dialect.columnDefinition(newColumn.name, newColumn.type, newColumn.defaultValue, newColumn.isPrimaryKey)) + "\n";
290
- changes.down += this.dialect.dropColumn(tableName, newColumn.name) + "\n";
291
- }
292
- else if (newColumn.type != oldColumn.type || newColumn.defaultValue != oldColumn.defaultValue) {
293
- this.migrations.recreateTable(newTableDefinition.table);
294
- }
295
- }
296
- //Search for removed columns:
297
- for (const oldColumn of oldColumnList) {
298
- const newColumn = newColumnList.find(entry => entry.name == oldColumn.name);
299
- if (newColumn == undefined) {
300
- this.migrations.throwIfNotAllowed(this.dbInstructions.version, tableName, "dropColumn");
301
- changes.up += this.dialect.dropColumn(tableName, oldColumn.name) + "\n";
302
- changes.down += this.dialect.createColumn(tableName, this.dialect.columnDefinition(oldColumn.name, oldColumn.type, oldColumn.defaultValue, oldColumn.isPrimaryKey)) + "\n";
303
- }
304
- }
305
- }
306
- return changes;
307
- }
308
- getPrimaryKeyColumn(columnInfoList) {
309
- for (const columnInfo of columnInfoList) {
310
- if (columnInfo.isPrimaryKey)
311
- return columnInfo.name;
312
- }
313
- }
314
- renameColumns() {
315
- const changes = {
316
- up: "\n\n-- Rename columns\n",
317
- down: "\n\n-- Rename columns\n"
318
- };
319
- const migrationData = this.migrations.getMigrationData();
320
- for (const tableName in migrationData) {
321
- if (migrationData[tableName].recreate)
322
- continue;
323
- this.migrations.loopRenamedColumns(tableName, (oldColumnName, newColumnName) => {
324
- changes.up += this.dialect.renameColumn(tableName, oldColumnName, newColumnName);
325
- changes.down += this.dialect.renameColumn(tableName, newColumnName, oldColumnName);
326
- });
327
- }
328
- return changes;
329
- }
330
- }
331
- exports.MigrationManager = MigrationManager;
@@ -1,10 +0,0 @@
1
- import DatabaseInstructions from "./typings/DatabaseInstructions";
2
- import { TableStructure } from "./typings/TableStructure";
3
- import DefaultSql from "./dialects/DefaultSql";
4
- export default class TableStructureGenerator {
5
- private readonly dialect;
6
- readonly tables: Record<string, TableStructure>;
7
- constructor(dbContext: DatabaseInstructions, dialect: DefaultSql);
8
- private getExpectedStructure;
9
- private getColumns;
10
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const Logger_1 = require("./Logger");
4
- const TableInfo_1 = require("./tableInfo/TableInfo");
5
- class TableStructureGenerator {
6
- dialect;
7
- tables = {};
8
- constructor(dbContext, dialect) {
9
- this.dialect = dialect;
10
- if (dbContext.tables.length) {
11
- const tableObjects = {};
12
- for (const table of dbContext.tables) {
13
- tableObjects[table.name] = { columns: new table, tableInfo: (0, TableInfo_1.getTableInfo)(table) };
14
- }
15
- this.getExpectedStructure(tableObjects);
16
- }
17
- else {
18
- const tableObjects = dbContext.tables;
19
- this.getExpectedStructure(tableObjects);
20
- }
21
- }
22
- getExpectedStructure(tableObjects) {
23
- for (const tableName in tableObjects) {
24
- const obj = tableObjects[tableName];
25
- const tableInfo = obj.tableInfo;
26
- this.tables[tableName] = {
27
- table: tableName,
28
- primaryKey: tableInfo?.primaryKey,
29
- columns: this.getColumns(obj.columns, tableInfo?.primaryKey),
30
- foreignKeys: tableInfo?.foreignKeys
31
- };
32
- }
33
- }
34
- getColumns(obj, primaryKey) {
35
- const columns = [];
36
- for (const property in obj) {
37
- const propertyKey = property;
38
- const value = obj[propertyKey];
39
- const columnData = {
40
- name: property,
41
- isPrimaryKey: property == primaryKey,
42
- type: "TEXT",
43
- defaultValue: this.dialect.typeNull
44
- };
45
- switch (typeof value) {
46
- case "string":
47
- columnData.type = this.dialect.typeString;
48
- columnData.defaultValue = value === null ? this.dialect.typeNull : `"${this.dialect.formatValueToSql(value)}"`;
49
- break;
50
- case "number":
51
- columnData.type = this.dialect.typeNumber;
52
- columnData.defaultValue = value === null ? this.dialect.typeNull : this.dialect.formatValueToSql(value);
53
- break;
54
- case "boolean":
55
- columnData.type = this.dialect.typeBoolean;
56
- columnData.defaultValue = value === null ? this.dialect.typeNull : this.dialect.formatValueToSql(value);
57
- break;
58
- case "function":
59
- continue;
60
- default:
61
- Logger_1.Logger.warn(`${obj.constructor.name}.${property} was skipped because its type is not supported (${typeof value})`);
62
- continue;
63
- }
64
- columns.push(columnData);
65
- }
66
- return columns;
67
- }
68
- }
69
- exports.default = TableStructureGenerator;
@@ -1,34 +0,0 @@
1
- import { ForeignKeyInfo } from "../typings/ForeignKeyInfo";
2
- import { DatabaseAccess } from "../typings/DatabaseAccess";
3
- import { ColumnInfo } from "../typings/ColumnInfo";
4
- export default abstract class DefaultSql {
5
- canAlterForeignKeys: boolean;
6
- canAlterPrimaryKey: boolean;
7
- canInspectForeignKeys: boolean;
8
- canInspectPrimaryKey: boolean;
9
- typeString: string;
10
- typeNumber: string;
11
- typeBoolean: string;
12
- typeNull: string;
13
- formatValueToSql(value: string | number | boolean): string;
14
- changeForeignKeysState(enabled: boolean): string;
15
- getForeignKeys(tableName: string, db: DatabaseAccess): Promise<ForeignKeyInfo[]>;
16
- addForeignKey(fromTableName: string, foreignKey: string): string;
17
- removeForeignKey(tableName: string, foreignKeyName: string): string;
18
- addPrimaryKey(tableName: string, columnName: string): string;
19
- removePrimaryKey(tableName: string, columnName: string): string;
20
- foreignKey(column: string, foreignTable: string, foreignColumn: string, onUpdate?: string, onDelete?: string): string;
21
- createTable(tableName: string, entries: string[]): string;
22
- renameTable(tableName: string, newTableName: string): string;
23
- dropTable(tableName: string): string;
24
- abstract getColumnInformation(tableName: string, db: DatabaseAccess): Promise<ColumnInfo[]>;
25
- abstract getTableNames(db: DatabaseAccess): Promise<string[]>;
26
- columnDefinition(tableName: string, type: string, defaultValue: string, isPrimaryKey: boolean): string;
27
- createColumn(columnTable: string, entry: string): string;
28
- renameColumn(tableName: string, oldColumnName: string, newColumnName: string): string;
29
- copyColumn(tableName: string, oldColumnName: string, newColumnName: string): string;
30
- dropColumn(tableName: string, columnName: string): string;
31
- select(tableName: string, select: string[], where?: string): string;
32
- insert(tableName: string, content: string): string;
33
- insertValues(keys: string[], valueString?: string): string;
34
- }