@mikeyt23/node-cli-utils 2.0.17 → 2.0.18
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/README.md +4 -48
- package/dist/cjs/DependencyChecker.d.ts +1 -0
- package/dist/cjs/DependencyChecker.d.ts.map +1 -1
- package/dist/cjs/DependencyChecker.js +16 -9
- package/dist/cjs/NugetUtility.d.ts +67 -0
- package/dist/cjs/NugetUtility.d.ts.map +1 -0
- package/dist/cjs/NugetUtility.js +256 -0
- package/dist/cjs/TarballUtility.d.ts +1 -1
- package/dist/cjs/TarballUtility.js +1 -1
- package/dist/cjs/dotnetUtils.d.ts +1 -0
- package/dist/cjs/dotnetUtils.d.ts.map +1 -1
- package/dist/cjs/dotnetUtils.js +4 -2
- package/dist/cjs/generalUtils.d.ts +11 -1
- package/dist/cjs/generalUtils.d.ts.map +1 -1
- package/dist/cjs/generalUtils.js +44 -13
- package/dist/cjs/generalUtilsInternal.d.ts +6 -0
- package/dist/cjs/generalUtilsInternal.d.ts.map +1 -1
- package/dist/cjs/generalUtilsInternal.js +33 -2
- package/dist/cjs/runWhileParentAlive.js +2 -2
- package/dist/esm/DependencyChecker.d.ts +1 -0
- package/dist/esm/DependencyChecker.d.ts.map +1 -1
- package/dist/esm/DependencyChecker.js +14 -8
- package/dist/esm/NugetUtility.d.ts +67 -0
- package/dist/esm/NugetUtility.d.ts.map +1 -0
- package/dist/esm/NugetUtility.js +254 -0
- package/dist/esm/TarballUtility.d.ts +1 -1
- package/dist/esm/TarballUtility.js +1 -1
- package/dist/esm/dotnetUtils.d.ts +1 -0
- package/dist/esm/dotnetUtils.d.ts.map +1 -1
- package/dist/esm/dotnetUtils.js +2 -1
- package/dist/esm/generalUtils.d.ts +11 -1
- package/dist/esm/generalUtils.d.ts.map +1 -1
- package/dist/esm/generalUtils.js +41 -12
- package/dist/esm/generalUtilsInternal.d.ts +6 -0
- package/dist/esm/generalUtilsInternal.d.ts.map +1 -1
- package/dist/esm/generalUtilsInternal.js +30 -1
- package/dist/esm/runWhileParentAlive.js +2 -2
- package/package.json +1 -11
- package/dist/cjs/dbMigrationUtils.d.ts +0 -39
- package/dist/cjs/dbMigrationUtils.d.ts.map +0 -1
- package/dist/cjs/dbMigrationUtils.js +0 -203
- package/dist/esm/dbMigrationUtils.d.ts +0 -39
- package/dist/esm/dbMigrationUtils.d.ts.map +0 -1
- package/dist/esm/dbMigrationUtils.js +0 -191
|
@@ -1,203 +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.efRemoveLastMigration = exports.efAddMigration = exports.efMigrationsUpdate = exports.efMigrationsList = exports.dotnetEfCommand = void 0;
|
|
7
|
-
const generalUtils_js_1 = require("./generalUtils.js");
|
|
8
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
|
-
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
11
|
-
/**
|
|
12
|
-
* Wrapper function for `dotnet ef`. If you don't pass `false` for `noBuild`, be sure the project has already been built by some other means.
|
|
13
|
-
*
|
|
14
|
-
* Docs for "dotnet ef" CLI: https://learn.microsoft.com/en-us/ef/core/cli/dotnet.
|
|
15
|
-
* @param projectPath Path to project that has the DbContext and Migration files used for the `--project` argument
|
|
16
|
-
* @param dbContextName The name of the DbContext class used for the `--context` argument
|
|
17
|
-
* @param args Arguments to pass to the `dotnet ef` CLI
|
|
18
|
-
* @param noBuild If true, the `--no-build` argument will be passed to the `dotnet ef` CLI (default: true)
|
|
19
|
-
*/
|
|
20
|
-
async function dotnetEfCommand(projectPath, dbContextName, args, noBuild = true) {
|
|
21
|
-
(0, generalUtils_js_1.requireValidPath)('projectPath', projectPath);
|
|
22
|
-
(0, generalUtils_js_1.requireString)('dbContextName', dbContextName);
|
|
23
|
-
const result = await (0, generalUtils_js_1.spawnAsync)('dotnet', ['ef', '--project', projectPath, ...args, '--context', dbContextName, ...(noBuild ? ['--no-build'] : [])]);
|
|
24
|
-
return result.code;
|
|
25
|
-
}
|
|
26
|
-
exports.dotnetEfCommand = dotnetEfCommand;
|
|
27
|
-
/**
|
|
28
|
-
* Wrapper function for `dotnet ef migrations list`.
|
|
29
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
30
|
-
* @param dbContextName The name of the DbContext class
|
|
31
|
-
*/
|
|
32
|
-
async function efMigrationsList(projectPath, dbContextName) {
|
|
33
|
-
await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'list']);
|
|
34
|
-
}
|
|
35
|
-
exports.efMigrationsList = efMigrationsList;
|
|
36
|
-
/**
|
|
37
|
-
* Wrapper function for `dotnet ef database update <migration_name>`.
|
|
38
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
39
|
-
* @param dbContextName The name of the DbContext class
|
|
40
|
-
* @param migrationName The name of the migration to update to (optional). If not provided, all migrations will be applied.
|
|
41
|
-
*/
|
|
42
|
-
async function efMigrationsUpdate(projectPath, dbContextName, migrationName) {
|
|
43
|
-
await dotnetEfCommand(projectPath, dbContextName, ['database', 'update', ...(migrationName ? [migrationName] : [])]);
|
|
44
|
-
}
|
|
45
|
-
exports.efMigrationsUpdate = efMigrationsUpdate;
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
49
|
-
* @param dbContextName The name of the DbContext class
|
|
50
|
-
* @param migrationName The name of the migration to add
|
|
51
|
-
* @param withBoilerplate If true, boilerplate will be added to the migration C# file and empty Up and Down SQL files will be created
|
|
52
|
-
*/
|
|
53
|
-
async function efAddMigration(projectPath, dbContextName, migrationName, withBoilerplate = false) {
|
|
54
|
-
const projectDirectory = projectPath.endsWith('.csproj') ? projectPath.substring(0, projectPath.lastIndexOf('/')) : projectPath;
|
|
55
|
-
const migrationsOutputDir = getMigrationsProjectRelativePath(dbContextName);
|
|
56
|
-
await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'add', migrationName, '-o', migrationsOutputDir]);
|
|
57
|
-
if (withBoilerplate) {
|
|
58
|
-
try {
|
|
59
|
-
await addDbMigrationBoilerplate(projectDirectory, dbContextName, migrationName);
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
console.error(error);
|
|
63
|
-
await efRemoveLastMigration(projectPath, dbContextName, true);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
exports.efAddMigration = efAddMigration;
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
71
|
-
* @param dbContextName The name of the DbContext class
|
|
72
|
-
* @param skipConfirm If `true`, the user will not be prompted to confirm the removal of the last migration
|
|
73
|
-
*/
|
|
74
|
-
async function efRemoveLastMigration(projectPath, dbContextName, skipConfirm = false) {
|
|
75
|
-
const lastMigrationName = await getLastMigrationName(projectPath, dbContextName);
|
|
76
|
-
if (!skipConfirm && !await (0, generalUtils_js_1.getConfirmation)(`Are you sure you want to remove the last migration: ➡️${lastMigrationName}?`)) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const returnCode = await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'remove']);
|
|
80
|
-
if (returnCode !== 0) {
|
|
81
|
-
throw new Error(`dotnet ef migrations remove returned non-zero exit code: ${returnCode}`);
|
|
82
|
-
}
|
|
83
|
-
(0, generalUtils_js_1.log)(`Removing migration SQL script files if they're empty`);
|
|
84
|
-
await deleteScriptFileIfEmpty(getScriptPath(projectPath, lastMigrationName, true));
|
|
85
|
-
await deleteScriptFileIfEmpty(getScriptPath(projectPath, lastMigrationName, false));
|
|
86
|
-
}
|
|
87
|
-
exports.efRemoveLastMigration = efRemoveLastMigration;
|
|
88
|
-
async function deleteScriptFileIfEmpty(scriptPath) {
|
|
89
|
-
if (node_fs_1.default.existsSync(scriptPath)) {
|
|
90
|
-
const scriptContents = node_fs_1.default.readFileSync(scriptPath, { encoding: 'utf8' });
|
|
91
|
-
if (scriptContents.trim().length === 0) {
|
|
92
|
-
await promises_1.default.unlink(scriptPath);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
(0, generalUtils_js_1.log)(`${generalUtils_js_1.Emoji.Warning} Skipping deletion of non-empty script file: ${scriptPath}`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function getLastMigrationName(projectPath, dbContextName) {
|
|
100
|
-
const migrationsDirectory = getMigrationsDirectory(projectPath, dbContextName);
|
|
101
|
-
const filenames = node_fs_1.default.readdirSync(migrationsDirectory);
|
|
102
|
-
const migrationNames = filenames.filter(filename => filename.endsWith('.cs') &&
|
|
103
|
-
!filename.endsWith('.Designer.cs') &&
|
|
104
|
-
!filename.endsWith('.ModelSnapshot.cs') &&
|
|
105
|
-
filename.includes('_')).map(filename => filename.substring(0, filename.length - 3));
|
|
106
|
-
const migrationNamesWithTimestamps = migrationNames.map(migrationName => {
|
|
107
|
-
const timestamp = migrationName.substring(0, 14);
|
|
108
|
-
const name = migrationName.substring(15);
|
|
109
|
-
return { timestamp, name };
|
|
110
|
-
});
|
|
111
|
-
(0, generalUtils_js_1.log)(`Found migrations: ${migrationNamesWithTimestamps.map(m => m.name).join(', ')}`);
|
|
112
|
-
(0, generalUtils_js_1.log)(`Found timestamps: ${migrationNamesWithTimestamps.map(m => m.timestamp).join(', ')}`);
|
|
113
|
-
const sortedMigrationNames = [...migrationNamesWithTimestamps].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
114
|
-
const lastMigrationName = sortedMigrationNames[sortedMigrationNames.length - 1].name;
|
|
115
|
-
return lastMigrationName;
|
|
116
|
-
}
|
|
117
|
-
function getMigrationsProjectRelativePath(dbContextName) {
|
|
118
|
-
return `Migrations/${dbContextName}Migrations`;
|
|
119
|
-
}
|
|
120
|
-
function getMigrationsDirectory(projectDirectory, dbContextName) {
|
|
121
|
-
return node_path_1.default.join(projectDirectory, `Migrations/${dbContextName}Migrations`);
|
|
122
|
-
}
|
|
123
|
-
function getScriptPath(projectDirectory, migrationName, isUp) {
|
|
124
|
-
return node_path_1.default.join(projectDirectory, `Scripts/${migrationName}${isUp ? '' : '_Down'}.sql`);
|
|
125
|
-
}
|
|
126
|
-
async function getCSharpMigrationFilePath(projectDirectory, dbContextName, migrationName) {
|
|
127
|
-
const migrationsOutputDir = getMigrationsDirectory(projectDirectory, dbContextName);
|
|
128
|
-
if (!node_fs_1.default.existsSync(migrationsOutputDir)) {
|
|
129
|
-
throw new Error(`Unable to add migration C# boilerplate - could not find migrations output directory: ${migrationsOutputDir}`);
|
|
130
|
-
}
|
|
131
|
-
(0, generalUtils_js_1.log)(`Checking for generated C# file 📄XXXX_${migrationName}.cs in directory 📁${migrationsOutputDir}`);
|
|
132
|
-
const filenamePattern = `_${migrationName}.cs`;
|
|
133
|
-
const filenames = node_fs_1.default.readdirSync(migrationsOutputDir).filter(filename => filename.endsWith(filenamePattern));
|
|
134
|
-
if (!filenames || filenames.length === 0) {
|
|
135
|
-
throw new Error(`Auto-generated migration file not found - migrations output directory has no C# files ending with : ${filenamePattern}`);
|
|
136
|
-
}
|
|
137
|
-
if (filenames.length > 1) {
|
|
138
|
-
throw new Error(`Auto-generated migration file not found - migrations output directory has multiple C# files with the same migration name: ${filenames.join(', ')}`);
|
|
139
|
-
}
|
|
140
|
-
const filename = filenames[0];
|
|
141
|
-
const filePath = node_path_1.default.join(migrationsOutputDir, filename);
|
|
142
|
-
if (!node_fs_1.default.existsSync(filePath)) {
|
|
143
|
-
throw new Error(`Issue generating file path for migration (bad file path): ${filePath}`);
|
|
144
|
-
}
|
|
145
|
-
return filePath;
|
|
146
|
-
}
|
|
147
|
-
async function addDbMigrationBoilerplate(projectDirectory, dbContextName, migrationName) {
|
|
148
|
-
var _a;
|
|
149
|
-
const cSharpMigrationFilePath = await getCSharpMigrationFilePath(projectDirectory, dbContextName, migrationName);
|
|
150
|
-
(0, generalUtils_js_1.log)(`Replacing file contents with boilerplate for file 📄${cSharpMigrationFilePath}`);
|
|
151
|
-
const oldFileContents = await promises_1.default.readFile(cSharpMigrationFilePath, { encoding: 'utf8' });
|
|
152
|
-
const namespaceLine = (_a = oldFileContents.split('\n').find(line => line.startsWith('namespace '))) === null || _a === void 0 ? void 0 : _a.trim();
|
|
153
|
-
if (!namespaceLine) {
|
|
154
|
-
throw new Error(`Unable to find namespace line in file: ${cSharpMigrationFilePath}`);
|
|
155
|
-
}
|
|
156
|
-
const newFileContents = cSharpMigrationFileTemplate
|
|
157
|
-
.replaceAll(namespaceLinePlaceholder, namespaceLine)
|
|
158
|
-
.replaceAll(contextNamePlaceholder, dbContextName)
|
|
159
|
-
.replaceAll(migrationNamePlaceholder, migrationName);
|
|
160
|
-
await promises_1.default.writeFile(cSharpMigrationFilePath, newFileContents, { encoding: 'utf8' });
|
|
161
|
-
(0, generalUtils_js_1.log)(`Updated file with boilerplate - please ensure it is correct: 📄${cSharpMigrationFilePath}`);
|
|
162
|
-
const upScriptPath = node_path_1.default.join(projectDirectory, `Scripts/${migrationName}.sql`);
|
|
163
|
-
const downScriptPath = node_path_1.default.join(projectDirectory, `Scripts/${migrationName}_Down.sql`);
|
|
164
|
-
(0, generalUtils_js_1.log)('\nCreating corresponding empty sql files (no action will be taken if they already exist):');
|
|
165
|
-
(0, generalUtils_js_1.log)(` - 📄${upScriptPath}`);
|
|
166
|
-
(0, generalUtils_js_1.log)(` - 📄${downScriptPath}\n`);
|
|
167
|
-
await writeEmptySqlFileIfNotExists(upScriptPath, 'Up');
|
|
168
|
-
await writeEmptySqlFileIfNotExists(downScriptPath, 'Down');
|
|
169
|
-
}
|
|
170
|
-
async function writeEmptySqlFileIfNotExists(scriptPath, scriptType) {
|
|
171
|
-
if (!node_fs_1.default.existsSync(scriptPath)) {
|
|
172
|
-
const filename = node_path_1.default.basename(scriptPath);
|
|
173
|
-
await promises_1.default.writeFile(scriptPath, `-- ${filename} - ${scriptType} script`, { encoding: 'utf8' });
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
(0, generalUtils_js_1.log)(`Skipping ${scriptType} sql script (already exists)`);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const namespaceLinePlaceholder = '{{namespace}}';
|
|
180
|
-
const contextNamePlaceholder = '{{context_name}}';
|
|
181
|
-
const migrationNamePlaceholder = '{{migration_name}}';
|
|
182
|
-
const cSharpMigrationFileTemplate = `using Microsoft.EntityFrameworkCore.Migrations;
|
|
183
|
-
using MikeyT.DbMigrations;
|
|
184
|
-
|
|
185
|
-
#nullable disable
|
|
186
|
-
|
|
187
|
-
{{namespace}}
|
|
188
|
-
{
|
|
189
|
-
public partial class ${migrationNamePlaceholder} : Migration
|
|
190
|
-
{
|
|
191
|
-
protected override void Up(MigrationBuilder migrationBuilder)
|
|
192
|
-
{
|
|
193
|
-
MigrationScriptRunner.RunScript(migrationBuilder, "${migrationNamePlaceholder}.sql");
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
protected override void Down(MigrationBuilder migrationBuilder)
|
|
197
|
-
{
|
|
198
|
-
MigrationScriptRunner.RunScript(migrationBuilder, "${migrationNamePlaceholder}_Down.sql");
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
`;
|
|
203
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGJNaWdyYXRpb25VdGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYk1pZ3JhdGlvblV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHVEQUE0RztBQUM1RywwREFBNEI7QUFDNUIsc0RBQXdCO0FBQ3hCLGdFQUFrQztBQUVsQzs7Ozs7Ozs7R0FRRztBQUNJLEtBQUssVUFBVSxlQUFlLENBQUMsV0FBbUIsRUFBRSxhQUFxQixFQUFFLElBQWMsRUFBRSxPQUFPLEdBQUcsSUFBSTtJQUM5RyxJQUFBLGtDQUFnQixFQUFDLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQTtJQUM1QyxJQUFBLCtCQUFhLEVBQUMsZUFBZSxFQUFFLGFBQWEsQ0FBQyxDQUFBO0lBQzdDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSw0QkFBVSxFQUFDLFFBQVEsRUFBRSxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLEdBQUcsSUFBSSxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3BKLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQTtBQUNwQixDQUFDO0FBTEQsMENBS0M7QUFFRDs7OztHQUlHO0FBQ0ksS0FBSyxVQUFVLGdCQUFnQixDQUFDLFdBQW1CLEVBQUUsYUFBcUI7SUFDL0UsTUFBTSxlQUFlLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsQ0FBRSxDQUFBO0FBQzVFLENBQUM7QUFGRCw0Q0FFQztBQUVEOzs7OztHQUtHO0FBQ0ksS0FBSyxVQUFVLGtCQUFrQixDQUFDLFdBQW1CLEVBQUUsYUFBcUIsRUFBRSxhQUFzQjtJQUN6RyxNQUFNLGVBQWUsQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLENBQUMsVUFB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
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wrapper function for `dotnet ef`. If you don't pass `false` for `noBuild`, be sure the project has already been built by some other means.
|
|
3
|
-
*
|
|
4
|
-
* Docs for "dotnet ef" CLI: https://learn.microsoft.com/en-us/ef/core/cli/dotnet.
|
|
5
|
-
* @param projectPath Path to project that has the DbContext and Migration files used for the `--project` argument
|
|
6
|
-
* @param dbContextName The name of the DbContext class used for the `--context` argument
|
|
7
|
-
* @param args Arguments to pass to the `dotnet ef` CLI
|
|
8
|
-
* @param noBuild If true, the `--no-build` argument will be passed to the `dotnet ef` CLI (default: true)
|
|
9
|
-
*/
|
|
10
|
-
export declare function dotnetEfCommand(projectPath: string, dbContextName: string, args: string[], noBuild?: boolean): Promise<number>;
|
|
11
|
-
/**
|
|
12
|
-
* Wrapper function for `dotnet ef migrations list`.
|
|
13
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
14
|
-
* @param dbContextName The name of the DbContext class
|
|
15
|
-
*/
|
|
16
|
-
export declare function efMigrationsList(projectPath: string, dbContextName: string): Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* Wrapper function for `dotnet ef database update <migration_name>`.
|
|
19
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
20
|
-
* @param dbContextName The name of the DbContext class
|
|
21
|
-
* @param migrationName The name of the migration to update to (optional). If not provided, all migrations will be applied.
|
|
22
|
-
*/
|
|
23
|
-
export declare function efMigrationsUpdate(projectPath: string, dbContextName: string, migrationName?: string): Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
27
|
-
* @param dbContextName The name of the DbContext class
|
|
28
|
-
* @param migrationName The name of the migration to add
|
|
29
|
-
* @param withBoilerplate If true, boilerplate will be added to the migration C# file and empty Up and Down SQL files will be created
|
|
30
|
-
*/
|
|
31
|
-
export declare function efAddMigration(projectPath: string, dbContextName: string, migrationName: string, withBoilerplate?: boolean): Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
35
|
-
* @param dbContextName The name of the DbContext class
|
|
36
|
-
* @param skipConfirm If `true`, the user will not be prompted to confirm the removal of the last migration
|
|
37
|
-
*/
|
|
38
|
-
export declare function efRemoveLastMigration(projectPath: string, dbContextName: string, skipConfirm?: boolean): Promise<void>;
|
|
39
|
-
//# sourceMappingURL=dbMigrationUtils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dbMigrationUtils.d.ts","sourceRoot":"","sources":["../../src/dbMigrationUtils.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,UAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAKjI;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAEhF;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,iBAE1G;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,UAAQ,iBAY9H;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,UAAQ,iBAe1G"}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { Emoji, getConfirmation, log, requireString, requireValidPath, spawnAsync } from './generalUtils.js';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import fsp from 'node:fs/promises';
|
|
5
|
-
/**
|
|
6
|
-
* Wrapper function for `dotnet ef`. If you don't pass `false` for `noBuild`, be sure the project has already been built by some other means.
|
|
7
|
-
*
|
|
8
|
-
* Docs for "dotnet ef" CLI: https://learn.microsoft.com/en-us/ef/core/cli/dotnet.
|
|
9
|
-
* @param projectPath Path to project that has the DbContext and Migration files used for the `--project` argument
|
|
10
|
-
* @param dbContextName The name of the DbContext class used for the `--context` argument
|
|
11
|
-
* @param args Arguments to pass to the `dotnet ef` CLI
|
|
12
|
-
* @param noBuild If true, the `--no-build` argument will be passed to the `dotnet ef` CLI (default: true)
|
|
13
|
-
*/
|
|
14
|
-
export async function dotnetEfCommand(projectPath, dbContextName, args, noBuild = true) {
|
|
15
|
-
requireValidPath('projectPath', projectPath);
|
|
16
|
-
requireString('dbContextName', dbContextName);
|
|
17
|
-
const result = await spawnAsync('dotnet', ['ef', '--project', projectPath, ...args, '--context', dbContextName, ...(noBuild ? ['--no-build'] : [])]);
|
|
18
|
-
return result.code;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Wrapper function for `dotnet ef migrations list`.
|
|
22
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
23
|
-
* @param dbContextName The name of the DbContext class
|
|
24
|
-
*/
|
|
25
|
-
export async function efMigrationsList(projectPath, dbContextName) {
|
|
26
|
-
await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'list']);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Wrapper function for `dotnet ef database update <migration_name>`.
|
|
30
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
31
|
-
* @param dbContextName The name of the DbContext class
|
|
32
|
-
* @param migrationName The name of the migration to update to (optional). If not provided, all migrations will be applied.
|
|
33
|
-
*/
|
|
34
|
-
export async function efMigrationsUpdate(projectPath, dbContextName, migrationName) {
|
|
35
|
-
await dotnetEfCommand(projectPath, dbContextName, ['database', 'update', ...(migrationName ? [migrationName] : [])]);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
40
|
-
* @param dbContextName The name of the DbContext class
|
|
41
|
-
* @param migrationName The name of the migration to add
|
|
42
|
-
* @param withBoilerplate If true, boilerplate will be added to the migration C# file and empty Up and Down SQL files will be created
|
|
43
|
-
*/
|
|
44
|
-
export async function efAddMigration(projectPath, dbContextName, migrationName, withBoilerplate = false) {
|
|
45
|
-
const projectDirectory = projectPath.endsWith('.csproj') ? projectPath.substring(0, projectPath.lastIndexOf('/')) : projectPath;
|
|
46
|
-
const migrationsOutputDir = getMigrationsProjectRelativePath(dbContextName);
|
|
47
|
-
await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'add', migrationName, '-o', migrationsOutputDir]);
|
|
48
|
-
if (withBoilerplate) {
|
|
49
|
-
try {
|
|
50
|
-
await addDbMigrationBoilerplate(projectDirectory, dbContextName, migrationName);
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
console.error(error);
|
|
54
|
-
await efRemoveLastMigration(projectPath, dbContextName, true);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
* @param projectPath The path to the project that contains the DbContext and Migration files
|
|
61
|
-
* @param dbContextName The name of the DbContext class
|
|
62
|
-
* @param skipConfirm If `true`, the user will not be prompted to confirm the removal of the last migration
|
|
63
|
-
*/
|
|
64
|
-
export async function efRemoveLastMigration(projectPath, dbContextName, skipConfirm = false) {
|
|
65
|
-
const lastMigrationName = await getLastMigrationName(projectPath, dbContextName);
|
|
66
|
-
if (!skipConfirm && !await getConfirmation(`Are you sure you want to remove the last migration: ➡️${lastMigrationName}?`)) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const returnCode = await dotnetEfCommand(projectPath, dbContextName, ['migrations', 'remove']);
|
|
70
|
-
if (returnCode !== 0) {
|
|
71
|
-
throw new Error(`dotnet ef migrations remove returned non-zero exit code: ${returnCode}`);
|
|
72
|
-
}
|
|
73
|
-
log(`Removing migration SQL script files if they're empty`);
|
|
74
|
-
await deleteScriptFileIfEmpty(getScriptPath(projectPath, lastMigrationName, true));
|
|
75
|
-
await deleteScriptFileIfEmpty(getScriptPath(projectPath, lastMigrationName, false));
|
|
76
|
-
}
|
|
77
|
-
async function deleteScriptFileIfEmpty(scriptPath) {
|
|
78
|
-
if (fs.existsSync(scriptPath)) {
|
|
79
|
-
const scriptContents = fs.readFileSync(scriptPath, { encoding: 'utf8' });
|
|
80
|
-
if (scriptContents.trim().length === 0) {
|
|
81
|
-
await fsp.unlink(scriptPath);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
log(`${Emoji.Warning} Skipping deletion of non-empty script file: ${scriptPath}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function getLastMigrationName(projectPath, dbContextName) {
|
|
89
|
-
const migrationsDirectory = getMigrationsDirectory(projectPath, dbContextName);
|
|
90
|
-
const filenames = fs.readdirSync(migrationsDirectory);
|
|
91
|
-
const migrationNames = filenames.filter(filename => filename.endsWith('.cs') &&
|
|
92
|
-
!filename.endsWith('.Designer.cs') &&
|
|
93
|
-
!filename.endsWith('.ModelSnapshot.cs') &&
|
|
94
|
-
filename.includes('_')).map(filename => filename.substring(0, filename.length - 3));
|
|
95
|
-
const migrationNamesWithTimestamps = migrationNames.map(migrationName => {
|
|
96
|
-
const timestamp = migrationName.substring(0, 14);
|
|
97
|
-
const name = migrationName.substring(15);
|
|
98
|
-
return { timestamp, name };
|
|
99
|
-
});
|
|
100
|
-
log(`Found migrations: ${migrationNamesWithTimestamps.map(m => m.name).join(', ')}`);
|
|
101
|
-
log(`Found timestamps: ${migrationNamesWithTimestamps.map(m => m.timestamp).join(', ')}`);
|
|
102
|
-
const sortedMigrationNames = [...migrationNamesWithTimestamps].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
103
|
-
const lastMigrationName = sortedMigrationNames[sortedMigrationNames.length - 1].name;
|
|
104
|
-
return lastMigrationName;
|
|
105
|
-
}
|
|
106
|
-
function getMigrationsProjectRelativePath(dbContextName) {
|
|
107
|
-
return `Migrations/${dbContextName}Migrations`;
|
|
108
|
-
}
|
|
109
|
-
function getMigrationsDirectory(projectDirectory, dbContextName) {
|
|
110
|
-
return path.join(projectDirectory, `Migrations/${dbContextName}Migrations`);
|
|
111
|
-
}
|
|
112
|
-
function getScriptPath(projectDirectory, migrationName, isUp) {
|
|
113
|
-
return path.join(projectDirectory, `Scripts/${migrationName}${isUp ? '' : '_Down'}.sql`);
|
|
114
|
-
}
|
|
115
|
-
async function getCSharpMigrationFilePath(projectDirectory, dbContextName, migrationName) {
|
|
116
|
-
const migrationsOutputDir = getMigrationsDirectory(projectDirectory, dbContextName);
|
|
117
|
-
if (!fs.existsSync(migrationsOutputDir)) {
|
|
118
|
-
throw new Error(`Unable to add migration C# boilerplate - could not find migrations output directory: ${migrationsOutputDir}`);
|
|
119
|
-
}
|
|
120
|
-
log(`Checking for generated C# file 📄XXXX_${migrationName}.cs in directory 📁${migrationsOutputDir}`);
|
|
121
|
-
const filenamePattern = `_${migrationName}.cs`;
|
|
122
|
-
const filenames = fs.readdirSync(migrationsOutputDir).filter(filename => filename.endsWith(filenamePattern));
|
|
123
|
-
if (!filenames || filenames.length === 0) {
|
|
124
|
-
throw new Error(`Auto-generated migration file not found - migrations output directory has no C# files ending with : ${filenamePattern}`);
|
|
125
|
-
}
|
|
126
|
-
if (filenames.length > 1) {
|
|
127
|
-
throw new Error(`Auto-generated migration file not found - migrations output directory has multiple C# files with the same migration name: ${filenames.join(', ')}`);
|
|
128
|
-
}
|
|
129
|
-
const filename = filenames[0];
|
|
130
|
-
const filePath = path.join(migrationsOutputDir, filename);
|
|
131
|
-
if (!fs.existsSync(filePath)) {
|
|
132
|
-
throw new Error(`Issue generating file path for migration (bad file path): ${filePath}`);
|
|
133
|
-
}
|
|
134
|
-
return filePath;
|
|
135
|
-
}
|
|
136
|
-
async function addDbMigrationBoilerplate(projectDirectory, dbContextName, migrationName) {
|
|
137
|
-
const cSharpMigrationFilePath = await getCSharpMigrationFilePath(projectDirectory, dbContextName, migrationName);
|
|
138
|
-
log(`Replacing file contents with boilerplate for file 📄${cSharpMigrationFilePath}`);
|
|
139
|
-
const oldFileContents = await fsp.readFile(cSharpMigrationFilePath, { encoding: 'utf8' });
|
|
140
|
-
const namespaceLine = oldFileContents.split('\n').find(line => line.startsWith('namespace '))?.trim();
|
|
141
|
-
if (!namespaceLine) {
|
|
142
|
-
throw new Error(`Unable to find namespace line in file: ${cSharpMigrationFilePath}`);
|
|
143
|
-
}
|
|
144
|
-
const newFileContents = cSharpMigrationFileTemplate
|
|
145
|
-
.replaceAll(namespaceLinePlaceholder, namespaceLine)
|
|
146
|
-
.replaceAll(contextNamePlaceholder, dbContextName)
|
|
147
|
-
.replaceAll(migrationNamePlaceholder, migrationName);
|
|
148
|
-
await fsp.writeFile(cSharpMigrationFilePath, newFileContents, { encoding: 'utf8' });
|
|
149
|
-
log(`Updated file with boilerplate - please ensure it is correct: 📄${cSharpMigrationFilePath}`);
|
|
150
|
-
const upScriptPath = path.join(projectDirectory, `Scripts/${migrationName}.sql`);
|
|
151
|
-
const downScriptPath = path.join(projectDirectory, `Scripts/${migrationName}_Down.sql`);
|
|
152
|
-
log('\nCreating corresponding empty sql files (no action will be taken if they already exist):');
|
|
153
|
-
log(` - 📄${upScriptPath}`);
|
|
154
|
-
log(` - 📄${downScriptPath}\n`);
|
|
155
|
-
await writeEmptySqlFileIfNotExists(upScriptPath, 'Up');
|
|
156
|
-
await writeEmptySqlFileIfNotExists(downScriptPath, 'Down');
|
|
157
|
-
}
|
|
158
|
-
async function writeEmptySqlFileIfNotExists(scriptPath, scriptType) {
|
|
159
|
-
if (!fs.existsSync(scriptPath)) {
|
|
160
|
-
const filename = path.basename(scriptPath);
|
|
161
|
-
await fsp.writeFile(scriptPath, `-- ${filename} - ${scriptType} script`, { encoding: 'utf8' });
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
log(`Skipping ${scriptType} sql script (already exists)`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
const namespaceLinePlaceholder = '{{namespace}}';
|
|
168
|
-
const contextNamePlaceholder = '{{context_name}}';
|
|
169
|
-
const migrationNamePlaceholder = '{{migration_name}}';
|
|
170
|
-
const cSharpMigrationFileTemplate = `using Microsoft.EntityFrameworkCore.Migrations;
|
|
171
|
-
using MikeyT.DbMigrations;
|
|
172
|
-
|
|
173
|
-
#nullable disable
|
|
174
|
-
|
|
175
|
-
{{namespace}}
|
|
176
|
-
{
|
|
177
|
-
public partial class ${migrationNamePlaceholder} : Migration
|
|
178
|
-
{
|
|
179
|
-
protected override void Up(MigrationBuilder migrationBuilder)
|
|
180
|
-
{
|
|
181
|
-
MigrationScriptRunner.RunScript(migrationBuilder, "${migrationNamePlaceholder}.sql");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
protected override void Down(MigrationBuilder migrationBuilder)
|
|
185
|
-
{
|
|
186
|
-
MigrationScriptRunner.RunScript(migrationBuilder, "${migrationNamePlaceholder}_Down.sql");
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
`;
|
|
191
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGJNaWdyYXRpb25VdGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYk1pZ3JhdGlvblV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDNUcsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBQzVCLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUN4QixPQUFPLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQTtBQUVsQzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZUFBZSxDQUFDLFdBQW1CLEVBQUUsYUFBcUIsRUFBRSxJQUFjLEVBQUUsT0FBTyxHQUFHLElBQUk7SUFDOUcsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBQzVDLGFBQWEsQ0FBQyxlQUFlLEVBQUUsYUFBYSxDQUFDLENBQUE7SUFDN0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDcEosT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFBO0FBQ3BCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLGFBQXFCO0lBQy9FLE1BQU0sZUFBZSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUUsQ0FBQTtBQUM1RSxDQUFDO0FBRUQ7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
|