@storecraft/database-sql-base 1.3.1 → 1.4.2
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/fix-migration-provider.js +43 -0
- package/migrate.js +50 -59
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
|
|
5
|
+
export class FixedFileMigrationProvider {
|
|
6
|
+
/**
|
|
7
|
+
* @param {{fs: typeof import("fs").promises, path: typeof import("path"), migrationFolder: string}} config
|
|
8
|
+
*/
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.fs = config.fs;
|
|
11
|
+
this.path = config.path;
|
|
12
|
+
this.migrationFolder = config.migrationFolder;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getMigrations() {
|
|
16
|
+
const files = await this.fs.readdir(this.migrationFolder);
|
|
17
|
+
|
|
18
|
+
/** @type {Record<string, any>} */
|
|
19
|
+
const migrations = {};
|
|
20
|
+
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
if (!file.endsWith(".js")) continue;
|
|
23
|
+
|
|
24
|
+
// resolve absolute path to ensure cross-platform consistency
|
|
25
|
+
const fullPath = this.path.resolve(this.migrationFolder, file);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Convert file path to file URL using Node's built-in utility.
|
|
29
|
+
* This avoids manual string manipulation (like regex) and ensures
|
|
30
|
+
* correct behavior across Windows, Linux, and macOS.
|
|
31
|
+
*/
|
|
32
|
+
const fileUrl = pathToFileURL(fullPath).href;
|
|
33
|
+
|
|
34
|
+
const name = file.replace(".js", "");
|
|
35
|
+
|
|
36
|
+
console.log("Provider loading:", fileUrl);
|
|
37
|
+
|
|
38
|
+
migrations[name] = await import(fileUrl);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return migrations;
|
|
42
|
+
}
|
|
43
|
+
}
|
package/migrate.js
CHANGED
|
@@ -3,112 +3,103 @@
|
|
|
3
3
|
* @import { SqlDialectType } from './types.public.js';
|
|
4
4
|
* @import { Migration } from 'kysely';
|
|
5
5
|
*/
|
|
6
|
+
|
|
6
7
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
-
import * as path from
|
|
8
|
-
import { promises as fs } from
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import { promises as fs } from "fs";
|
|
9
10
|
import {
|
|
10
11
|
Migrator,
|
|
11
|
-
FileMigrationProvider,
|
|
12
12
|
Kysely,
|
|
13
|
-
} from
|
|
13
|
+
} from "kysely";
|
|
14
14
|
import { SQL } from "./index.js";
|
|
15
15
|
|
|
16
|
+
// reusing the same provider for all migrations to avoid issues with dynamic imports and file URLs
|
|
17
|
+
import { FixedFileMigrationProvider } from "./fix-migration-provider.js";
|
|
18
|
+
|
|
16
19
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
20
|
const __dirname = path.dirname(__filename);
|
|
18
21
|
|
|
19
22
|
export const current = {
|
|
23
|
+
/** @type {SQL | undefined} */
|
|
20
24
|
driver: undefined
|
|
21
|
-
}
|
|
25
|
+
};
|
|
22
26
|
|
|
23
|
-
export const read_files_in_folder = async (folder=
|
|
27
|
+
export const read_files_in_folder = async (folder = "") => {
|
|
24
28
|
const files = await fs.readdir(folder);
|
|
25
|
-
return files.filter(file => file.endsWith(
|
|
26
|
-
}
|
|
29
|
+
return files.filter(file => file.endsWith(".js"));
|
|
30
|
+
};
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
33
|
* @param {SqlDialectType} dialect_type
|
|
30
34
|
*/
|
|
31
|
-
export const get_migrations = async (dialect_type=
|
|
32
|
-
const folder =
|
|
35
|
+
export const get_migrations = async (dialect_type = "SQLITE") => {
|
|
36
|
+
const folder = "migrations." + dialect_type.toLowerCase();
|
|
33
37
|
const files = await fs.readdir(path.join(__dirname, folder));
|
|
34
38
|
|
|
35
39
|
/** @type {Record<string, Migration>} */
|
|
36
40
|
const migrations = {};
|
|
37
41
|
|
|
38
42
|
for (const file of files) {
|
|
39
|
-
if(file.endsWith(
|
|
40
|
-
const file_name = file.split(
|
|
43
|
+
if (file.endsWith(".js")) {
|
|
44
|
+
const file_name = file.split(".").slice(0, -1).join(".");
|
|
41
45
|
const file_path = path.join(__dirname, folder, file);
|
|
42
46
|
const file_url = pathToFileURL(file_path);
|
|
47
|
+
|
|
43
48
|
const migration = await import(file_url.href);
|
|
44
49
|
migrations[file_name] = migration;
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
return migrations;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// console.log(
|
|
52
|
-
// await get_migrations()
|
|
53
|
-
// )
|
|
54
|
-
|
|
54
|
+
};
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @param {
|
|
59
|
-
* @param {boolean} [release_db_upon_completion=true]
|
|
57
|
+
* @param {SQL} db_driver
|
|
58
|
+
* @param {boolean} [release_db_upon_completion=true]
|
|
60
59
|
*/
|
|
61
|
-
export async function migrateToLatest(db_driver, release_db_upon_completion=true) {
|
|
62
|
-
if(!db_driver?.client)
|
|
63
|
-
throw new Error(
|
|
60
|
+
export async function migrateToLatest(db_driver, release_db_upon_completion = true) {
|
|
61
|
+
if (!db_driver?.client) {
|
|
62
|
+
throw new Error("No Kysely client found !!!");
|
|
63
|
+
}
|
|
64
64
|
|
|
65
|
-
console.log(
|
|
65
|
+
console.log("Resolving migrations. This may take some time...");
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
const db = db_driver.client;
|
|
68
68
|
|
|
69
69
|
current.driver = db_driver;
|
|
70
70
|
|
|
71
|
-
const migrator = new Migrator(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
__dirname,
|
|
80
|
-
`migrations.${db_driver.dialectType.toLowerCase()}`
|
|
81
|
-
),
|
|
82
|
-
}
|
|
71
|
+
const migrator = new Migrator({
|
|
72
|
+
db,
|
|
73
|
+
provider: new FixedFileMigrationProvider({
|
|
74
|
+
fs,
|
|
75
|
+
path,
|
|
76
|
+
migrationFolder: path.join(
|
|
77
|
+
__dirname,
|
|
78
|
+
`migrations.${db_driver.dialectType.toLowerCase()}`
|
|
83
79
|
),
|
|
84
|
-
}
|
|
85
|
-
);
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
86
82
|
|
|
87
83
|
const { error, results } = await migrator.migrateToLatest();
|
|
88
84
|
|
|
89
|
-
results?.forEach(
|
|
90
|
-
(it)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
95
|
-
} else if (it.status === 'Error') {
|
|
96
|
-
console.error(
|
|
97
|
-
`failed to execute migration "${it.migrationName}"`
|
|
98
|
-
);
|
|
99
|
-
}
|
|
85
|
+
results?.forEach((it) => {
|
|
86
|
+
if (it.status === "Success") {
|
|
87
|
+
console.log(`migration "${it.migrationName}" was executed successfully`);
|
|
88
|
+
} else if (it.status === "Error") {
|
|
89
|
+
console.error(`failed to execute migration "${it.migrationName}"`);
|
|
100
90
|
}
|
|
101
|
-
);
|
|
91
|
+
});
|
|
102
92
|
|
|
103
93
|
if (error) {
|
|
104
|
-
console.error(
|
|
105
|
-
console.error(JSON.stringify(error, null, 2))
|
|
106
|
-
console.error(JSON.stringify(results, null, 2))
|
|
107
|
-
process.exit(1)
|
|
94
|
+
console.error("failed to migrate");
|
|
95
|
+
console.error(JSON.stringify(error, null, 2));
|
|
96
|
+
console.error(JSON.stringify(results, null, 2));
|
|
97
|
+
process.exit(1);
|
|
108
98
|
}
|
|
109
99
|
|
|
110
|
-
console.log(
|
|
100
|
+
console.log("Resolving migrations COMPLETE.");
|
|
111
101
|
|
|
112
|
-
if(release_db_upon_completion)
|
|
102
|
+
if (release_db_upon_completion) {
|
|
113
103
|
await db.destroy();
|
|
114
|
-
}
|
|
104
|
+
}
|
|
105
|
+
}
|