@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,170 +0,0 @@
1
- function _define_property(obj, key, value) {
2
- if (key in obj) {
3
- Object.defineProperty(obj, key, {
4
- value: value,
5
- enumerable: true,
6
- configurable: true,
7
- writable: true
8
- });
9
- } else {
10
- obj[key] = value;
11
- }
12
- return obj;
13
- }
14
- /**
15
- * Entity Reader Service
16
- *
17
- * Extracts metadata from TypeORM entities for seed data generation.
18
- * Discovers columns, types, constraints, and relationships.
19
- *
20
- * Usage:
21
- * ```typescript
22
- * const reader = new EntityReader(dataSource);
23
- * const entities = reader.getAllEntities();
24
- * const userInfo = reader.getEntityInfo('User');
25
- * ```
26
- */ export class EntityReader {
27
- /**
28
- * Get all entity metadata from DataSource
29
- */ getAllEntities() {
30
- return this.dataSource.entityMetadatas;
31
- }
32
- /**
33
- * Get detailed entity information
34
- * @param entityName Entity class name or table name
35
- */ getEntityInfo(entityName) {
36
- const metadata = this.findEntityMetadata(entityName);
37
- if (!metadata) {
38
- throw new Error(`Entity ${entityName} not found in DataSource`);
39
- }
40
- return {
41
- name: metadata.name,
42
- tableName: metadata.tableName,
43
- columns: this.extractColumns(metadata),
44
- relations: this.extractRelations(metadata),
45
- hasSoftDelete: metadata.deleteDateColumn !== undefined,
46
- hasCompany: this.hasCompanyColumn(metadata)
47
- };
48
- }
49
- /**
50
- * Get seeding order based on foreign key dependencies
51
- * Returns entity names sorted by dependency (independent entities first)
52
- */ getSeedingOrder(skipEntities = []) {
53
- const entities = this.getAllEntities().filter((e)=>!skipEntities.includes(e.name) && !skipEntities.includes(e.tableName));
54
- const graph = this.buildDependencyGraph(entities);
55
- return this.topologicalSort(graph);
56
- }
57
- /**
58
- * Check if entity has required columns populated
59
- * Used to determine if entity is ready for seeding
60
- */ hasRequiredDependencies(entityName, dataSource) {
61
- const info = this.getEntityInfo(entityName);
62
- for (const relation of info.relations){
63
- if (!relation.isNullable && relation.type === 'many-to-one') {
64
- const targetRepo = dataSource.getRepository(relation.targetEntity);
65
- if (targetRepo) {
66
- // Check if target entity has data
67
- // Note: This is a simplified check, actual implementation may need async
68
- return true;
69
- }
70
- }
71
- }
72
- return true;
73
- }
74
- /**
75
- * Find entity metadata by name or table name
76
- */ findEntityMetadata(entityName) {
77
- return this.getAllEntities().find((e)=>e.name === entityName || e.tableName === entityName);
78
- }
79
- /**
80
- * Extract column information from entity metadata
81
- */ extractColumns(metadata) {
82
- return metadata.columns.map((col)=>({
83
- name: col.databaseName,
84
- propertyName: col.propertyName,
85
- type: this.getColumnTypeString(col.type),
86
- length: col.length,
87
- isNullable: col.isNullable,
88
- isUnique: col.isUnique === true || false,
89
- isPrimary: col.isPrimary,
90
- isGenerated: col.isGenerated,
91
- default: col.default,
92
- enum: col.enum ? Object.values(col.enum) : undefined,
93
- precision: col.precision ?? undefined,
94
- scale: col.scale ?? undefined
95
- }));
96
- }
97
- /**
98
- * Extract relation information from entity metadata
99
- */ extractRelations(metadata) {
100
- return metadata.relations.map((rel)=>({
101
- propertyName: rel.propertyName,
102
- type: rel.relationType,
103
- targetEntity: rel.inverseEntityMetadata.name,
104
- isNullable: rel.isNullable,
105
- joinColumnName: rel.joinColumns?.[0]?.databaseName
106
- }));
107
- }
108
- /**
109
- * Check if entity has company-related columns
110
- */ hasCompanyColumn(metadata) {
111
- return metadata.columns.some((col)=>col.propertyName === 'companyId' || col.databaseName === 'company_id');
112
- }
113
- /**
114
- * Convert TypeORM column type to string
115
- */ getColumnTypeString(type) {
116
- if (typeof type === 'string') {
117
- return type;
118
- }
119
- if (typeof type === 'function') {
120
- return type.name.toLowerCase();
121
- }
122
- return 'unknown';
123
- }
124
- /**
125
- * Build dependency graph for entities
126
- */ buildDependencyGraph(entities) {
127
- const graph = new Map();
128
- for (const entity of entities){
129
- const dependencies = [];
130
- for (const relation of entity.relations){
131
- if (relation.relationType === 'many-to-one' && !relation.isNullable) {
132
- dependencies.push(relation.inverseEntityMetadata.name);
133
- }
134
- }
135
- graph.set(entity.name, dependencies);
136
- }
137
- return graph;
138
- }
139
- /**
140
- * Topological sort for dependency resolution
141
- */ topologicalSort(graph) {
142
- const sorted = [];
143
- const visited = new Set();
144
- const visiting = new Set();
145
- const visit = (node)=>{
146
- if (visited.has(node)) return;
147
- if (visiting.has(node)) {
148
- throw new Error(`Circular dependency detected involving ${node}`);
149
- }
150
- visiting.add(node);
151
- const dependencies = graph.get(node) || [];
152
- for (const dep of dependencies){
153
- if (graph.has(dep)) {
154
- visit(dep);
155
- }
156
- }
157
- visiting.delete(node);
158
- visited.add(node);
159
- sorted.push(node);
160
- };
161
- for (const node of graph.keys()){
162
- visit(node);
163
- }
164
- return sorted;
165
- }
166
- constructor(dataSource){
167
- _define_property(this, "dataSource", void 0);
168
- this.dataSource = dataSource;
169
- }
170
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Seed System Exports
3
- *
4
- * Public API for seed data generation system.
5
- */ export { BaseSeeder } from './base-seeder';
6
- export { EntityReader, IEntityInfo, IColumnInfo, IRelationInfo } from './entity-reader';
7
- export { DataGenerator } from './data-generator';
8
- export { TemplateGenerator } from './template-generator';
9
- export { SeedRunner, ISeedResult, ISeedOptions, ISeederLogger, defaultLogger } from './seed-runner';
10
- export { seedConfig, ISeedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder } from './seed-config';
11
- export { runSeedCli } from './cli';
@@ -1,85 +0,0 @@
1
- /**
2
- * Seed Configuration
3
- *
4
- * Configuration for seed data generation.
5
- * Customize record counts, seeding order, and behavior.
6
- */ /**
7
- * Default seed configuration
8
- */ export const seedConfig = {
9
- // Default record counts per entity
10
- counts: {
11
- // Auth entities
12
- Company: 10,
13
- CompanyBranch: 25,
14
- User: 50,
15
- // IAM entities
16
- Role: 8,
17
- Permission: 45,
18
- Action: 30,
19
- Menu: 20,
20
- UserIAMPermission: 50,
21
- UserCompanyPermission: 100,
22
- // Storage entities
23
- StorageConfig: 5,
24
- Folder: 20,
25
- FileManager: 100
26
- },
27
- // Entity seeding order (respects FK constraints)
28
- // Parent entities must come before child entities
29
- order: [
30
- // Auth - foundational
31
- 'Company',
32
- 'CompanyBranch',
33
- 'User',
34
- // IAM - permissions system
35
- 'Action',
36
- 'Role',
37
- 'Permission',
38
- 'Menu',
39
- 'UserIAMPermission',
40
- 'UserCompanyPermission',
41
- // Storage - file system
42
- 'StorageConfig',
43
- 'Folder',
44
- 'FileManager'
45
- ],
46
- // Skip these entities (system tables, migrations)
47
- skipEntities: [
48
- 'migrations',
49
- 'typeorm_metadata',
50
- 'Migration',
51
- 'Typeorm_Metadata'
52
- ],
53
- // Faker locale (en, ar, es, fr, de, etc.)
54
- locale: 'en',
55
- // Respect soft delete when clearing data
56
- respectSoftDelete: true
57
- };
58
- /**
59
- * Get count for entity (with default fallback)
60
- */ export function getEntityCount(entityName, config = seedConfig) {
61
- return config.counts[entityName] || 10;
62
- }
63
- /**
64
- * Check if entity should be skipped
65
- */ export function shouldSkipEntity(entityName, config = seedConfig) {
66
- return config.skipEntities.some((skip)=>skip.toLowerCase() === entityName.toLowerCase());
67
- }
68
- /**
69
- * Get seeding order for entities
70
- */ export function getSeedingOrder(availableEntities, config = seedConfig) {
71
- const ordered = [];
72
- // Add entities in configured order
73
- for (const entityName of config.order){
74
- if (availableEntities.includes(entityName) && !shouldSkipEntity(entityName, config)) {
75
- ordered.push(entityName);
76
- }
77
- }
78
- // Add remaining entities not in order configuration
79
- for (const entityName of availableEntities){
80
- if (!ordered.includes(entityName) && !shouldSkipEntity(entityName, config)) {
81
- ordered.push(entityName);
82
- }
83
- }
84
- return ordered;
85
- }
@@ -1,323 +0,0 @@
1
- function _define_property(obj, key, value) {
2
- if (key in obj) {
3
- Object.defineProperty(obj, key, {
4
- value: value,
5
- enumerable: true,
6
- configurable: true,
7
- writable: true
8
- });
9
- } else {
10
- obj[key] = value;
11
- }
12
- return obj;
13
- }
14
- import { EntityReader } from './entity-reader';
15
- import { DataGenerator } from './data-generator';
16
- import { BaseSeeder } from './base-seeder';
17
- import { seedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder } from './seed-config';
18
- /**
19
- * Default console logger implementation
20
- */ export const defaultLogger = {
21
- log: (message)=>console.log(message),
22
- error: (message)=>console.error(message)
23
- };
24
- /**
25
- * Seed Runner Service
26
- *
27
- * Orchestrates seed data generation across all entities.
28
- * Handles dependency order, transactions, and error reporting.
29
- *
30
- * Usage:
31
- * ```typescript
32
- * const runner = new SeedRunner(dataSource);
33
- * await runner.runAll();
34
- * await runner.runSingle('User', { count: 50 });
35
- * await runner.clearAll();
36
- *
37
- * // With custom logger
38
- * const runner = new SeedRunner(dataSource, customLogger);
39
- *
40
- * // With custom seeder
41
- * runner.registerCustomSeeder('User', new UserSeeder(dataSource));
42
- * ```
43
- */ export class SeedRunner {
44
- /**
45
- * Register a custom seeder for specific entity
46
- * Custom seeders take precedence over generic seeders
47
- * @param entityName Entity name
48
- * @param seeder Custom seeder instance
49
- */ registerCustomSeeder(entityName, seeder) {
50
- this.customSeeders.set(entityName, seeder);
51
- }
52
- /**
53
- * Unregister a custom seeder
54
- * @param entityName Entity name
55
- */ unregisterCustomSeeder(entityName) {
56
- this.customSeeders.delete(entityName);
57
- }
58
- /**
59
- * Check if entity has custom seeder registered
60
- * @param entityName Entity name
61
- */ hasCustomSeeder(entityName) {
62
- return this.customSeeders.has(entityName);
63
- }
64
- /**
65
- * Run seeds for all entities
66
- * @param options Seeding options
67
- * @returns Array of seed results
68
- */ async runAll(options = {}) {
69
- const results = [];
70
- const continueOnError = options.continueOnError ?? true;
71
- // Get all entities
72
- const allEntities = this.entityReader.getAllEntities();
73
- const entityNames = allEntities.map((e)=>e.name).filter((name)=>!shouldSkipEntity(name));
74
- // Get seeding order
75
- const orderedNames = getSeedingOrder(entityNames);
76
- const mode = options.dryRun ? 'Previewing' : 'Seeding';
77
- this.logger.log(`\n🌱 ${mode} ${orderedNames.length} entities...\n`);
78
- for(let i = 0; i < orderedNames.length; i++){
79
- const entityName = orderedNames[i];
80
- // Call progress callback
81
- options.onProgress?.(i + 1, orderedNames.length, entityName);
82
- const result = await this.runSingle(entityName, options);
83
- results.push(result);
84
- // Log result
85
- if (result.success) {
86
- if (result.dryRun) {
87
- this.logger.log(`āœ“ ${entityName}: ${result.count} records (dry run)`);
88
- } else if (result.skipped) {
89
- this.logger.log(`⊘ ${entityName}: skipped (already has data)`);
90
- } else {
91
- this.logger.log(`āœ“ ${entityName}: ${result.count} records`);
92
- }
93
- } else {
94
- this.logger.error(`āœ— ${entityName}: ${result.error}`);
95
- // Fail-fast if continueOnError is false
96
- if (!continueOnError) {
97
- this.logger.error(`\nāŒ Seeding failed at ${entityName}, stopping...\n`);
98
- break;
99
- }
100
- }
101
- }
102
- const successCount = results.filter((r)=>r.success).length;
103
- const failedCount = results.length - successCount;
104
- if (failedCount > 0) {
105
- this.logger.log(`\nāš ļø Completed with errors: ${successCount}/${results.length} entities seeded (${failedCount} failed)\n`);
106
- } else {
107
- this.logger.log(`\nāœ“ Completed: ${successCount}/${results.length} entities seeded\n`);
108
- }
109
- return results;
110
- }
111
- /**
112
- * Run seed for a single entity
113
- * @param entityName Entity name to seed
114
- * @param options Seeding options
115
- * @returns Seed result
116
- */ async runSingle(entityName, options = {}) {
117
- const queryRunner = this.dataSource.createQueryRunner();
118
- await queryRunner.connect();
119
- await queryRunner.startTransaction();
120
- try {
121
- // Get entity info
122
- const entityInfo = this.entityReader.getEntityInfo(entityName);
123
- // Find entity target
124
- const entity = this.dataSource.entityMetadatas.find((e)=>e.name === entityName)?.target;
125
- if (!entity) {
126
- throw new Error(`Entity ${entityName} not found`);
127
- }
128
- // Get seeder (custom or generic)
129
- let seeder;
130
- if (this.customSeeders.has(entityName)) {
131
- seeder = this.customSeeders.get(entityName);
132
- } else {
133
- seeder = new GenericSeeder(queryRunner.manager.connection, entity, this.dataGenerator, entityInfo, options.batchSize);
134
- }
135
- // Dry run mode - preview without executing
136
- if (options.dryRun) {
137
- const count = options.count ?? getEntityCount(entityName);
138
- await queryRunner.rollbackTransaction();
139
- return {
140
- entity: entityName,
141
- success: true,
142
- count,
143
- dryRun: true
144
- };
145
- }
146
- // Skip if exists
147
- if (options.skipIfExists) {
148
- const existingCount = await seeder.count();
149
- if (existingCount > 0) {
150
- await queryRunner.rollbackTransaction();
151
- return {
152
- entity: entityName,
153
- success: true,
154
- count: 0,
155
- skipped: true
156
- };
157
- }
158
- }
159
- // Clear if requested
160
- if (options.clear) {
161
- await seeder.clear(options.respectSoftDelete ?? seedConfig.respectSoftDelete);
162
- }
163
- // Generate data
164
- const count = options.count ?? getEntityCount(entityName);
165
- const entities = await seeder.generate(count);
166
- // Commit transaction
167
- await queryRunner.commitTransaction();
168
- return {
169
- entity: entityName,
170
- success: true,
171
- count: entities.length
172
- };
173
- } catch (error) {
174
- // Rollback on error
175
- await queryRunner.rollbackTransaction();
176
- return {
177
- entity: entityName,
178
- success: false,
179
- count: 0,
180
- error: error instanceof Error ? error.message : String(error)
181
- };
182
- } finally{
183
- await queryRunner.release();
184
- }
185
- }
186
- /**
187
- * Clear all seeded data
188
- * @param hard If true, hard delete (ignore soft delete)
189
- * @param continueOnError If true, continue even if an entity fails (default: true)
190
- * @returns Array of clear results
191
- */ async clearAll(hard = false, continueOnError = true) {
192
- const results = [];
193
- // Get all entities
194
- const allEntities = this.entityReader.getAllEntities();
195
- const entityNames = allEntities.map((e)=>e.name).filter((name)=>!shouldSkipEntity(name));
196
- // Reverse order for clearing (delete children before parents)
197
- const orderedNames = getSeedingOrder(entityNames).reverse();
198
- const mode = hard ? 'Hard deleting' : 'Clearing';
199
- this.logger.log(`\nšŸ—‘ļø ${mode} ${orderedNames.length} entities...\n`);
200
- for (const entityName of orderedNames){
201
- try {
202
- const entity = this.dataSource.entityMetadatas.find((e)=>e.name === entityName)?.target;
203
- if (!entity) {
204
- throw new Error(`Entity ${entityName} not found`);
205
- }
206
- // Use custom seeder if available, otherwise generic
207
- let seeder;
208
- if (this.customSeeders.has(entityName)) {
209
- seeder = this.customSeeders.get(entityName);
210
- } else {
211
- seeder = new GenericSeeder(this.dataSource, entity, this.dataGenerator, this.entityReader.getEntityInfo(entityName));
212
- }
213
- const countBefore = await seeder.count(true);
214
- // Skip if already empty
215
- if (countBefore === 0) {
216
- results.push({
217
- entity: entityName,
218
- success: true,
219
- count: 0
220
- });
221
- this.logger.log(`⊘ ${entityName}: already empty`);
222
- continue;
223
- }
224
- await seeder.clear(hard);
225
- const countAfter = await seeder.count(true);
226
- results.push({
227
- entity: entityName,
228
- success: true,
229
- count: countBefore - countAfter
230
- });
231
- this.logger.log(`āœ“ ${entityName}: ${countBefore - countAfter} records cleared`);
232
- } catch (error) {
233
- const errorMessage = error instanceof Error ? error.message : String(error);
234
- results.push({
235
- entity: entityName,
236
- success: false,
237
- count: 0,
238
- error: errorMessage
239
- });
240
- this.logger.error(`āœ— ${entityName}: ${errorMessage}`);
241
- // Fail-fast if continueOnError is false
242
- if (!continueOnError) {
243
- this.logger.error(`\nāŒ Clearing failed at ${entityName}, stopping...\n`);
244
- break;
245
- }
246
- }
247
- }
248
- const successCount = results.filter((r)=>r.success).length;
249
- const failedCount = results.length - successCount;
250
- if (failedCount > 0) {
251
- this.logger.log(`\nāš ļø Completed with errors: ${successCount}/${results.length} entities cleared (${failedCount} failed)\n`);
252
- } else {
253
- this.logger.log(`\nāœ“ Completed: ${successCount}/${results.length} entities cleared\n`);
254
- }
255
- return results;
256
- }
257
- /**
258
- * Get status for all entities
259
- * @returns Array of entity status
260
- */ async getStatus() {
261
- const allEntities = this.entityReader.getAllEntities();
262
- const status = [];
263
- for (const metadata of allEntities){
264
- if (shouldSkipEntity(metadata.name)) {
265
- continue;
266
- }
267
- const repo = this.dataSource.getRepository(metadata.target);
268
- const count = await repo.count();
269
- const isEmpty = count === 0;
270
- const hasSoftDelete = metadata.deleteDateColumn !== undefined;
271
- status.push({
272
- entity: metadata.name,
273
- tableName: metadata.tableName,
274
- count,
275
- isEmpty,
276
- hasSoftDelete
277
- });
278
- }
279
- return status;
280
- }
281
- constructor(dataSource, logger){
282
- _define_property(this, "dataSource", void 0);
283
- _define_property(this, "entityReader", void 0);
284
- _define_property(this, "dataGenerator", void 0);
285
- _define_property(this, "logger", void 0);
286
- _define_property(this, "customSeeders", void 0);
287
- this.dataSource = dataSource;
288
- this.customSeeders = new Map();
289
- this.entityReader = new EntityReader(dataSource);
290
- this.dataGenerator = new DataGenerator(seedConfig.locale);
291
- this.logger = logger ?? defaultLogger;
292
- }
293
- }
294
- /**
295
- * Generic Seeder Implementation
296
- *
297
- * Used by SeedRunner for entities without custom seeders.
298
- * Generates data based on entity metadata with batch processing support.
299
- */ let GenericSeeder = class GenericSeeder extends BaseSeeder {
300
- async generate(count) {
301
- const allSaved = [];
302
- // Process in batches to optimize memory usage for large datasets
303
- for(let offset = 0; offset < count; offset += this.batchSize){
304
- const currentBatchSize = Math.min(this.batchSize, count - offset);
305
- const batch = [];
306
- for(let i = 0; i < currentBatchSize; i++){
307
- const data = this.generator.generateEntity(this.entityInfo.columns);
308
- // TypeORM's create method returns T, but TypeScript needs explicit type assertion
309
- const entity = this.repository.create(data);
310
- batch.push(entity);
311
- }
312
- // TypeORM's save method has overloads for T and T[]
313
- // We need to explicitly cast to handle the generic type resolution
314
- const saved = await this.repository.save(batch);
315
- allSaved.push(...saved);
316
- }
317
- return allSaved;
318
- }
319
- constructor(dataSource, entity, generator, entityInfo, batchSize){
320
- super(dataSource, entity), _define_property(this, "generator", void 0), _define_property(this, "entityInfo", void 0), _define_property(this, "batchSize", void 0), this.generator = generator, this.entityInfo = entityInfo;
321
- this.batchSize = batchSize ?? 1000; // Default batch size
322
- }
323
- };