@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.
Files changed (69) hide show
  1. package/README.md +2 -2
  2. package/config/index.d.ts +1 -1
  3. package/constants/index.d.ts +1 -1
  4. package/docs/docs.config.d.ts +1 -1
  5. package/docs/index.d.ts +1 -1
  6. package/fesm/229.js +729 -0
  7. package/fesm/config/index.js +126 -1
  8. package/fesm/constants/index.js +29 -1
  9. package/fesm/docs/index.js +288 -1
  10. package/fesm/index.js +124 -5
  11. package/fesm/interfaces/index.js +18 -4
  12. package/fesm/migration/cli.js +19 -2
  13. package/fesm/migration/index.js +45 -3
  14. package/fesm/runtime.js +85 -0
  15. package/fesm/utils/index.js +131 -1
  16. package/index.d.ts +5 -5
  17. package/interfaces/app-config.interfaces.d.ts +1 -1
  18. package/interfaces/index.d.ts +4 -4
  19. package/interfaces/migration.interface.d.ts +2 -2
  20. package/migration/cli.d.ts +0 -1
  21. package/migration/datasource.factory.d.ts +1 -1
  22. package/migration/index.d.ts +3 -3
  23. package/migration/migration.cli.d.ts +1 -1
  24. package/migration/migration.runner.d.ts +1 -1
  25. package/package.json +24 -32
  26. package/utils/datasource-config.builder.d.ts +2 -2
  27. package/utils/index.d.ts +1 -1
  28. package/cjs/config/env-config.service.js +0 -162
  29. package/cjs/config/env-config.service.spec.js +0 -325
  30. package/cjs/config/index.js +0 -18
  31. package/cjs/constants/database.constants.js +0 -20
  32. package/cjs/constants/index.js +0 -18
  33. package/cjs/docs/docs.config.js +0 -276
  34. package/cjs/docs/docs.config.spec.js +0 -923
  35. package/cjs/docs/index.js +0 -18
  36. package/cjs/index.js +0 -23
  37. package/cjs/interfaces/app-config.interfaces.js +0 -4
  38. package/cjs/interfaces/base-entity.interface.js +0 -9
  39. package/cjs/interfaces/database.interface.js +0 -4
  40. package/cjs/interfaces/index.js +0 -21
  41. package/cjs/interfaces/migration.interface.js +0 -4
  42. package/cjs/migration/cli.js +0 -10
  43. package/cjs/migration/datasource.factory.js +0 -43
  44. package/cjs/migration/datasource.factory.spec.js +0 -113
  45. package/cjs/migration/index.js +0 -45
  46. package/cjs/migration/migration.cli.js +0 -231
  47. package/cjs/migration/migration.cli.spec.js +0 -293
  48. package/cjs/migration/migration.runner.js +0 -276
  49. package/cjs/migration/migration.runner.spec.js +0 -268
  50. package/cjs/utils/datasource-config.builder.js +0 -103
  51. package/cjs/utils/datasource-config.builder.spec.js +0 -232
  52. package/cjs/utils/index.js +0 -18
  53. package/fesm/config/env-config.service.js +0 -112
  54. package/fesm/config/env-config.service.spec.js +0 -321
  55. package/fesm/constants/database.constants.js +0 -2
  56. package/fesm/docs/docs.config.js +0 -258
  57. package/fesm/docs/docs.config.spec.js +0 -919
  58. package/fesm/interfaces/app-config.interfaces.js +0 -1
  59. package/fesm/interfaces/base-entity.interface.js +0 -6
  60. package/fesm/interfaces/database.interface.js +0 -1
  61. package/fesm/interfaces/migration.interface.js +0 -1
  62. package/fesm/migration/datasource.factory.js +0 -25
  63. package/fesm/migration/datasource.factory.spec.js +0 -109
  64. package/fesm/migration/migration.cli.js +0 -180
  65. package/fesm/migration/migration.cli.spec.js +0 -289
  66. package/fesm/migration/migration.runner.js +0 -202
  67. package/fesm/migration/migration.runner.spec.js +0 -264
  68. package/fesm/utils/datasource-config.builder.js +0 -84
  69. 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
- }