@flusys/nestjs-core 1.1.0-beta → 2.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 (56) hide show
  1. package/README.md +505 -63
  2. package/cjs/config/env-config.service.js +1 -1
  3. package/cjs/docs/docs.config.js +77 -3
  4. package/cjs/docs/index.js +0 -1
  5. package/cjs/interfaces/base-entity.interface.js +5 -3
  6. package/cjs/interfaces/database.interface.js +1 -3
  7. package/cjs/migration/datasource.factory.js +1 -3
  8. package/cjs/migration/index.js +0 -12
  9. package/cjs/migration/migration.cli.js +1 -17
  10. package/cjs/migration/migration.runner.js +37 -65
  11. package/cjs/seeders/base-seeder.js +6 -25
  12. package/cjs/seeders/cli.js +65 -172
  13. package/cjs/seeders/data-generator.js +96 -142
  14. package/cjs/seeders/entity-reader.js +0 -17
  15. package/cjs/seeders/field-patterns.js +172 -0
  16. package/cjs/seeders/index.js +16 -8
  17. package/cjs/seeders/seed-config.js +9 -48
  18. package/cjs/seeders/seed-runner.js +8 -14
  19. package/cjs/utils/datasource-config.builder.js +2 -14
  20. package/docs/docs.config.d.ts +7 -0
  21. package/docs/index.d.ts +0 -1
  22. package/fesm/config/env-config.service.js +1 -1
  23. package/fesm/docs/docs.config.js +68 -0
  24. package/fesm/docs/index.js +0 -1
  25. package/fesm/interfaces/app-config.interfaces.js +1 -3
  26. package/fesm/interfaces/base-entity.interface.js +5 -5
  27. package/fesm/interfaces/database.interface.js +1 -5
  28. package/fesm/migration/cli.js +1 -20
  29. package/fesm/migration/datasource.factory.js +3 -20
  30. package/fesm/migration/index.js +0 -14
  31. package/fesm/migration/migration.cli.js +1 -17
  32. package/fesm/migration/migration.runner.js +43 -132
  33. package/fesm/seeders/base-seeder.js +7 -51
  34. package/fesm/seeders/cli.js +65 -182
  35. package/fesm/seeders/data-generator.js +96 -149
  36. package/fesm/seeders/entity-reader.js +0 -17
  37. package/fesm/seeders/field-patterns.js +143 -0
  38. package/fesm/seeders/index.js +3 -7
  39. package/fesm/seeders/seed-config.js +9 -59
  40. package/fesm/seeders/seed-runner.js +8 -14
  41. package/fesm/utils/datasource-config.builder.js +2 -13
  42. package/interfaces/base-entity.interface.d.ts +3 -0
  43. package/package.json +2 -2
  44. package/seeders/data-generator.d.ts +1 -1
  45. package/seeders/entity-reader.d.ts +0 -1
  46. package/seeders/field-patterns.d.ts +12 -0
  47. package/seeders/index.d.ts +3 -3
  48. package/seeders/seed-config.d.ts +1 -0
  49. package/seeders/seed-runner.d.ts +1 -0
  50. package/utils/datasource-config.builder.d.ts +0 -1
  51. package/cjs/docs/docs.setup.js +0 -14
  52. package/cjs/seeders/template-generator.js +0 -297
  53. package/docs/docs.setup.d.ts +0 -3
  54. package/fesm/docs/docs.setup.js +0 -4
  55. package/fesm/seeders/template-generator.js +0 -257
  56. package/seeders/template-generator.d.ts +0 -16
@@ -12,10 +12,7 @@ Object.defineProperty(exports, "runSeedCli", {
12
12
  const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
13
13
  const _typeorm = require("typeorm");
14
14
  const _config = require("../config");
15
- const _entityreader = require("./entity-reader");
16
- const _templategenerator = require("./template-generator");
17
15
  const _seedrunner = require("./seed-runner");
18
- const _seedconfig = require("./seed-config");
19
16
  function _getRequireWildcardCache(nodeInterop) {
20
17
  if (typeof WeakMap !== "function") return null;
21
18
  var cacheBabelInterop = new WeakMap();
@@ -57,9 +54,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
57
54
  }
58
55
  return newObj;
59
56
  }
60
- /**
61
- * Show help message
62
- */ function showHelp() {
57
+ function showHelp() {
63
58
  console.log(`
64
59
  Seed Data CLI
65
60
 
@@ -67,7 +62,6 @@ Usage:
67
62
  npm run seed:<command> [options]
68
63
 
69
64
  Commands:
70
- generate Generate seeder template files
71
65
  run Execute seeders for all entities
72
66
  run:all Execute seeders for all tenants (multi-tenant mode)
73
67
  clear Clear all seeded data
@@ -81,24 +75,17 @@ Options:
81
75
  --hard Hard delete when clearing (ignore soft delete)
82
76
  --tenant=<id> Target specific tenant (multi-tenant mode)
83
77
 
84
- Environment:
85
- MIGRATION_CONFIG Default config path (overrides auto-detection)
86
-
87
78
  Examples:
88
- npm run seed:generate
89
79
  npm run seed:run
90
80
  npm run seed:run -- --count=50 --clear
91
81
  npm run seed:run -- --entity=User --count=100
92
- npm run seed:run -- --config=src/persistence/migration.config.ts
93
82
  npm run seed:clear
94
83
  npm run seed:clear -- --hard
95
84
  npm run seed:status
96
85
  npm run seed:run:all
97
86
  `);
98
87
  }
99
- /**
100
- * Parse command-line arguments
101
- */ function parseArgs() {
88
+ function parseArgs() {
102
89
  const args = process.argv.slice(2);
103
90
  let command;
104
91
  let count;
@@ -107,8 +94,7 @@ Examples:
107
94
  let hard = false;
108
95
  let tenant;
109
96
  let configPath;
110
- for(let i = 0; i < args.length; i++){
111
- const arg = args[i];
97
+ for (const arg of args){
112
98
  if (arg.startsWith('--count=')) {
113
99
  count = parseInt(arg.split('=')[1], 10);
114
100
  } else if (arg === '--clear') {
@@ -135,21 +121,15 @@ Examples:
135
121
  configPath
136
122
  };
137
123
  }
138
- // Resolved config path (set once during CLI initialization)
139
124
  let resolvedConfigPath;
140
- /**
141
- * Resolve migration config path with auto-detection
142
- */ async function resolveConfigPath(explicitPath) {
125
+ async function resolveConfigPath(explicitPath) {
143
126
  if (resolvedConfigPath) return resolvedConfigPath;
144
- // Try paths in order: explicit, env var, then common defaults
145
127
  const envConfigPath = _config.envConfig.tryGetValue('MIGRATION_CONFIG');
146
128
  const defaultPaths = [
147
129
  explicitPath,
148
130
  envConfigPath,
149
131
  'src/persistence/migration.config.ts',
150
- 'src/persistence/migration.config.js',
151
- 'persistence/migration.config.ts',
152
- 'persistence/migration.config.js'
132
+ 'src/persistence/migration.config.js'
153
133
  ].filter(Boolean);
154
134
  for (const tryPath of defaultPaths){
155
135
  const absolutePath = _path.isAbsolute(tryPath) ? tryPath : _path.resolve(process.cwd(), tryPath);
@@ -162,97 +142,41 @@ let resolvedConfigPath;
162
142
  }
163
143
  }
164
144
  console.error('āŒ Config not found. Use --config=<path> or set MIGRATION_CONFIG env var');
165
- console.error(' Tried paths:', defaultPaths.join(', '));
166
145
  process.exit(1);
167
146
  }
168
- /**
169
- * Load DataSource configuration
170
- */ async function loadDataSource(tenantId, configPath) {
147
+ async function loadDataSource(tenantId, configPath) {
171
148
  const resolvedPath = await resolveConfigPath(configPath);
172
- try {
173
- const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
174
- const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
175
- // Get database config for tenant
176
- const dbConfig = tenantId ? migrationConfig.tenants?.find((t)=>t.tenantId === tenantId || t.id === tenantId) : migrationConfig.defaultDatabaseConfig || migrationConfig.database;
177
- if (!dbConfig) {
178
- throw new Error(`Database configuration not found${tenantId ? ` for tenant: ${tenantId}` : ''}`);
179
- }
180
- // Get entities - handle both function and array
181
- const entities = typeof migrationConfig.entities === 'function' ? migrationConfig.entities() : migrationConfig.entities || [];
182
- // Create DataSource
183
- const dataSource = new _typeorm.DataSource({
184
- type: dbConfig.type || 'mysql',
185
- host: dbConfig.host,
186
- port: dbConfig.port,
187
- username: dbConfig.username,
188
- password: dbConfig.password,
189
- database: dbConfig.database,
190
- entities,
191
- synchronize: false,
192
- logging: false
193
- });
194
- await dataSource.initialize();
195
- return dataSource;
196
- } catch (error) {
197
- console.error('āŒ Failed to load DataSource configuration');
198
- console.error(' Error:', error instanceof Error ? error.message : String(error));
199
- throw error;
149
+ const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
150
+ const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
151
+ const dbConfig = tenantId ? migrationConfig.tenants?.find((t)=>t.tenantId === tenantId || t.id === tenantId) : migrationConfig.defaultDatabaseConfig || migrationConfig.database;
152
+ if (!dbConfig) {
153
+ throw new Error(`Database configuration not found${tenantId ? ` for tenant: ${tenantId}` : ''}`);
200
154
  }
155
+ const entities = typeof migrationConfig.entities === 'function' ? migrationConfig.entities() : migrationConfig.entities || [];
156
+ const dataSource = new _typeorm.DataSource({
157
+ type: dbConfig.type || 'mysql',
158
+ host: dbConfig.host,
159
+ port: dbConfig.port,
160
+ username: dbConfig.username,
161
+ password: dbConfig.password,
162
+ database: dbConfig.database,
163
+ entities,
164
+ synchronize: false,
165
+ logging: false
166
+ });
167
+ await dataSource.initialize();
168
+ return dataSource;
201
169
  }
202
- /**
203
- * Get all tenant IDs from configuration
204
- */ async function getAllTenantIds(configPath) {
170
+ async function getAllTenantIds(configPath) {
205
171
  const resolvedPath = await resolveConfigPath(configPath);
206
- try {
207
- const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
208
- const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
209
- if (migrationConfig.bootstrapAppConfig?.databaseMode !== 'multi-tenant' || !migrationConfig.tenants) {
210
- throw new Error('Multi-tenant mode is not configured');
211
- }
212
- return migrationConfig.tenants.map((t)=>t.tenantId || t.id);
213
- } catch (error) {
214
- console.error('āŒ Failed to load tenant configuration');
215
- throw error;
172
+ const module1 = await Promise.resolve(resolvedPath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
173
+ const migrationConfig = module1.migrationConfig || module1.default?.migrationConfig || module1;
174
+ if (migrationConfig.bootstrapAppConfig?.databaseMode !== 'multi-tenant' || !migrationConfig.tenants) {
175
+ throw new Error('Multi-tenant mode is not configured');
216
176
  }
177
+ return migrationConfig.tenants.map((t)=>t.tenantId || t.id);
217
178
  }
218
- /**
219
- * Generate seeder template files
220
- */ async function generateCommand(configPath) {
221
- console.log('šŸ” Discovering entities...\n');
222
- const dataSource = await loadDataSource(undefined, configPath);
223
- try {
224
- const reader = new _entityreader.EntityReader(dataSource);
225
- const generator = new _templategenerator.TemplateGenerator();
226
- const entities = reader.getAllEntities();
227
- const outputDir = _path.resolve(process.cwd(), 'src/seeders/generators');
228
- console.log(`šŸ“ Generating seeder files in ${outputDir}\n`);
229
- let generatedCount = 0;
230
- const entityInfos = [];
231
- for (const metadata of entities){
232
- if ((0, _seedconfig.shouldSkipEntity)(metadata.name)) {
233
- continue;
234
- }
235
- try {
236
- const entityInfo = reader.getEntityInfo(metadata.name);
237
- entityInfos.push(entityInfo);
238
- const filePath = generator.generateSeederFile(entityInfo, outputDir);
239
- console.log(`āœ“ Generated: ${_path.basename(filePath)}`);
240
- generatedCount++;
241
- } catch (error) {
242
- console.error(`āœ— Failed to generate ${metadata.name}:`, error instanceof Error ? error.message : String(error));
243
- }
244
- }
245
- // Generate index file
246
- const indexPath = generator.generateIndexFile(entityInfos, outputDir);
247
- console.log(`āœ“ Generated: ${_path.basename(indexPath)}`);
248
- console.log(`\nāœ“ Generated ${generatedCount} seeder files\n`);
249
- } finally{
250
- await dataSource.destroy();
251
- }
252
- }
253
- /**
254
- * Run seeds for single database
255
- */ async function runCommand(options, configPath) {
179
+ async function runCommand(options, configPath) {
256
180
  const dataSource = await loadDataSource(undefined, configPath);
257
181
  try {
258
182
  const runner = new _seedrunner.SeedRunner(dataSource);
@@ -267,18 +191,13 @@ let resolvedConfigPath;
267
191
  }
268
192
  } else {
269
193
  const results = await runner.runAll(options);
270
- const failedCount = results.filter((r)=>!r.success).length;
271
- if (failedCount > 0) {
272
- process.exit(1);
273
- }
194
+ if (results.some((r)=>!r.success)) process.exit(1);
274
195
  }
275
196
  } finally{
276
197
  await dataSource.destroy();
277
198
  }
278
199
  }
279
- /**
280
- * Run seeds for all tenants
281
- */ async function runAllTenantsCommand(options, configPath) {
200
+ async function runAllTenantsCommand(options, configPath) {
282
201
  console.log('šŸ¢ Running seeds for all tenants...\n');
283
202
  const tenantIds = await getAllTenantIds(configPath);
284
203
  let successCount = 0;
@@ -290,12 +209,7 @@ let resolvedConfigPath;
290
209
  try {
291
210
  const runner = new _seedrunner.SeedRunner(dataSource);
292
211
  const results = await runner.runAll(options);
293
- const failed = results.filter((r)=>!r.success).length;
294
- if (failed === 0) {
295
- successCount++;
296
- } else {
297
- failCount++;
298
- }
212
+ results.some((r)=>!r.success) ? failCount++ : successCount++;
299
213
  } catch (error) {
300
214
  console.error(`āœ— Failed to seed tenant ${tenantId}:`, error);
301
215
  failCount++;
@@ -310,86 +224,65 @@ let resolvedConfigPath;
310
224
  process.exit(1);
311
225
  }
312
226
  }
313
- /**
314
- * Clear all seeded data
315
- */ async function clearCommand(hard = false, configPath) {
227
+ async function clearCommand(hard = false, configPath) {
316
228
  const dataSource = await loadDataSource(undefined, configPath);
317
229
  try {
318
- const runner = new _seedrunner.SeedRunner(dataSource);
319
- await runner.clearAll(hard);
230
+ await new _seedrunner.SeedRunner(dataSource).clearAll(hard);
320
231
  } finally{
321
232
  await dataSource.destroy();
322
233
  }
323
234
  }
324
- /**
325
- * Show seeding status
326
- */ async function statusCommand(configPath) {
235
+ async function statusCommand(configPath) {
327
236
  const dataSource = await loadDataSource(undefined, configPath);
328
237
  try {
329
- const runner = new _seedrunner.SeedRunner(dataSource);
330
- const status = await runner.getStatus();
238
+ const status = await new _seedrunner.SeedRunner(dataSource).getStatus();
331
239
  console.log('\nSeed Status:');
332
240
  console.log('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
333
241
  console.log('│ Entity │ Records │ Status │');
334
242
  console.log('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
335
243
  for (const item of status){
336
- const entityName = item.entity.padEnd(26);
337
- const count = item.count.toString().padEnd(9);
338
- const statusIcon = item.isEmpty ? '⚠ Empty' : 'āœ“ Ready ';
339
- console.log(`│ ${entityName} │ ${count} │ ${statusIcon} │`);
244
+ console.log(`│ ${item.entity.padEnd(26)} │ ${item.count.toString().padEnd(9)} │ ${item.isEmpty ? '⚠ Empty' : 'āœ“ Ready '} │`);
340
245
  }
341
246
  console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜\n');
342
247
  } finally{
343
248
  await dataSource.destroy();
344
249
  }
345
250
  }
346
- /**
347
- * Main CLI entry point
348
- */ async function main() {
251
+ async function main() {
349
252
  const args = parseArgs();
350
253
  if (!args.command) {
351
254
  showHelp();
352
255
  return;
353
256
  }
354
- // Initialize config path for all commands
355
257
  if (args.configPath) {
356
258
  await resolveConfigPath(args.configPath);
357
259
  }
358
- try {
359
- switch(args.command){
360
- case 'generate':
361
- await generateCommand(args.configPath);
362
- break;
363
- case 'run':
364
- await runCommand({
365
- count: args.count,
366
- clear: args.clear,
367
- entity: args.entity
368
- }, args.configPath);
369
- break;
370
- case 'run:all':
371
- await runAllTenantsCommand({
372
- count: args.count,
373
- clear: args.clear
374
- }, args.configPath);
375
- break;
376
- case 'clear':
377
- await clearCommand(args.hard, args.configPath);
378
- break;
379
- case 'status':
380
- await statusCommand(args.configPath);
381
- break;
382
- default:
383
- console.error(`āŒ Unknown command: ${args.command}`);
384
- showHelp();
385
- process.exit(1);
386
- }
387
- } catch (error) {
388
- console.error('\nāŒ CLI Error:', error instanceof Error ? error.message : String(error));
389
- process.exit(1);
260
+ switch(args.command){
261
+ case 'run':
262
+ await runCommand({
263
+ count: args.count,
264
+ clear: args.clear,
265
+ entity: args.entity
266
+ }, args.configPath);
267
+ break;
268
+ case 'run:all':
269
+ await runAllTenantsCommand({
270
+ count: args.count,
271
+ clear: args.clear
272
+ }, args.configPath);
273
+ break;
274
+ case 'clear':
275
+ await clearCommand(args.hard, args.configPath);
276
+ break;
277
+ case 'status':
278
+ await statusCommand(args.configPath);
279
+ break;
280
+ default:
281
+ console.error(`āŒ Unknown command: ${args.command}`);
282
+ showHelp();
283
+ process.exit(1);
390
284
  }
391
285
  }
392
- // Run CLI if called directly
393
286
  if (require.main === module) {
394
287
  main().catch((error)=>{
395
288
  console.error('Fatal error:', error);