@flusys/nestjs-core 1.1.0-beta → 1.2.0-rc.1

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 (61) hide show
  1. package/README.md +136 -162
  2. package/cjs/config/env-config.service.js +14 -10
  3. package/cjs/docs/docs.config.js +99 -15
  4. package/cjs/docs/index.js +0 -1
  5. package/cjs/index.js +0 -1
  6. package/cjs/interfaces/base-entity.interface.js +5 -3
  7. package/cjs/interfaces/database.interface.js +1 -3
  8. package/cjs/migration/datasource.factory.js +1 -3
  9. package/cjs/migration/index.js +0 -12
  10. package/cjs/migration/migration.cli.js +1 -17
  11. package/cjs/migration/migration.runner.js +37 -65
  12. package/cjs/utils/datasource-config.builder.js +2 -14
  13. package/config/env-config.service.d.ts +3 -1
  14. package/docs/docs.config.d.ts +8 -0
  15. package/docs/index.d.ts +0 -1
  16. package/fesm/config/env-config.service.js +14 -10
  17. package/fesm/docs/docs.config.js +89 -15
  18. package/fesm/docs/index.js +0 -1
  19. package/fesm/index.js +0 -2
  20. package/fesm/interfaces/app-config.interfaces.js +1 -3
  21. package/fesm/interfaces/base-entity.interface.js +5 -5
  22. package/fesm/interfaces/database.interface.js +1 -5
  23. package/fesm/migration/cli.js +1 -20
  24. package/fesm/migration/datasource.factory.js +3 -20
  25. package/fesm/migration/index.js +0 -14
  26. package/fesm/migration/migration.cli.js +1 -17
  27. package/fesm/migration/migration.runner.js +43 -132
  28. package/fesm/utils/datasource-config.builder.js +2 -13
  29. package/index.d.ts +0 -1
  30. package/interfaces/app-config.interfaces.d.ts +1 -0
  31. package/interfaces/base-entity.interface.d.ts +2 -2
  32. package/interfaces/database.interface.d.ts +2 -1
  33. package/package.json +9 -9
  34. package/utils/datasource-config.builder.d.ts +0 -1
  35. package/cjs/docs/docs.setup.js +0 -14
  36. package/cjs/seeders/base-seeder.js +0 -95
  37. package/cjs/seeders/cli.js +0 -398
  38. package/cjs/seeders/data-generator.js +0 -247
  39. package/cjs/seeders/entity-reader.js +0 -168
  40. package/cjs/seeders/index.js +0 -77
  41. package/cjs/seeders/seed-config.js +0 -101
  42. package/cjs/seeders/seed-runner.js +0 -320
  43. package/cjs/seeders/template-generator.js +0 -297
  44. package/docs/docs.setup.d.ts +0 -3
  45. package/fesm/docs/docs.setup.js +0 -4
  46. package/fesm/seeders/base-seeder.js +0 -110
  47. package/fesm/seeders/cli.js +0 -366
  48. package/fesm/seeders/data-generator.js +0 -249
  49. package/fesm/seeders/entity-reader.js +0 -170
  50. package/fesm/seeders/index.js +0 -11
  51. package/fesm/seeders/seed-config.js +0 -85
  52. package/fesm/seeders/seed-runner.js +0 -323
  53. package/fesm/seeders/template-generator.js +0 -257
  54. package/seeders/base-seeder.d.ts +0 -14
  55. package/seeders/cli.d.ts +0 -3
  56. package/seeders/data-generator.d.ts +0 -15
  57. package/seeders/entity-reader.d.ts +0 -45
  58. package/seeders/index.d.ts +0 -7
  59. package/seeders/seed-config.d.ts +0 -11
  60. package/seeders/seed-runner.d.ts +0 -47
  61. package/seeders/template-generator.d.ts +0 -16
@@ -1,398 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "runSeedCli", {
7
- enumerable: true,
8
- get: function() {
9
- return main;
10
- }
11
- });
12
- const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
13
- const _typeorm = require("typeorm");
14
- const _config = require("../config");
15
- const _entityreader = require("./entity-reader");
16
- const _templategenerator = require("./template-generator");
17
- const _seedrunner = require("./seed-runner");
18
- const _seedconfig = require("./seed-config");
19
- function _getRequireWildcardCache(nodeInterop) {
20
- if (typeof WeakMap !== "function") return null;
21
- var cacheBabelInterop = new WeakMap();
22
- var cacheNodeInterop = new WeakMap();
23
- return (_getRequireWildcardCache = function(nodeInterop) {
24
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
25
- })(nodeInterop);
26
- }
27
- function _interop_require_wildcard(obj, nodeInterop) {
28
- if (!nodeInterop && obj && obj.__esModule) {
29
- return obj;
30
- }
31
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
32
- return {
33
- default: obj
34
- };
35
- }
36
- var cache = _getRequireWildcardCache(nodeInterop);
37
- if (cache && cache.has(obj)) {
38
- return cache.get(obj);
39
- }
40
- var newObj = {
41
- __proto__: null
42
- };
43
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
44
- for(var key in obj){
45
- if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
46
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
47
- if (desc && (desc.get || desc.set)) {
48
- Object.defineProperty(newObj, key, desc);
49
- } else {
50
- newObj[key] = obj[key];
51
- }
52
- }
53
- }
54
- newObj.default = obj;
55
- if (cache) {
56
- cache.set(obj, newObj);
57
- }
58
- return newObj;
59
- }
60
- /**
61
- * Show help message
62
- */ function showHelp() {
63
- console.log(`
64
- Seed Data CLI
65
-
66
- Usage:
67
- npm run seed:<command> [options]
68
-
69
- Commands:
70
- generate Generate seeder template files
71
- run Execute seeders for all entities
72
- run:all Execute seeders for all tenants (multi-tenant mode)
73
- clear Clear all seeded data
74
- status Show seeding status
75
-
76
- Options:
77
- --config=<path> Migration config file (default: src/persistence/migration.config.ts)
78
- --count=<number> Number of records per entity (default: from seed-config)
79
- --clear Clear existing data before seeding
80
- --entity=<name> Seed only specific entity
81
- --hard Hard delete when clearing (ignore soft delete)
82
- --tenant=<id> Target specific tenant (multi-tenant mode)
83
-
84
- Environment:
85
- MIGRATION_CONFIG Default config path (overrides auto-detection)
86
-
87
- Examples:
88
- npm run seed:generate
89
- npm run seed:run
90
- npm run seed:run -- --count=50 --clear
91
- npm run seed:run -- --entity=User --count=100
92
- npm run seed:run -- --config=src/persistence/migration.config.ts
93
- npm run seed:clear
94
- npm run seed:clear -- --hard
95
- npm run seed:status
96
- npm run seed:run:all
97
- `);
98
- }
99
- /**
100
- * Parse command-line arguments
101
- */ function parseArgs() {
102
- const args = process.argv.slice(2);
103
- let command;
104
- let count;
105
- let clear = false;
106
- let entity;
107
- let hard = false;
108
- let tenant;
109
- let configPath;
110
- for(let i = 0; i < args.length; i++){
111
- const arg = args[i];
112
- if (arg.startsWith('--count=')) {
113
- count = parseInt(arg.split('=')[1], 10);
114
- } else if (arg === '--clear') {
115
- clear = true;
116
- } else if (arg.startsWith('--entity=')) {
117
- entity = arg.split('=')[1];
118
- } else if (arg === '--hard') {
119
- hard = true;
120
- } else if (arg.startsWith('--tenant=')) {
121
- tenant = arg.split('=')[1];
122
- } else if (arg.startsWith('--config=')) {
123
- configPath = arg.split('=')[1];
124
- } else if (!arg.startsWith('-') && !command) {
125
- command = arg;
126
- }
127
- }
128
- return {
129
- command,
130
- count,
131
- clear,
132
- entity,
133
- hard,
134
- tenant,
135
- configPath
136
- };
137
- }
138
- // Resolved config path (set once during CLI initialization)
139
- let resolvedConfigPath;
140
- /**
141
- * Resolve migration config path with auto-detection
142
- */ async function resolveConfigPath(explicitPath) {
143
- if (resolvedConfigPath) return resolvedConfigPath;
144
- // Try paths in order: explicit, env var, then common defaults
145
- const envConfigPath = _config.envConfig.tryGetValue('MIGRATION_CONFIG');
146
- const defaultPaths = [
147
- explicitPath,
148
- envConfigPath,
149
- 'src/persistence/migration.config.ts',
150
- 'src/persistence/migration.config.js',
151
- 'persistence/migration.config.ts',
152
- 'persistence/migration.config.js'
153
- ].filter(Boolean);
154
- for (const tryPath of defaultPaths){
155
- const absolutePath = _path.isAbsolute(tryPath) ? tryPath : _path.resolve(process.cwd(), tryPath);
156
- try {
157
- await Promise.resolve(absolutePath).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
158
- resolvedConfigPath = absolutePath;
159
- return absolutePath;
160
- } catch {
161
- // Try next path
162
- }
163
- }
164
- console.error('❌ Config not found. Use --config=<path> or set MIGRATION_CONFIG env var');
165
- console.error(' Tried paths:', defaultPaths.join(', '));
166
- process.exit(1);
167
- }
168
- /**
169
- * Load DataSource configuration
170
- */ async function loadDataSource(tenantId, configPath) {
171
- 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;
200
- }
201
- }
202
- /**
203
- * Get all tenant IDs from configuration
204
- */ async function getAllTenantIds(configPath) {
205
- 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;
216
- }
217
- }
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) {
256
- const dataSource = await loadDataSource(undefined, configPath);
257
- try {
258
- const runner = new _seedrunner.SeedRunner(dataSource);
259
- if (options.entity) {
260
- console.log(`🌱 Seeding entity: ${options.entity}\n`);
261
- const result = await runner.runSingle(options.entity, options);
262
- if (result.success) {
263
- console.log(`\n✓ ${result.entity}: ${result.count} records created\n`);
264
- } else {
265
- console.error(`\n✗ ${result.entity}: ${result.error}\n`);
266
- process.exit(1);
267
- }
268
- } else {
269
- const results = await runner.runAll(options);
270
- const failedCount = results.filter((r)=>!r.success).length;
271
- if (failedCount > 0) {
272
- process.exit(1);
273
- }
274
- }
275
- } finally{
276
- await dataSource.destroy();
277
- }
278
- }
279
- /**
280
- * Run seeds for all tenants
281
- */ async function runAllTenantsCommand(options, configPath) {
282
- console.log('🏢 Running seeds for all tenants...\n');
283
- const tenantIds = await getAllTenantIds(configPath);
284
- let successCount = 0;
285
- let failCount = 0;
286
- for (const tenantId of tenantIds){
287
- console.log(`\n📦 Tenant: ${tenantId}`);
288
- console.log('─'.repeat(50));
289
- const dataSource = await loadDataSource(tenantId, configPath);
290
- try {
291
- const runner = new _seedrunner.SeedRunner(dataSource);
292
- 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
- }
299
- } catch (error) {
300
- console.error(`✗ Failed to seed tenant ${tenantId}:`, error);
301
- failCount++;
302
- } finally{
303
- await dataSource.destroy();
304
- }
305
- }
306
- console.log('\n' + '='.repeat(50));
307
- console.log(`\n✓ Completed: ${successCount} tenants seeded`);
308
- if (failCount > 0) {
309
- console.log(`✗ Failed: ${failCount} tenants\n`);
310
- process.exit(1);
311
- }
312
- }
313
- /**
314
- * Clear all seeded data
315
- */ async function clearCommand(hard = false, configPath) {
316
- const dataSource = await loadDataSource(undefined, configPath);
317
- try {
318
- const runner = new _seedrunner.SeedRunner(dataSource);
319
- await runner.clearAll(hard);
320
- } finally{
321
- await dataSource.destroy();
322
- }
323
- }
324
- /**
325
- * Show seeding status
326
- */ async function statusCommand(configPath) {
327
- const dataSource = await loadDataSource(undefined, configPath);
328
- try {
329
- const runner = new _seedrunner.SeedRunner(dataSource);
330
- const status = await runner.getStatus();
331
- console.log('\nSeed Status:');
332
- console.log('┌────────────────────────────┬───────────┬─────────┐');
333
- console.log('│ Entity │ Records │ Status │');
334
- console.log('├────────────────────────────┼───────────┼─────────┤');
335
- 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} │`);
340
- }
341
- console.log('└────────────────────────────┴───────────┴─────────┘\n');
342
- } finally{
343
- await dataSource.destroy();
344
- }
345
- }
346
- /**
347
- * Main CLI entry point
348
- */ async function main() {
349
- const args = parseArgs();
350
- if (!args.command) {
351
- showHelp();
352
- return;
353
- }
354
- // Initialize config path for all commands
355
- if (args.configPath) {
356
- await resolveConfigPath(args.configPath);
357
- }
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);
390
- }
391
- }
392
- // Run CLI if called directly
393
- if (require.main === module) {
394
- main().catch((error)=>{
395
- console.error('Fatal error:', error);
396
- process.exit(1);
397
- });
398
- }
@@ -1,247 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "DataGenerator", {
6
- enumerable: true,
7
- get: function() {
8
- return DataGenerator;
9
- }
10
- });
11
- const _faker = require("@faker-js/faker");
12
- let DataGenerator = class DataGenerator {
13
- /**
14
- * Generate value for a single column based on its metadata
15
- */ generateValue(column) {
16
- // Skip generated fields
17
- if (column.isGenerated) {
18
- return undefined;
19
- }
20
- // Handle nullable fields (50% chance of null)
21
- if (column.isNullable && _faker.faker.datatype.boolean()) {
22
- return null;
23
- }
24
- // Check for enum
25
- if (column.enum && column.enum.length > 0) {
26
- return _faker.faker.helpers.arrayElement(column.enum);
27
- }
28
- // Generate based on column name pattern
29
- const nameLower = column.propertyName.toLowerCase();
30
- const value = this.generateByName(nameLower, column);
31
- if (value !== undefined) {
32
- return value;
33
- }
34
- // Generate based on column type
35
- return this.generateByType(column);
36
- }
37
- /**
38
- * Generate entity object from column definitions
39
- */ generateEntity(columns) {
40
- const entity = {};
41
- for (const column of columns){
42
- const value = this.generateValue(column);
43
- if (value !== undefined) {
44
- entity[column.propertyName] = value;
45
- }
46
- }
47
- return entity;
48
- }
49
- /**
50
- * Generate value based on column name patterns
51
- */ generateByName(nameLower, column) {
52
- // Identity fields (skip, handled by database)
53
- if ([
54
- 'id',
55
- 'createdat',
56
- 'updatedat',
57
- 'deletedat'
58
- ].includes(nameLower)) {
59
- return undefined;
60
- }
61
- // Audit fields (skip, handled by interceptors)
62
- if ([
63
- 'createdbyid',
64
- 'updatedbyid',
65
- 'deletedbyid'
66
- ].includes(nameLower)) {
67
- return null;
68
- }
69
- // Name fields
70
- if (nameLower.includes('firstname')) return _faker.faker.person.firstName();
71
- if (nameLower.includes('lastname')) return _faker.faker.person.lastName();
72
- if (nameLower.includes('fullname') || nameLower === 'name') {
73
- return _faker.faker.person.fullName();
74
- }
75
- // Contact fields
76
- if (nameLower.includes('email')) return _faker.faker.internet.email().toLowerCase();
77
- if (nameLower.includes('phone')) return _faker.faker.phone.number();
78
- if (nameLower.includes('mobile')) return _faker.faker.phone.number();
79
- // Location fields
80
- if (nameLower.includes('address')) return _faker.faker.location.streetAddress();
81
- if (nameLower.includes('street')) return _faker.faker.location.street();
82
- if (nameLower.includes('city')) return _faker.faker.location.city();
83
- if (nameLower.includes('state')) return _faker.faker.location.state();
84
- if (nameLower.includes('country')) return _faker.faker.location.country();
85
- if (nameLower.includes('zipcode') || nameLower.includes('postalcode')) {
86
- return _faker.faker.location.zipCode();
87
- }
88
- // URL/Web fields
89
- if (nameLower.includes('url')) return _faker.faker.internet.url();
90
- if (nameLower.includes('website')) return _faker.faker.internet.url();
91
- if (nameLower.includes('domain')) return _faker.faker.internet.domainName();
92
- if (nameLower.includes('slug')) {
93
- return _faker.faker.helpers.slugify(_faker.faker.lorem.words(3)).toLowerCase();
94
- }
95
- // Text fields
96
- if (nameLower.includes('description')) return _faker.faker.lorem.paragraph();
97
- if (nameLower.includes('summary')) return _faker.faker.lorem.sentence();
98
- if (nameLower.includes('content')) return _faker.faker.lorem.paragraphs(3);
99
- if (nameLower.includes('title')) return _faker.faker.lorem.sentence();
100
- // User fields
101
- if (nameLower.includes('username')) return _faker.faker.internet.username();
102
- if (nameLower.includes('password')) return '$2b$12$dummy.hashed.password.value'; // Dummy bcrypt hash
103
- // Status/Active fields
104
- if (nameLower.includes('isactive')) return _faker.faker.datatype.boolean();
105
- if (nameLower.includes('isenabled')) return _faker.faker.datatype.boolean();
106
- if (nameLower.includes('ispublic')) return _faker.faker.datatype.boolean();
107
- if (nameLower.includes('isverified')) return _faker.faker.datatype.boolean();
108
- // Date fields
109
- if (nameLower.includes('birthdate') || nameLower.includes('dateofbirth')) {
110
- return _faker.faker.date.birthdate({
111
- min: 18,
112
- max: 80,
113
- mode: 'age'
114
- });
115
- }
116
- if (nameLower.includes('expiresat') || nameLower.includes('expirydate')) {
117
- return _faker.faker.date.future();
118
- }
119
- if (nameLower.includes('verifiedat')) {
120
- return _faker.faker.datatype.boolean() ? _faker.faker.date.recent() : null;
121
- }
122
- // Serial/Order fields
123
- if (nameLower.includes('serial') || nameLower.includes('order')) {
124
- return _faker.faker.number.int({
125
- min: 1,
126
- max: 100
127
- });
128
- }
129
- // Company/Organization
130
- if (nameLower.includes('company') && !nameLower.includes('id')) {
131
- return _faker.faker.company.name();
132
- }
133
- return undefined;
134
- }
135
- /**
136
- * Generate value based on column type
137
- */ generateByType(column) {
138
- const type = column.type.toLowerCase();
139
- switch(type){
140
- // String types
141
- case 'varchar':
142
- case 'character varying':
143
- case 'text':
144
- case 'string':
145
- return this.generateString(column);
146
- // Number types
147
- case 'int':
148
- case 'integer':
149
- case 'smallint':
150
- case 'bigint':
151
- return _faker.faker.number.int({
152
- min: 1,
153
- max: 1000
154
- });
155
- case 'decimal':
156
- case 'numeric':
157
- case 'float':
158
- case 'double':
159
- case 'real':
160
- return _faker.faker.number.float({
161
- min: 0,
162
- max: 10000,
163
- fractionDigits: column.scale || 2
164
- });
165
- // Boolean
166
- case 'boolean':
167
- case 'bool':
168
- return _faker.faker.datatype.boolean();
169
- // Date/Time
170
- case 'date':
171
- return _faker.faker.date.recent({
172
- days: 30
173
- });
174
- case 'timestamp':
175
- case 'datetime':
176
- return _faker.faker.date.recent({
177
- days: 30
178
- });
179
- case 'time':
180
- return _faker.faker.date.recent().toTimeString().split(' ')[0];
181
- // UUID
182
- case 'uuid':
183
- return _faker.faker.string.uuid();
184
- // JSON
185
- case 'json':
186
- case 'jsonb':
187
- return {
188
- key1: _faker.faker.lorem.word(),
189
- key2: _faker.faker.number.int({
190
- min: 1,
191
- max: 100
192
- })
193
- };
194
- // Array
195
- case 'array':
196
- return [
197
- _faker.faker.lorem.word(),
198
- _faker.faker.lorem.word()
199
- ];
200
- // Default
201
- default:
202
- return _faker.faker.lorem.word();
203
- }
204
- }
205
- /**
206
- * Generate string value respecting length constraints
207
- */ generateString(column) {
208
- const maxLength = typeof column.length === 'number' ? column.length : 255;
209
- if (maxLength <= 50) {
210
- return _faker.faker.lorem.word().substring(0, maxLength);
211
- } else if (maxLength <= 255) {
212
- return _faker.faker.lorem.sentence().substring(0, maxLength);
213
- } else {
214
- return _faker.faker.lorem.paragraph().substring(0, maxLength);
215
- }
216
- }
217
- /**
218
- * Generate related entity ID (for foreign keys)
219
- * @param relatedEntities Array of entities to pick from
220
- */ generateRelationId(relatedEntities) {
221
- if (relatedEntities.length === 0) {
222
- return null;
223
- }
224
- return _faker.faker.helpers.arrayElement(relatedEntities).id;
225
- }
226
- /**
227
- * Generate multiple related entity IDs (for many-to-many)
228
- * @param relatedEntities Array of entities to pick from
229
- * @param min Minimum number of relations
230
- * @param max Maximum number of relations
231
- */ generateRelationIds(relatedEntities, min = 1, max = 3) {
232
- if (relatedEntities.length === 0) {
233
- return [];
234
- }
235
- const count = _faker.faker.number.int({
236
- min,
237
- max: Math.min(max, relatedEntities.length)
238
- });
239
- const selected = _faker.faker.helpers.arrayElements(relatedEntities, count);
240
- return selected.map((e)=>e.id);
241
- }
242
- constructor(locale = 'en'){
243
- // Note: faker v8+ uses faker.locale instead of setLocale
244
- // For v8+: faker.locale = locale;
245
- // Locale is set globally, not needed for basic usage
246
- }
247
- };