@flusys/nestjs-core 7.1.0 → 8.0.0
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 +2 -2
- package/config/index.d.ts +1 -1
- package/constants/index.d.ts +1 -1
- package/docs/docs.config.d.ts +1 -1
- package/docs/index.d.ts +1 -1
- package/fesm/229.js +729 -0
- package/fesm/config/index.js +126 -1
- package/fesm/constants/index.js +29 -1
- package/fesm/docs/index.js +288 -1
- package/fesm/index.js +124 -5
- package/fesm/interfaces/index.js +18 -4
- package/fesm/migration/cli.js +19 -2
- package/fesm/migration/index.js +45 -3
- package/fesm/runtime.js +85 -0
- package/fesm/utils/index.js +131 -1
- package/index.d.ts +5 -5
- package/interfaces/app-config.interfaces.d.ts +1 -1
- package/interfaces/index.d.ts +4 -4
- package/interfaces/migration.interface.d.ts +2 -2
- package/migration/cli.d.ts +0 -1
- package/migration/datasource.factory.d.ts +1 -1
- package/migration/index.d.ts +3 -3
- package/migration/migration.cli.d.ts +1 -1
- package/migration/migration.runner.d.ts +1 -1
- package/package.json +24 -32
- package/utils/datasource-config.builder.d.ts +2 -2
- package/utils/index.d.ts +1 -1
- package/cjs/config/env-config.service.js +0 -162
- package/cjs/config/env-config.service.spec.js +0 -325
- package/cjs/config/index.js +0 -18
- package/cjs/constants/database.constants.js +0 -20
- package/cjs/constants/index.js +0 -18
- package/cjs/docs/docs.config.js +0 -276
- package/cjs/docs/docs.config.spec.js +0 -923
- package/cjs/docs/index.js +0 -18
- package/cjs/index.js +0 -23
- package/cjs/interfaces/app-config.interfaces.js +0 -4
- package/cjs/interfaces/base-entity.interface.js +0 -9
- package/cjs/interfaces/database.interface.js +0 -4
- package/cjs/interfaces/index.js +0 -21
- package/cjs/interfaces/migration.interface.js +0 -4
- package/cjs/migration/cli.js +0 -10
- package/cjs/migration/datasource.factory.js +0 -43
- package/cjs/migration/datasource.factory.spec.js +0 -113
- package/cjs/migration/index.js +0 -45
- package/cjs/migration/migration.cli.js +0 -231
- package/cjs/migration/migration.cli.spec.js +0 -293
- package/cjs/migration/migration.runner.js +0 -276
- package/cjs/migration/migration.runner.spec.js +0 -268
- package/cjs/utils/datasource-config.builder.js +0 -103
- package/cjs/utils/datasource-config.builder.spec.js +0 -232
- package/cjs/utils/index.js +0 -18
- package/fesm/config/env-config.service.js +0 -112
- package/fesm/config/env-config.service.spec.js +0 -321
- package/fesm/constants/database.constants.js +0 -2
- package/fesm/docs/docs.config.js +0 -258
- package/fesm/docs/docs.config.spec.js +0 -919
- package/fesm/interfaces/app-config.interfaces.js +0 -1
- package/fesm/interfaces/base-entity.interface.js +0 -6
- package/fesm/interfaces/database.interface.js +0 -1
- package/fesm/interfaces/migration.interface.js +0 -1
- package/fesm/migration/datasource.factory.js +0 -25
- package/fesm/migration/datasource.factory.spec.js +0 -109
- package/fesm/migration/migration.cli.js +0 -180
- package/fesm/migration/migration.cli.spec.js +0 -289
- package/fesm/migration/migration.runner.js +0 -202
- package/fesm/migration/migration.runner.spec.js +0 -264
- package/fesm/utils/datasource-config.builder.js +0 -84
- package/fesm/utils/datasource-config.builder.spec.js +0 -228
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
const _migrationcli = require("./migration.cli");
|
|
6
|
-
const mockGetTenantId = jest.fn();
|
|
7
|
-
const mockTryGetValue = jest.fn();
|
|
8
|
-
const mockIsProduction = jest.fn();
|
|
9
|
-
jest.mock('../config', ()=>({
|
|
10
|
-
envConfig: {
|
|
11
|
-
getTenantId: (...args)=>mockGetTenantId(...args),
|
|
12
|
-
tryGetValue: (...args)=>mockTryGetValue(...args),
|
|
13
|
-
isProduction: (...args)=>mockIsProduction(...args)
|
|
14
|
-
}
|
|
15
|
-
}));
|
|
16
|
-
const mockGetDatabaseForTenant = jest.fn();
|
|
17
|
-
const mockGetMigrationsFolderPath = jest.fn();
|
|
18
|
-
jest.mock('../utils', ()=>({
|
|
19
|
-
getDatabaseForTenant: (...args)=>mockGetDatabaseForTenant(...args),
|
|
20
|
-
getMigrationsFolderPath: (...args)=>mockGetMigrationsFolderPath(...args)
|
|
21
|
-
}));
|
|
22
|
-
const mockGenerateMigration = jest.fn();
|
|
23
|
-
const mockRunMigrations = jest.fn();
|
|
24
|
-
const mockRevertMigration = jest.fn();
|
|
25
|
-
const mockResetDatabase = jest.fn();
|
|
26
|
-
const mockMigrationStatus = jest.fn();
|
|
27
|
-
const mockRunForAllTenants = jest.fn();
|
|
28
|
-
jest.mock('./migration.runner', ()=>({
|
|
29
|
-
generateMigration: (...args)=>mockGenerateMigration(...args),
|
|
30
|
-
runMigrations: (...args)=>mockRunMigrations(...args),
|
|
31
|
-
revertMigration: (...args)=>mockRevertMigration(...args),
|
|
32
|
-
resetDatabase: (...args)=>mockResetDatabase(...args),
|
|
33
|
-
migrationStatus: (...args)=>mockMigrationStatus(...args),
|
|
34
|
-
runForAllTenants: (...args)=>mockRunForAllTenants(...args)
|
|
35
|
-
}));
|
|
36
|
-
describe('runMigrationCli', ()=>{
|
|
37
|
-
const baseConfig = {
|
|
38
|
-
defaultDatabaseConfig: {
|
|
39
|
-
type: 'postgres',
|
|
40
|
-
database: 'flusys_default'
|
|
41
|
-
},
|
|
42
|
-
migrationsPath: 'migrations',
|
|
43
|
-
entities: []
|
|
44
|
-
};
|
|
45
|
-
let logSpy;
|
|
46
|
-
let errorSpy;
|
|
47
|
-
let exitSpy;
|
|
48
|
-
let originalArgv;
|
|
49
|
-
beforeEach(()=>{
|
|
50
|
-
jest.clearAllMocks();
|
|
51
|
-
originalArgv = process.argv;
|
|
52
|
-
logSpy = jest.spyOn(console, 'log').mockImplementation(()=>undefined);
|
|
53
|
-
errorSpy = jest.spyOn(console, 'error').mockImplementation(()=>undefined);
|
|
54
|
-
exitSpy = jest.spyOn(process, 'exit').mockImplementation(()=>{
|
|
55
|
-
throw new Error('process.exit called');
|
|
56
|
-
});
|
|
57
|
-
mockGetTenantId.mockReturnValue(null);
|
|
58
|
-
mockTryGetValue.mockReturnValue('');
|
|
59
|
-
mockIsProduction.mockReturnValue(false);
|
|
60
|
-
mockGetDatabaseForTenant.mockReturnValue({
|
|
61
|
-
database: 'flusys_default'
|
|
62
|
-
});
|
|
63
|
-
mockGetMigrationsFolderPath.mockReturnValue('migrations/default');
|
|
64
|
-
});
|
|
65
|
-
afterEach(()=>{
|
|
66
|
-
process.argv = originalArgv;
|
|
67
|
-
logSpy.mockRestore();
|
|
68
|
-
errorSpy.mockRestore();
|
|
69
|
-
exitSpy.mockRestore();
|
|
70
|
-
});
|
|
71
|
-
function setArgv(...args) {
|
|
72
|
-
process.argv = [
|
|
73
|
-
'node',
|
|
74
|
-
'cli.js',
|
|
75
|
-
...args
|
|
76
|
-
];
|
|
77
|
-
}
|
|
78
|
-
it('should print help and return when no command is given', async ()=>{
|
|
79
|
-
setArgv();
|
|
80
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
81
|
-
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Migration CLI'));
|
|
82
|
-
expect(mockRunMigrations).not.toHaveBeenCalled();
|
|
83
|
-
});
|
|
84
|
-
it('should run migrations for the default tenant', async ()=>{
|
|
85
|
-
setArgv('run');
|
|
86
|
-
mockRunMigrations.mockResolvedValue({
|
|
87
|
-
success: true,
|
|
88
|
-
migrationsRun: []
|
|
89
|
-
});
|
|
90
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
91
|
-
expect(mockRunMigrations).toHaveBeenCalledWith(baseConfig, undefined);
|
|
92
|
-
expect(exitSpy).not.toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
it('should exit with code 1 when run fails', async ()=>{
|
|
95
|
-
setArgv('run');
|
|
96
|
-
mockRunMigrations.mockResolvedValue({
|
|
97
|
-
success: false,
|
|
98
|
-
error: 'boom'
|
|
99
|
-
});
|
|
100
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
101
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
102
|
-
});
|
|
103
|
-
it('should revert the last migration', async ()=>{
|
|
104
|
-
setArgv('revert');
|
|
105
|
-
mockRevertMigration.mockResolvedValue({
|
|
106
|
-
success: true
|
|
107
|
-
});
|
|
108
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
109
|
-
expect(mockRevertMigration).toHaveBeenCalledWith(baseConfig, undefined);
|
|
110
|
-
});
|
|
111
|
-
it('should exit with code 1 when revert fails', async ()=>{
|
|
112
|
-
setArgv('revert');
|
|
113
|
-
mockRevertMigration.mockResolvedValue({
|
|
114
|
-
success: false,
|
|
115
|
-
error: 'nothing to revert'
|
|
116
|
-
});
|
|
117
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
118
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
119
|
-
});
|
|
120
|
-
it('should report migration status', async ()=>{
|
|
121
|
-
setArgv('status');
|
|
122
|
-
mockMigrationStatus.mockResolvedValue({
|
|
123
|
-
success: true,
|
|
124
|
-
migrationsRun: [
|
|
125
|
-
'Up to date'
|
|
126
|
-
]
|
|
127
|
-
});
|
|
128
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
129
|
-
expect(mockMigrationStatus).toHaveBeenCalledWith(baseConfig, undefined);
|
|
130
|
-
});
|
|
131
|
-
it('should generate a migration using the --name flag', async ()=>{
|
|
132
|
-
setArgv('generate', '--name=AddProducts');
|
|
133
|
-
mockGenerateMigration.mockResolvedValue(undefined);
|
|
134
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
135
|
-
expect(mockGenerateMigration).toHaveBeenCalledWith(baseConfig, 'AddProducts', undefined, undefined);
|
|
136
|
-
});
|
|
137
|
-
it('should prefer npm_config_name over --name', async ()=>{
|
|
138
|
-
setArgv('generate', '--name=Ignored');
|
|
139
|
-
mockTryGetValue.mockImplementation((key)=>key === 'npm_config_name' ? 'FromNpm' : '');
|
|
140
|
-
mockGenerateMigration.mockResolvedValue(undefined);
|
|
141
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
142
|
-
expect(mockGenerateMigration).toHaveBeenCalledWith(baseConfig, 'FromNpm', undefined, undefined);
|
|
143
|
-
});
|
|
144
|
-
it('should exit with code 1 when generate is missing a name', async ()=>{
|
|
145
|
-
setArgv('generate');
|
|
146
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
147
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
148
|
-
expect(mockGenerateMigration).not.toHaveBeenCalled();
|
|
149
|
-
});
|
|
150
|
-
it('should pass the resolved tenant id through to sub-commands', async ()=>{
|
|
151
|
-
setArgv('run');
|
|
152
|
-
mockGetTenantId.mockReturnValue('tenant-a');
|
|
153
|
-
mockRunMigrations.mockResolvedValue({
|
|
154
|
-
success: true,
|
|
155
|
-
migrationsRun: []
|
|
156
|
-
});
|
|
157
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
158
|
-
expect(mockRunMigrations).toHaveBeenCalledWith(baseConfig, 'tenant-a');
|
|
159
|
-
});
|
|
160
|
-
it('should reject reset in production without --force', async ()=>{
|
|
161
|
-
setArgv('reset');
|
|
162
|
-
mockIsProduction.mockReturnValue(true);
|
|
163
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
164
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
165
|
-
expect(mockResetDatabase).not.toHaveBeenCalled();
|
|
166
|
-
});
|
|
167
|
-
it('should allow reset in production when --force is passed', async ()=>{
|
|
168
|
-
setArgv('reset', '--force');
|
|
169
|
-
mockIsProduction.mockReturnValue(true);
|
|
170
|
-
mockResetDatabase.mockResolvedValue({
|
|
171
|
-
success: true
|
|
172
|
-
});
|
|
173
|
-
mockGenerateMigration.mockResolvedValue(undefined);
|
|
174
|
-
mockRunMigrations.mockResolvedValue({
|
|
175
|
-
success: true,
|
|
176
|
-
migrationsRun: []
|
|
177
|
-
});
|
|
178
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
179
|
-
expect(mockResetDatabase).toHaveBeenCalledWith(baseConfig, undefined);
|
|
180
|
-
expect(mockGenerateMigration).toHaveBeenCalledWith(baseConfig, 'Init', undefined, undefined);
|
|
181
|
-
expect(mockRunMigrations).toHaveBeenCalledWith(baseConfig, undefined);
|
|
182
|
-
});
|
|
183
|
-
it('should use provided migration name as the reset init migration name', async ()=>{
|
|
184
|
-
setArgv('reset', '--name=InitialSetup');
|
|
185
|
-
mockResetDatabase.mockResolvedValue({
|
|
186
|
-
success: true
|
|
187
|
-
});
|
|
188
|
-
mockGenerateMigration.mockResolvedValue(undefined);
|
|
189
|
-
mockRunMigrations.mockResolvedValue({
|
|
190
|
-
success: true,
|
|
191
|
-
migrationsRun: []
|
|
192
|
-
});
|
|
193
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
194
|
-
expect(mockGenerateMigration).toHaveBeenCalledWith(baseConfig, 'InitialSetup', undefined, undefined);
|
|
195
|
-
});
|
|
196
|
-
it('should exit with code 1 when reset fails', async ()=>{
|
|
197
|
-
setArgv('reset');
|
|
198
|
-
mockResetDatabase.mockResolvedValue({
|
|
199
|
-
success: false,
|
|
200
|
-
error: 'cannot drop'
|
|
201
|
-
});
|
|
202
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
203
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
204
|
-
expect(mockGenerateMigration).not.toHaveBeenCalled();
|
|
205
|
-
});
|
|
206
|
-
it('should reject unknown commands', async ()=>{
|
|
207
|
-
setArgv('frobnicate');
|
|
208
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
209
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
210
|
-
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown command'));
|
|
211
|
-
});
|
|
212
|
-
describe(':all commands', ()=>{
|
|
213
|
-
it('should run for all tenants when multi-tenant mode is enabled', async ()=>{
|
|
214
|
-
setArgv('run:all');
|
|
215
|
-
const multiTenantConfig = {
|
|
216
|
-
...baseConfig,
|
|
217
|
-
bootstrapAppConfig: {
|
|
218
|
-
databaseMode: 'multi-tenant'
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
mockRunForAllTenants.mockResolvedValue([
|
|
222
|
-
{
|
|
223
|
-
success: true
|
|
224
|
-
}
|
|
225
|
-
]);
|
|
226
|
-
await (0, _migrationcli.runMigrationCli)(multiTenantConfig);
|
|
227
|
-
expect(mockRunForAllTenants).toHaveBeenCalledWith(multiTenantConfig, 'run');
|
|
228
|
-
});
|
|
229
|
-
it('should reject :all commands when database mode is single', async ()=>{
|
|
230
|
-
setArgv('run:all');
|
|
231
|
-
const singleConfig = {
|
|
232
|
-
...baseConfig,
|
|
233
|
-
bootstrapAppConfig: {
|
|
234
|
-
databaseMode: 'single'
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
await expect((0, _migrationcli.runMigrationCli)(singleConfig)).rejects.toThrow('process.exit called');
|
|
238
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
239
|
-
expect(mockRunForAllTenants).not.toHaveBeenCalled();
|
|
240
|
-
});
|
|
241
|
-
it('should exit with code 1 when any tenant fails during :all commands', async ()=>{
|
|
242
|
-
setArgv('status:all');
|
|
243
|
-
mockRunForAllTenants.mockResolvedValue([
|
|
244
|
-
{
|
|
245
|
-
success: true
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
success: false
|
|
249
|
-
}
|
|
250
|
-
]);
|
|
251
|
-
await expect((0, _migrationcli.runMigrationCli)(baseConfig)).rejects.toThrow('process.exit called');
|
|
252
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
253
|
-
});
|
|
254
|
-
it('should parse the action prefix from the :all command', async ()=>{
|
|
255
|
-
setArgv('revert:all');
|
|
256
|
-
mockRunForAllTenants.mockResolvedValue([
|
|
257
|
-
{
|
|
258
|
-
success: true
|
|
259
|
-
}
|
|
260
|
-
]);
|
|
261
|
-
await (0, _migrationcli.runMigrationCli)(baseConfig);
|
|
262
|
-
expect(mockRunForAllTenants).toHaveBeenCalledWith(baseConfig, 'revert');
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
describe('config resolution', ()=>{
|
|
266
|
-
it('should load config from an explicit string path argument', async ()=>{
|
|
267
|
-
setArgv('status');
|
|
268
|
-
const loadedConfig = {
|
|
269
|
-
...baseConfig,
|
|
270
|
-
migrationsPath: 'custom-migrations'
|
|
271
|
-
};
|
|
272
|
-
jest.doMock(require('path').resolve(process.cwd(), 'custom-config.ts'), ()=>({
|
|
273
|
-
migrationConfig: loadedConfig
|
|
274
|
-
}), {
|
|
275
|
-
virtual: true
|
|
276
|
-
});
|
|
277
|
-
mockMigrationStatus.mockResolvedValue({
|
|
278
|
-
success: true,
|
|
279
|
-
migrationsRun: [
|
|
280
|
-
'Up to date'
|
|
281
|
-
]
|
|
282
|
-
});
|
|
283
|
-
await (0, _migrationcli.runMigrationCli)('custom-config.ts');
|
|
284
|
-
expect(mockMigrationStatus).toHaveBeenCalledWith(loadedConfig, undefined);
|
|
285
|
-
});
|
|
286
|
-
it('should exit with code 1 and show help when no config can be resolved', async ()=>{
|
|
287
|
-
setArgv('status');
|
|
288
|
-
await expect((0, _migrationcli.runMigrationCli)()).rejects.toThrow('process.exit called');
|
|
289
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
290
|
-
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('Config not found'));
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
});
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get ensureMigrationsFolder () {
|
|
13
|
-
return ensureMigrationsFolder;
|
|
14
|
-
},
|
|
15
|
-
get generateMigration () {
|
|
16
|
-
return generateMigration;
|
|
17
|
-
},
|
|
18
|
-
get migrationStatus () {
|
|
19
|
-
return migrationStatus;
|
|
20
|
-
},
|
|
21
|
-
get resetDatabase () {
|
|
22
|
-
return resetDatabase;
|
|
23
|
-
},
|
|
24
|
-
get revertMigration () {
|
|
25
|
-
return revertMigration;
|
|
26
|
-
},
|
|
27
|
-
get runForAllTenants () {
|
|
28
|
-
return runForAllTenants;
|
|
29
|
-
},
|
|
30
|
-
get runMigrations () {
|
|
31
|
-
return runMigrations;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
const _child_process = require("child_process");
|
|
35
|
-
const _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
36
|
-
const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
37
|
-
const _typeorm = require("typeorm");
|
|
38
|
-
const _config = require("../config");
|
|
39
|
-
const _utils = require("../utils");
|
|
40
|
-
const _datasourcefactory = require("./datasource.factory");
|
|
41
|
-
function _getRequireWildcardCache(nodeInterop) {
|
|
42
|
-
if (typeof WeakMap !== "function") return null;
|
|
43
|
-
var cacheBabelInterop = new WeakMap();
|
|
44
|
-
var cacheNodeInterop = new WeakMap();
|
|
45
|
-
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
46
|
-
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
47
|
-
})(nodeInterop);
|
|
48
|
-
}
|
|
49
|
-
function _interop_require_wildcard(obj, nodeInterop) {
|
|
50
|
-
if (!nodeInterop && obj && obj.__esModule) {
|
|
51
|
-
return obj;
|
|
52
|
-
}
|
|
53
|
-
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
54
|
-
return {
|
|
55
|
-
default: obj
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
var cache = _getRequireWildcardCache(nodeInterop);
|
|
59
|
-
if (cache && cache.has(obj)) {
|
|
60
|
-
return cache.get(obj);
|
|
61
|
-
}
|
|
62
|
-
var newObj = {
|
|
63
|
-
__proto__: null
|
|
64
|
-
};
|
|
65
|
-
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
66
|
-
for(var key in obj){
|
|
67
|
-
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
68
|
-
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
69
|
-
if (desc && (desc.get || desc.set)) {
|
|
70
|
-
Object.defineProperty(newObj, key, desc);
|
|
71
|
-
} else {
|
|
72
|
-
newObj[key] = obj[key];
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
newObj.default = obj;
|
|
77
|
-
if (cache) {
|
|
78
|
-
cache.set(obj, newObj);
|
|
79
|
-
}
|
|
80
|
-
return newObj;
|
|
81
|
-
}
|
|
82
|
-
function getLabel(tenantId) {
|
|
83
|
-
return tenantId ? `[${tenantId}]` : '[default]';
|
|
84
|
-
}
|
|
85
|
-
async function withDataSource(config, tenantId, operation) {
|
|
86
|
-
const { database } = (0, _utils.getDatabaseForTenant)(config, tenantId);
|
|
87
|
-
const label = getLabel(tenantId);
|
|
88
|
-
try {
|
|
89
|
-
const ds = await (0, _datasourcefactory.initializeDataSource)({
|
|
90
|
-
config,
|
|
91
|
-
tenantId
|
|
92
|
-
});
|
|
93
|
-
const partial = await operation(ds, label);
|
|
94
|
-
await ds.destroy();
|
|
95
|
-
return {
|
|
96
|
-
tenantId,
|
|
97
|
-
database,
|
|
98
|
-
success: true,
|
|
99
|
-
...partial
|
|
100
|
-
};
|
|
101
|
-
} catch (error) {
|
|
102
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
103
|
-
console.error(`${label} ✗ Failed: ${errorMessage}`);
|
|
104
|
-
return {
|
|
105
|
-
tenantId,
|
|
106
|
-
database,
|
|
107
|
-
success: false,
|
|
108
|
-
error: errorMessage
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function ensureMigrationsFolder(basePath, tenantId) {
|
|
113
|
-
const folder = (0, _utils.getMigrationsFolderPath)(basePath, tenantId);
|
|
114
|
-
if (!_fs.existsSync(folder)) {
|
|
115
|
-
_fs.mkdirSync(folder, {
|
|
116
|
-
recursive: true
|
|
117
|
-
});
|
|
118
|
-
console.log(`📁 Created: ${folder}`);
|
|
119
|
-
}
|
|
120
|
-
return folder;
|
|
121
|
-
}
|
|
122
|
-
async function generateMigration(config, name, tenantId, datasourcePath) {
|
|
123
|
-
const label = tenantId ? `[${tenantId}]` : '[default]';
|
|
124
|
-
const folder = ensureMigrationsFolder(config.migrationsPath, tenantId);
|
|
125
|
-
console.log(`${label} Generating migration: ${name}`);
|
|
126
|
-
console.log(`${label} Target folder: ${folder}`);
|
|
127
|
-
const dsPath = datasourcePath || findDatasourcePath();
|
|
128
|
-
const migrationFile = _path.join(folder, name);
|
|
129
|
-
const command = `ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli migration:generate "${migrationFile}" -d "${dsPath}"`;
|
|
130
|
-
(0, _child_process.execSync)(command, {
|
|
131
|
-
stdio: 'inherit',
|
|
132
|
-
env: {
|
|
133
|
-
..._config.envConfig.getEnv(),
|
|
134
|
-
TENANT_ID: tenantId || ''
|
|
135
|
-
},
|
|
136
|
-
cwd: process.cwd()
|
|
137
|
-
});
|
|
138
|
-
console.log(`${label} ✓ Generated!`);
|
|
139
|
-
}
|
|
140
|
-
function findDatasourcePath() {
|
|
141
|
-
const possiblePaths = [
|
|
142
|
-
'src/persistence/migration.config.ts',
|
|
143
|
-
'projects/flusysnest/src/persistence/migration.config.ts'
|
|
144
|
-
];
|
|
145
|
-
for (const p of possiblePaths){
|
|
146
|
-
if (_fs.existsSync(_path.join(process.cwd(), p))) {
|
|
147
|
-
return p;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
throw new Error('Could not find datasource file. Specify with --datasource=<path>');
|
|
151
|
-
}
|
|
152
|
-
async function runMigrations(config, tenantId) {
|
|
153
|
-
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
154
|
-
const migrations = await ds.runMigrations();
|
|
155
|
-
if (migrations.length === 0) {
|
|
156
|
-
console.log(`${label} No pending migrations.`);
|
|
157
|
-
} else {
|
|
158
|
-
console.log(`${label} ✓ Executed ${migrations.length} migration(s):`);
|
|
159
|
-
migrations.forEach((m)=>console.log(` - ${m.name}`));
|
|
160
|
-
}
|
|
161
|
-
return {
|
|
162
|
-
migrationsRun: migrations.map((m)=>m.name)
|
|
163
|
-
};
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
async function revertMigration(config, tenantId) {
|
|
167
|
-
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
168
|
-
await ds.undoLastMigration();
|
|
169
|
-
console.log(`${label} ✓ Reverted!`);
|
|
170
|
-
return {};
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
function clearMigrationFiles(basePath, tenantId, label) {
|
|
174
|
-
const folder = (0, _utils.getMigrationsFolderPath)(basePath, tenantId);
|
|
175
|
-
if (!_fs.existsSync(folder)) return;
|
|
176
|
-
const files = _fs.readdirSync(folder).filter((f)=>f.endsWith('.ts') || f.endsWith('.js'));
|
|
177
|
-
files.forEach((file)=>_fs.rmSync(_path.join(folder, file)));
|
|
178
|
-
console.log(`${label} ✓ Removed ${files.length} migration file(s) from ${folder}`);
|
|
179
|
-
}
|
|
180
|
-
async function dropAndRecreateDatabase(dbConfig, label) {
|
|
181
|
-
const { type, database } = dbConfig;
|
|
182
|
-
if (type === 'sqlite') {
|
|
183
|
-
if (database && _fs.existsSync(database)) _fs.rmSync(database);
|
|
184
|
-
console.log(`${label} ✓ Deleted sqlite file`);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
if (type !== 'mysql' && type !== 'mariadb' && type !== 'postgres') {
|
|
188
|
-
throw new Error(`Database reset is not supported for type '${type}'`);
|
|
189
|
-
}
|
|
190
|
-
const adminDs = new _typeorm.DataSource({
|
|
191
|
-
type,
|
|
192
|
-
host: dbConfig.host,
|
|
193
|
-
port: dbConfig.port,
|
|
194
|
-
username: dbConfig.username,
|
|
195
|
-
password: dbConfig.password,
|
|
196
|
-
database: type === 'postgres' ? 'postgres' : undefined
|
|
197
|
-
});
|
|
198
|
-
await adminDs.initialize();
|
|
199
|
-
try {
|
|
200
|
-
if (type === 'postgres') {
|
|
201
|
-
await adminDs.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [
|
|
202
|
-
database
|
|
203
|
-
]);
|
|
204
|
-
await adminDs.query(`DROP DATABASE IF EXISTS "${database}"`);
|
|
205
|
-
await adminDs.query(`CREATE DATABASE "${database}"`);
|
|
206
|
-
} else {
|
|
207
|
-
await adminDs.query(`DROP DATABASE IF EXISTS \`${database}\``);
|
|
208
|
-
await adminDs.query(`CREATE DATABASE \`${database}\` CHARACTER SET utf8mb4`);
|
|
209
|
-
}
|
|
210
|
-
console.log(`${label} ✓ Database '${database}' dropped and recreated`);
|
|
211
|
-
} finally{
|
|
212
|
-
await adminDs.destroy();
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
async function resetDatabase(config, tenantId) {
|
|
216
|
-
const { database } = (0, _utils.getDatabaseForTenant)(config, tenantId);
|
|
217
|
-
const label = getLabel(tenantId);
|
|
218
|
-
try {
|
|
219
|
-
clearMigrationFiles(config.migrationsPath, tenantId, label);
|
|
220
|
-
const dbConfig = (0, _utils.resolveDatabaseConnection)(config, tenantId);
|
|
221
|
-
await dropAndRecreateDatabase(dbConfig, label);
|
|
222
|
-
return {
|
|
223
|
-
tenantId,
|
|
224
|
-
database,
|
|
225
|
-
success: true
|
|
226
|
-
};
|
|
227
|
-
} catch (error) {
|
|
228
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
229
|
-
console.error(`${label} ✗ Failed: ${errorMessage}`);
|
|
230
|
-
return {
|
|
231
|
-
tenantId,
|
|
232
|
-
database,
|
|
233
|
-
success: false,
|
|
234
|
-
error: errorMessage
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
async function migrationStatus(config, tenantId) {
|
|
239
|
-
return withDataSource(config, tenantId, async (ds, label)=>{
|
|
240
|
-
const hasPending = await ds.showMigrations();
|
|
241
|
-
console.log(`${label} Pending: ${hasPending ? 'Yes' : 'No'}`);
|
|
242
|
-
return {
|
|
243
|
-
migrationsRun: [
|
|
244
|
-
hasPending ? 'Has pending' : 'Up to date'
|
|
245
|
-
]
|
|
246
|
-
};
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
async function runForAllTenants(config, command) {
|
|
250
|
-
const tenants = (0, _utils.getActiveTenants)(config);
|
|
251
|
-
console.log(`\n🔄 Running '${command}' for ${tenants.length} tenant(s)...\n`);
|
|
252
|
-
const results = [];
|
|
253
|
-
for (const tenant of tenants){
|
|
254
|
-
let result;
|
|
255
|
-
switch(command){
|
|
256
|
-
case 'run':
|
|
257
|
-
result = await runMigrations(config, tenant.id);
|
|
258
|
-
break;
|
|
259
|
-
case 'revert':
|
|
260
|
-
result = await revertMigration(config, tenant.id);
|
|
261
|
-
break;
|
|
262
|
-
case 'status':
|
|
263
|
-
result = await migrationStatus(config, tenant.id);
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
results.push(result);
|
|
267
|
-
console.log('');
|
|
268
|
-
}
|
|
269
|
-
console.log('\n=== Summary ===');
|
|
270
|
-
results.forEach((r)=>{
|
|
271
|
-
const icon = r.success ? '✓' : '✗';
|
|
272
|
-
const msg = r.error ? ` - ${r.error}` : '';
|
|
273
|
-
console.log(`${icon} ${r.tenantId || 'default'}${msg}`);
|
|
274
|
-
});
|
|
275
|
-
return results;
|
|
276
|
-
}
|