@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
package/fesm/229.js ADDED
@@ -0,0 +1,729 @@
1
+ import * as __rspack_external_path from "path";
2
+ import * as __rspack_external_typeorm from "typeorm";
3
+ import * as __rspack_external_typeorm_naming_strategies_48a68f8e from "typeorm-naming-strategies";
4
+ import * as __rspack_external_url from "url";
5
+ import * as __rspack_external_dotenv from "dotenv";
6
+ import * as __rspack_external_child_process from "child_process";
7
+ import * as __rspack_external_fs from "fs";
8
+ export const __rspack_esm_id = 229;
9
+ export const __rspack_esm_ids = [229];
10
+ export const __webpack_modules__ = {
11
+ 398(module) {
12
+ function __rspack_empty_async_context(req) {
13
+ // Here Promise.resolve().then() is used instead of new Promise() to prevent
14
+ // uncaught exception popping up in devtools
15
+ return Promise.resolve().then(function() {
16
+ var e = new Error("Cannot find module '" + req + "'");
17
+ e.code = 'MODULE_NOT_FOUND';
18
+ throw e;
19
+ });
20
+ }
21
+ __rspack_empty_async_context.keys = () => ([]);
22
+ __rspack_empty_async_context.resolve = __rspack_empty_async_context;
23
+ __rspack_empty_async_context.id = 398;
24
+ module.exports = __rspack_empty_async_context;
25
+
26
+
27
+ },
28
+ 892(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
29
+
30
+ // EXPORTS
31
+ __webpack_require__.d(__webpack_exports__, {
32
+ K: () => (/* reexport */ envConfig)
33
+ });
34
+
35
+ ;// CONCATENATED MODULE: external "dotenv"
36
+
37
+ ;// CONCATENATED MODULE: ./projects/nestjs-core/src/config/env-config.service.ts
38
+
39
+ __rspack_external_dotenv.config();
40
+ let EnvConfigService = class EnvConfigService {
41
+ env;
42
+ restrictedKeys = {
43
+ FRONTEND_URL: 'getFrontendUrl',
44
+ ALLOW_ORIGINS: 'getOrigins',
45
+ PORT: 'getPort',
46
+ MODE: 'isProduction',
47
+ DB_TYPE: 'getTypeOrmConfig',
48
+ DB_HOST: 'getTypeOrmConfig',
49
+ DB_PORT: 'getTypeOrmConfig',
50
+ DB_USER: 'getTypeOrmConfig',
51
+ DB_PASSWORD: 'getTypeOrmConfig',
52
+ DB_NAME: 'getTypeOrmConfig'
53
+ };
54
+ constructor(env){
55
+ this.env = env;
56
+ }
57
+ getValue(key, throwOnMissing = true) {
58
+ const value = this.env[key];
59
+ if (!value && throwOnMissing) {
60
+ throw new Error(`Config error - missing env.${key}`);
61
+ }
62
+ return value ?? '';
63
+ }
64
+ tryGetValue(key, throwOnMissing = false) {
65
+ if (this.restrictedKeys[key]) {
66
+ throw new Error(`Access denied for env key "${key}". Use the method \`${this.restrictedKeys[key]}()\` instead.`);
67
+ }
68
+ return this.getValue(key, throwOnMissing);
69
+ }
70
+ getNumber(key, throwOnMissing = true) {
71
+ return Number(this.getValue(key, throwOnMissing));
72
+ }
73
+ getBoolean(key, throwOnMissing = true) {
74
+ return this.getValue(key, throwOnMissing).toLowerCase() === 'true';
75
+ }
76
+ getPort() {
77
+ return this.getNumber('PORT', false) || 3000;
78
+ }
79
+ isProduction() {
80
+ return this.getValue('MODE', false).toUpperCase() !== 'DEV';
81
+ }
82
+ getOrigins() {
83
+ const origins = this.getValue('ALLOW_ORIGINS');
84
+ return origins ? origins.split(',').map((o)=>o.trim()) : [];
85
+ }
86
+ getTypeOrmConfig() {
87
+ const type = this.getValue('DB_TYPE', false) || 'mysql';
88
+ const defaultPort = type === 'postgres' ? 5432 : 3306;
89
+ return {
90
+ type,
91
+ host: this.getValue('DB_HOST', false) || 'localhost',
92
+ port: this.getNumber('DB_PORT', false) || defaultPort,
93
+ username: this.getValue('DB_USER', false) || 'root',
94
+ password: this.getValue('DB_PASSWORD', false) || '',
95
+ database: this.getValue('DB_NAME', false) || 'flusys_main'
96
+ };
97
+ }
98
+ getJwtConfig() {
99
+ return {
100
+ secret: this.getValue('JWT_SECRET'),
101
+ expiration: this.getValue('JWT_EXPIRATION', false) || '1h',
102
+ refreshSecret: this.getValue('REFRESH_TOKEN_SECRET'),
103
+ refreshExpiration: this.getValue('REFRESH_TOKEN_EXPIRATION', false) || '7d'
104
+ };
105
+ }
106
+ getRedisUrl() {
107
+ return this.getValue('REDIS_URL', false) || 'redis://localhost:6379';
108
+ }
109
+ getMailConfig() {
110
+ return {
111
+ MAIL_FROM: this.getValue('MAIL_FROM', false) || '',
112
+ MAIL_APP_PASSWORD: this.getValue('MAIL_APP_PASSWORD', false) || ''
113
+ };
114
+ }
115
+ getTenantId() {
116
+ return this.getValue('TENANT_ID', false) || null;
117
+ }
118
+ useTenantMode() {
119
+ return this.getValue('USE_TENANT_MODE', false).toLowerCase() === 'true';
120
+ }
121
+ getLogConfig() {
122
+ return {
123
+ dir: this.getValue('LOG_DIR', false) || 'logs',
124
+ level: this.getValue('LOG_LEVEL', false) || (this.isProduction() ? 'info' : 'debug'),
125
+ maxSize: this.getValue('LOG_MAX_SIZE', false) || '20m',
126
+ maxFiles: this.getValue('LOG_MAX_FILES', false) || '14d',
127
+ disableHttpLogging: this.getValue('DISABLE_HTTP_LOGGING', false).toLowerCase() === 'true'
128
+ };
129
+ }
130
+ getEnv() {
131
+ return process.env;
132
+ }
133
+ };
134
+ const envConfig = new EnvConfigService(process.env);
135
+
136
+
137
+ ;// CONCATENATED MODULE: ./projects/nestjs-core/src/config/index.ts
138
+
139
+
140
+
141
+ },
142
+ 193(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
143
+
144
+ // EXPORTS
145
+ __webpack_require__.d(__webpack_exports__, {
146
+ O: () => (/* binding */ createMigrationDataSource),
147
+ w: () => (/* binding */ initializeDataSource)
148
+ });
149
+
150
+ // EXTERNAL MODULE: external "typeorm"
151
+ var external_typeorm_ = __webpack_require__(158);
152
+ ;// CONCATENATED MODULE: external "typeorm-naming-strategies"
153
+
154
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/utils/datasource-config.builder.ts
155
+ var datasource_config_builder = __webpack_require__(722);
156
+ ;// CONCATENATED MODULE: ./projects/nestjs-core/src/migration/datasource.factory.ts
157
+
158
+
159
+
160
+ function createMigrationDataSource(options) {
161
+ const { config, tenantId } = options;
162
+ const { database, tenant, tenantConfig } = (0,datasource_config_builder/* .getDatabaseForTenant */.LH)(config, tenantId);
163
+ console.log(`\nšŸ“¦ Database: ${database}${tenant ? ` [${tenant.name}]` : ' [default]'}`);
164
+ console.log(`šŸ“ Migrations: migrations/${tenantId || 'default'}/`);
165
+ if (config.bootstrapAppConfig?.databaseMode === 'multi-tenant' && !tenantId && config.tenants && config.tenants.length > 0) {
166
+ console.log(`\nšŸ’” Multi-tenant mode. Available tenants:`);
167
+ config.tenants.forEach((t)=>console.log(` - TENANT_ID=${t.id} → ${t.database}`));
168
+ }
169
+ const dbConfig = (0,datasource_config_builder/* .resolveDatabaseConnection */.ul)(config, tenantId);
170
+ const entities = (0,datasource_config_builder/* .resolveEntities */.Md)(config, tenantConfig);
171
+ const dsOptions = (0,datasource_config_builder/* .buildDataSourceOptions */.QP)(dbConfig, entities, (0,datasource_config_builder/* .getMigrationsGlobPattern */.Q0)(config.migrationsPath, tenantId), config.migrationsTableName);
172
+ return new external_typeorm_.DataSource({
173
+ ...dsOptions,
174
+ namingStrategy: new __rspack_external_typeorm_naming_strategies_48a68f8e.SnakeNamingStrategy()
175
+ });
176
+ }
177
+ async function initializeDataSource(options) {
178
+ const ds = createMigrationDataSource(options);
179
+ await ds.initialize();
180
+ return ds;
181
+ }
182
+
183
+
184
+ },
185
+ 164(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
186
+
187
+ // EXPORTS
188
+ __webpack_require__.d(__webpack_exports__, {
189
+ w: () => (/* binding */ runMigrationCli)
190
+ });
191
+
192
+ // EXTERNAL MODULE: external "path"
193
+ var external_path_ = __webpack_require__(521);
194
+ ;// CONCATENATED MODULE: external "url"
195
+
196
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/config/index.ts + 2 modules
197
+ var src_config = __webpack_require__(892);
198
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/utils/datasource-config.builder.ts
199
+ var datasource_config_builder = __webpack_require__(722);
200
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/migration/migration.runner.ts + 2 modules
201
+ var migration_runner = __webpack_require__(654);
202
+ ;// CONCATENATED MODULE: ./projects/nestjs-core/src/migration/migration.cli.ts
203
+
204
+
205
+
206
+
207
+
208
+ function showHelp() {
209
+ console.log(`
210
+ Migration CLI
211
+
212
+ Usage:
213
+ npm run migration <command> [options]
214
+
215
+ Commands:
216
+ generate --name=<Name> Generate migration
217
+ run Run pending migrations
218
+ revert Revert last migration
219
+ reset Drop db, wipe migration files, recreate db, generate + run initial migration (dev only)
220
+ status Show migration status
221
+ run:all Run for all tenants
222
+ revert:all Revert for all tenants
223
+ status:all Status for all tenants
224
+
225
+ Options:
226
+ --config=<path> Migration config file (default: src/persistence/migration.config.ts)
227
+ --name=<Name> Migration name (for generate command)
228
+ --force Required to run 'reset' when MODE is not 'dev'
229
+
230
+ Environment:
231
+ TENANT_ID Target tenant (default: uses default database)
232
+ MIGRATION_CONFIG Default config path (overrides auto-detection)
233
+
234
+ Examples:
235
+ npm run migration generate --name=CreateUsers
236
+ npm run migration -- generate --name=CreateUsers --config=src/persistence/migration.config.ts
237
+ TENANT_ID=tenant1 npm run migration run
238
+ npm run migration run:all
239
+ npm run migration reset
240
+ `);
241
+ }
242
+ function parseArgs() {
243
+ const args = process.argv.slice(2);
244
+ let command;
245
+ let name;
246
+ let configPath;
247
+ let datasourcePath;
248
+ let force = false;
249
+ for(let i = 0; i < args.length; i++){
250
+ const arg = args[i];
251
+ if (arg.startsWith('--name=')) {
252
+ name = arg.split('=')[1];
253
+ } else if (arg.startsWith('--config=')) {
254
+ configPath = arg.split('=')[1];
255
+ } else if (arg.startsWith('--datasource=')) {
256
+ datasourcePath = arg.split('=')[1];
257
+ } else if (arg === '--force') {
258
+ force = true;
259
+ } else if (!arg.startsWith('-') && !command) {
260
+ command = arg;
261
+ }
262
+ }
263
+ return {
264
+ command,
265
+ name,
266
+ configPath,
267
+ datasourcePath,
268
+ force
269
+ };
270
+ }
271
+ async function loadConfig(configPath) {
272
+ const absolutePath = external_path_.isAbsolute(configPath) ? configPath : external_path_.resolve(process.cwd(), configPath);
273
+ const module = await __webpack_require__(398)((0,__rspack_external_url.pathToFileURL)(absolutePath).href);
274
+ return module.migrationConfig || module.default?.migrationConfig || module;
275
+ }
276
+ async function runMigrationCli(configOrPath) {
277
+ const { command, name, configPath: argConfigPath, datasourcePath, force } = parseArgs();
278
+ const tenantId = src_config/* .envConfig.getTenantId */.K.getTenantId() ?? undefined;
279
+ // npm passes --name=X as npm_config_name
280
+ const migrationName = src_config/* .envConfig.tryGetValue */.K.tryGetValue('npm_config_name') || src_config/* .envConfig.tryGetValue */.K.tryGetValue('MIGRATION_NAME') || name;
281
+ // Resolve config
282
+ let config;
283
+ let dsPath = datasourcePath;
284
+ if (typeof configOrPath === 'string') {
285
+ config = await loadConfig(configOrPath);
286
+ dsPath = dsPath || configOrPath;
287
+ } else if (configOrPath) {
288
+ config = configOrPath;
289
+ } else if (argConfigPath) {
290
+ config = await loadConfig(argConfigPath);
291
+ dsPath = dsPath || argConfigPath;
292
+ } else {
293
+ // Try paths in order: env var, then common defaults
294
+ const envConfigPath = src_config/* .envConfig.tryGetValue */.K.tryGetValue('MIGRATION_CONFIG');
295
+ const defaultPaths = [
296
+ envConfigPath,
297
+ 'src/persistence/migration.config.ts',
298
+ 'src/persistence/migration.config.js',
299
+ 'persistence/migration.config.ts',
300
+ 'persistence/migration.config.js'
301
+ ].filter(Boolean);
302
+ let loaded = false;
303
+ for (const tryPath of defaultPaths){
304
+ try {
305
+ config = await loadConfig(tryPath);
306
+ dsPath = dsPath || tryPath;
307
+ loaded = true;
308
+ break;
309
+ } catch {
310
+ // Try next path
311
+ }
312
+ }
313
+ if (!loaded) {
314
+ console.error('āŒ Config not found. Use --config=<path> or set MIGRATION_CONFIG env var');
315
+ console.error(' Tried paths:', defaultPaths.join(', '));
316
+ showHelp();
317
+ process.exit(1);
318
+ }
319
+ }
320
+ if (!command) {
321
+ showHelp();
322
+ return;
323
+ }
324
+ // Multi-tenant batch commands
325
+ if (command.endsWith(':all')) {
326
+ if (config.bootstrapAppConfig?.databaseMode === 'single') {
327
+ console.error('āŒ Multi-tenant mode not enabled');
328
+ process.exit(1);
329
+ }
330
+ const action = command.split(':')[0];
331
+ const results = await (0,migration_runner/* .runForAllTenants */.XR)(config, action);
332
+ if (results.some((r)=>!r.success)) process.exit(1);
333
+ return;
334
+ }
335
+ // Show target info
336
+ const { database } = (0,datasource_config_builder/* .getDatabaseForTenant */.LH)(config, tenantId);
337
+ const folder = (0,datasource_config_builder/* .getMigrationsFolderPath */.jr)(config.migrationsPath, tenantId);
338
+ console.log(`\nšŸ“¦ Database: ${database}`);
339
+ console.log(`šŸ“ Migrations: ${external_path_.relative(process.cwd(), folder)}`);
340
+ switch(command){
341
+ case 'generate':
342
+ if (!migrationName) {
343
+ console.error('āŒ Migration name required. Use --name=<Name>');
344
+ process.exit(1);
345
+ }
346
+ await (0,migration_runner/* .generateMigration */.iL)(config, migrationName, tenantId, dsPath);
347
+ break;
348
+ case 'run':
349
+ {
350
+ const result = await (0,migration_runner/* .runMigrations */.vI)(config, tenantId);
351
+ if (!result.success) process.exit(1);
352
+ break;
353
+ }
354
+ case 'revert':
355
+ {
356
+ const result = await (0,migration_runner/* .revertMigration */.$N)(config, tenantId);
357
+ if (!result.success) process.exit(1);
358
+ break;
359
+ }
360
+ case 'reset':
361
+ {
362
+ if (src_config/* .envConfig.isProduction */.K.isProduction() && !force) {
363
+ console.error('āŒ Refusing to reset database outside dev mode. Pass --force to override.');
364
+ process.exit(1);
365
+ }
366
+ const result = await (0,migration_runner/* .resetDatabase */.$7)(config, tenantId);
367
+ if (!result.success) process.exit(1);
368
+ await (0,migration_runner/* .generateMigration */.iL)(config, migrationName || 'Init', tenantId, dsPath);
369
+ const runResult = await (0,migration_runner/* .runMigrations */.vI)(config, tenantId);
370
+ if (!runResult.success) process.exit(1);
371
+ break;
372
+ }
373
+ case 'status':
374
+ await (0,migration_runner/* .migrationStatus */.vd)(config, tenantId);
375
+ break;
376
+ default:
377
+ console.error(`āŒ Unknown command: ${command}`);
378
+ showHelp();
379
+ process.exit(1);
380
+ }
381
+ }
382
+
383
+
384
+ },
385
+ 654(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
386
+
387
+ // EXPORTS
388
+ __webpack_require__.d(__webpack_exports__, {
389
+ Mg: () => (/* binding */ ensureMigrationsFolder),
390
+ iL: () => (/* binding */ generateMigration),
391
+ vd: () => (/* binding */ migrationStatus),
392
+ $7: () => (/* binding */ resetDatabase),
393
+ $N: () => (/* binding */ revertMigration),
394
+ XR: () => (/* binding */ runForAllTenants),
395
+ vI: () => (/* binding */ runMigrations)
396
+ });
397
+
398
+ ;// CONCATENATED MODULE: external "child_process"
399
+
400
+ ;// CONCATENATED MODULE: external "fs"
401
+
402
+ // EXTERNAL MODULE: external "path"
403
+ var external_path_ = __webpack_require__(521);
404
+ // EXTERNAL MODULE: external "typeorm"
405
+ var external_typeorm_ = __webpack_require__(158);
406
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/config/index.ts + 2 modules
407
+ var src_config = __webpack_require__(892);
408
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/utils/datasource-config.builder.ts
409
+ var datasource_config_builder = __webpack_require__(722);
410
+ // EXTERNAL MODULE: ./projects/nestjs-core/src/migration/datasource.factory.ts + 1 modules
411
+ var datasource_factory = __webpack_require__(193);
412
+ ;// CONCATENATED MODULE: ./projects/nestjs-core/src/migration/migration.runner.ts
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420
+ function getLabel(tenantId) {
421
+ return tenantId ? `[${tenantId}]` : '[default]';
422
+ }
423
+ async function withDataSource(config, tenantId, operation) {
424
+ const { database } = (0,datasource_config_builder/* .getDatabaseForTenant */.LH)(config, tenantId);
425
+ const label = getLabel(tenantId);
426
+ try {
427
+ const ds = await (0,datasource_factory/* .initializeDataSource */.w)({
428
+ config,
429
+ tenantId
430
+ });
431
+ const partial = await operation(ds, label);
432
+ await ds.destroy();
433
+ return {
434
+ tenantId,
435
+ database,
436
+ success: true,
437
+ ...partial
438
+ };
439
+ } catch (error) {
440
+ const errorMessage = error instanceof Error ? error.message : String(error);
441
+ console.error(`${label} āœ— Failed: ${errorMessage}`);
442
+ return {
443
+ tenantId,
444
+ database,
445
+ success: false,
446
+ error: errorMessage
447
+ };
448
+ }
449
+ }
450
+ function ensureMigrationsFolder(basePath, tenantId) {
451
+ const folder = (0,datasource_config_builder/* .getMigrationsFolderPath */.jr)(basePath, tenantId);
452
+ if (!__rspack_external_fs.existsSync(folder)) {
453
+ __rspack_external_fs.mkdirSync(folder, {
454
+ recursive: true
455
+ });
456
+ console.log(`šŸ“ Created: ${folder}`);
457
+ }
458
+ return folder;
459
+ }
460
+ async function generateMigration(config, name, tenantId, datasourcePath) {
461
+ const label = tenantId ? `[${tenantId}]` : '[default]';
462
+ const folder = ensureMigrationsFolder(config.migrationsPath, tenantId);
463
+ console.log(`${label} Generating migration: ${name}`);
464
+ console.log(`${label} Target folder: ${folder}`);
465
+ const dsPath = datasourcePath || findDatasourcePath();
466
+ const migrationFile = external_path_.join(folder, name);
467
+ const command = `tsx ./node_modules/typeorm/cli.js migration:generate "${migrationFile}" -d "${dsPath}"`;
468
+ (0,__rspack_external_child_process.execSync)(command, {
469
+ stdio: 'inherit',
470
+ env: {
471
+ ...src_config/* .envConfig.getEnv */.K.getEnv(),
472
+ TENANT_ID: tenantId || ''
473
+ },
474
+ cwd: process.cwd()
475
+ });
476
+ console.log(`${label} āœ“ Generated!`);
477
+ }
478
+ function findDatasourcePath() {
479
+ const possiblePaths = [
480
+ 'src/persistence/migration.config.ts',
481
+ 'projects/flusysnest/src/persistence/migration.config.ts'
482
+ ];
483
+ for (const p of possiblePaths){
484
+ if (__rspack_external_fs.existsSync(external_path_.join(process.cwd(), p))) {
485
+ return p;
486
+ }
487
+ }
488
+ throw new Error('Could not find datasource file. Specify with --datasource=<path>');
489
+ }
490
+ async function runMigrations(config, tenantId) {
491
+ return withDataSource(config, tenantId, async (ds, label)=>{
492
+ const migrations = await ds.runMigrations();
493
+ if (migrations.length === 0) {
494
+ console.log(`${label} No pending migrations.`);
495
+ } else {
496
+ console.log(`${label} āœ“ Executed ${migrations.length} migration(s):`);
497
+ migrations.forEach((m)=>console.log(` - ${m.name}`));
498
+ }
499
+ return {
500
+ migrationsRun: migrations.map((m)=>m.name)
501
+ };
502
+ });
503
+ }
504
+ async function revertMigration(config, tenantId) {
505
+ return withDataSource(config, tenantId, async (ds, label)=>{
506
+ await ds.undoLastMigration();
507
+ console.log(`${label} āœ“ Reverted!`);
508
+ return {};
509
+ });
510
+ }
511
+ function clearMigrationFiles(basePath, tenantId, label) {
512
+ const folder = (0,datasource_config_builder/* .getMigrationsFolderPath */.jr)(basePath, tenantId);
513
+ if (!__rspack_external_fs.existsSync(folder)) return;
514
+ const files = __rspack_external_fs.readdirSync(folder).filter((f)=>f.endsWith('.ts') || f.endsWith('.js'));
515
+ files.forEach((file)=>__rspack_external_fs.rmSync(external_path_.join(folder, file)));
516
+ console.log(`${label} āœ“ Removed ${files.length} migration file(s) from ${folder}`);
517
+ }
518
+ async function dropAndRecreateDatabase(dbConfig, label) {
519
+ const { type, database } = dbConfig;
520
+ if (type === 'sqlite') {
521
+ if (database && __rspack_external_fs.existsSync(database)) __rspack_external_fs.rmSync(database);
522
+ console.log(`${label} āœ“ Deleted sqlite file`);
523
+ return;
524
+ }
525
+ if (type !== 'mysql' && type !== 'mariadb' && type !== 'postgres') {
526
+ throw new Error(`Database reset is not supported for type '${type}'`);
527
+ }
528
+ const adminDs = new external_typeorm_.DataSource({
529
+ type,
530
+ host: dbConfig.host,
531
+ port: dbConfig.port,
532
+ username: dbConfig.username,
533
+ password: dbConfig.password,
534
+ database: type === 'postgres' ? 'postgres' : undefined
535
+ });
536
+ await adminDs.initialize();
537
+ try {
538
+ if (type === 'postgres') {
539
+ await adminDs.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [
540
+ database
541
+ ]);
542
+ await adminDs.query(`DROP DATABASE IF EXISTS "${database}"`);
543
+ await adminDs.query(`CREATE DATABASE "${database}"`);
544
+ } else {
545
+ await adminDs.query(`DROP DATABASE IF EXISTS \`${database}\``);
546
+ await adminDs.query(`CREATE DATABASE \`${database}\` CHARACTER SET utf8mb4`);
547
+ }
548
+ console.log(`${label} āœ“ Database '${database}' dropped and recreated`);
549
+ } finally{
550
+ await adminDs.destroy();
551
+ }
552
+ }
553
+ async function resetDatabase(config, tenantId) {
554
+ const { database } = (0,datasource_config_builder/* .getDatabaseForTenant */.LH)(config, tenantId);
555
+ const label = getLabel(tenantId);
556
+ try {
557
+ clearMigrationFiles(config.migrationsPath, tenantId, label);
558
+ const dbConfig = (0,datasource_config_builder/* .resolveDatabaseConnection */.ul)(config, tenantId);
559
+ await dropAndRecreateDatabase(dbConfig, label);
560
+ return {
561
+ tenantId,
562
+ database,
563
+ success: true
564
+ };
565
+ } catch (error) {
566
+ const errorMessage = error instanceof Error ? error.message : String(error);
567
+ console.error(`${label} āœ— Failed: ${errorMessage}`);
568
+ return {
569
+ tenantId,
570
+ database,
571
+ success: false,
572
+ error: errorMessage
573
+ };
574
+ }
575
+ }
576
+ async function migrationStatus(config, tenantId) {
577
+ return withDataSource(config, tenantId, async (ds, label)=>{
578
+ const hasPending = await ds.showMigrations();
579
+ console.log(`${label} Pending: ${hasPending ? 'Yes' : 'No'}`);
580
+ return {
581
+ migrationsRun: [
582
+ hasPending ? 'Has pending' : 'Up to date'
583
+ ]
584
+ };
585
+ });
586
+ }
587
+ async function runForAllTenants(config, command) {
588
+ const tenants = (0,datasource_config_builder/* .getActiveTenants */.SP)(config);
589
+ console.log(`\nšŸ”„ Running '${command}' for ${tenants.length} tenant(s)...\n`);
590
+ const results = [];
591
+ for (const tenant of tenants){
592
+ let result;
593
+ switch(command){
594
+ case 'run':
595
+ result = await runMigrations(config, tenant.id);
596
+ break;
597
+ case 'revert':
598
+ result = await revertMigration(config, tenant.id);
599
+ break;
600
+ case 'status':
601
+ result = await migrationStatus(config, tenant.id);
602
+ break;
603
+ }
604
+ results.push(result);
605
+ console.log('');
606
+ }
607
+ console.log('\n=== Summary ===');
608
+ results.forEach((r)=>{
609
+ const icon = r.success ? 'āœ“' : 'āœ—';
610
+ const msg = r.error ? ` - ${r.error}` : '';
611
+ console.log(`${icon} ${r.tenantId || 'default'}${msg}`);
612
+ });
613
+ return results;
614
+ }
615
+
616
+
617
+ },
618
+ 722(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
619
+ /**
620
+ * Build DataSource options from database config
621
+ */ function buildDataSourceOptions(config, entities, migrationsPath, migrationsTableName = 'migrations') {
622
+ return {
623
+ type: config.type,
624
+ host: config.host,
625
+ port: config.port,
626
+ username: config.username,
627
+ password: config.password,
628
+ database: config.database || '',
629
+ entities,
630
+ migrations: [
631
+ migrationsPath
632
+ ],
633
+ migrationsTableName,
634
+ synchronize: false
635
+ };
636
+ }
637
+ /**
638
+ * Get migration folder path for a tenant
639
+ */ function getMigrationsFolderPath(basePath, tenantId) {
640
+ const folder = tenantId || 'default';
641
+ return `${basePath}/${folder}`;
642
+ }
643
+ /**
644
+ * Get migrations glob pattern for a tenant
645
+ */ function getMigrationsGlobPattern(basePath, tenantId) {
646
+ return `${getMigrationsFolderPath(basePath, tenantId)}/*{.ts,.js}`;
647
+ }
648
+ /**
649
+ * Get database and config for a tenant (or default)
650
+ */ function getDatabaseForTenant(config, tenantId) {
651
+ if (tenantId && config.tenants) {
652
+ const tenant = config.tenants.find((t)=>t.id === tenantId);
653
+ if (!tenant) {
654
+ throw new Error(`Tenant '${tenantId}' not found. Available: ${config.tenants.map((t)=>t.id).join(', ')}`);
655
+ }
656
+ return {
657
+ database: tenant.database,
658
+ tenant,
659
+ tenantConfig: tenant
660
+ };
661
+ }
662
+ // Default config - use bootstrapAppConfig for feature flags
663
+ const defaultTenantConfig = {
664
+ id: 'default',
665
+ database: config.defaultDatabaseConfig.database || 'default',
666
+ enableCompanyFeature: config.bootstrapAppConfig?.enableCompanyFeature ?? false,
667
+ permissionMode: config.bootstrapAppConfig?.permissionMode ?? 'FULL'
668
+ };
669
+ return {
670
+ database: defaultTenantConfig.database,
671
+ tenantConfig: defaultTenantConfig
672
+ };
673
+ }
674
+ /**
675
+ * Resolve full connection details for a tenant.
676
+ */ function resolveDatabaseConnection(config, tenantId) {
677
+ const { database, tenant } = getDatabaseForTenant(config, tenantId);
678
+ return tenant ? {
679
+ ...config.defaultDatabaseConfig,
680
+ host: tenant.host ?? config.defaultDatabaseConfig.host,
681
+ port: tenant.port ?? config.defaultDatabaseConfig.port,
682
+ username: tenant.username ?? config.defaultDatabaseConfig.username,
683
+ password: tenant.password ?? config.defaultDatabaseConfig.password,
684
+ database: tenant.database
685
+ } : {
686
+ ...config.defaultDatabaseConfig,
687
+ database
688
+ };
689
+ }
690
+ /**
691
+ * Resolve entities based on tenant config
692
+ */ function resolveEntities(config, tenantConfig) {
693
+ if (typeof config.entities === 'function') {
694
+ return config.entities(tenantConfig);
695
+ }
696
+ return config.entities;
697
+ }
698
+ /**
699
+ * Get active tenants from config
700
+ */ function getActiveTenants(config) {
701
+ return config.tenants || [];
702
+ }
703
+
704
+ __webpack_require__.d(__webpack_exports__, {
705
+ LH: () => (getDatabaseForTenant),
706
+ Md: () => (resolveEntities),
707
+ Q0: () => (getMigrationsGlobPattern),
708
+ QP: () => (buildDataSourceOptions),
709
+ SP: () => (getActiveTenants),
710
+ jr: () => (getMigrationsFolderPath),
711
+ ul: () => (resolveDatabaseConnection)
712
+ });
713
+
714
+
715
+ },
716
+ 521(module) {
717
+
718
+ module.exports = __rspack_external_path;
719
+
720
+
721
+ },
722
+ 158(module) {
723
+
724
+ module.exports = __rspack_external_typeorm;
725
+
726
+
727
+ },
728
+
729
+ };