@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.
- package/README.md +505 -63
- package/cjs/config/env-config.service.js +1 -1
- package/cjs/docs/docs.config.js +77 -3
- package/cjs/docs/index.js +0 -1
- package/cjs/interfaces/base-entity.interface.js +5 -3
- package/cjs/interfaces/database.interface.js +1 -3
- package/cjs/migration/datasource.factory.js +1 -3
- package/cjs/migration/index.js +0 -12
- package/cjs/migration/migration.cli.js +1 -17
- package/cjs/migration/migration.runner.js +37 -65
- package/cjs/seeders/base-seeder.js +6 -25
- package/cjs/seeders/cli.js +65 -172
- package/cjs/seeders/data-generator.js +96 -142
- package/cjs/seeders/entity-reader.js +0 -17
- package/cjs/seeders/field-patterns.js +172 -0
- package/cjs/seeders/index.js +16 -8
- package/cjs/seeders/seed-config.js +9 -48
- package/cjs/seeders/seed-runner.js +8 -14
- package/cjs/utils/datasource-config.builder.js +2 -14
- package/docs/docs.config.d.ts +7 -0
- package/docs/index.d.ts +0 -1
- package/fesm/config/env-config.service.js +1 -1
- package/fesm/docs/docs.config.js +68 -0
- package/fesm/docs/index.js +0 -1
- package/fesm/interfaces/app-config.interfaces.js +1 -3
- package/fesm/interfaces/base-entity.interface.js +5 -5
- package/fesm/interfaces/database.interface.js +1 -5
- package/fesm/migration/cli.js +1 -20
- package/fesm/migration/datasource.factory.js +3 -20
- package/fesm/migration/index.js +0 -14
- package/fesm/migration/migration.cli.js +1 -17
- package/fesm/migration/migration.runner.js +43 -132
- package/fesm/seeders/base-seeder.js +7 -51
- package/fesm/seeders/cli.js +65 -182
- package/fesm/seeders/data-generator.js +96 -149
- package/fesm/seeders/entity-reader.js +0 -17
- package/fesm/seeders/field-patterns.js +143 -0
- package/fesm/seeders/index.js +3 -7
- package/fesm/seeders/seed-config.js +9 -59
- package/fesm/seeders/seed-runner.js +8 -14
- package/fesm/utils/datasource-config.builder.js +2 -13
- package/interfaces/base-entity.interface.d.ts +3 -0
- package/package.json +2 -2
- package/seeders/data-generator.d.ts +1 -1
- package/seeders/entity-reader.d.ts +0 -1
- package/seeders/field-patterns.d.ts +12 -0
- package/seeders/index.d.ts +3 -3
- package/seeders/seed-config.d.ts +1 -0
- package/seeders/seed-runner.d.ts +1 -0
- package/utils/datasource-config.builder.d.ts +0 -1
- package/cjs/docs/docs.setup.js +0 -14
- package/cjs/seeders/template-generator.js +0 -297
- package/docs/docs.setup.d.ts +0 -3
- package/fesm/docs/docs.setup.js +0 -4
- package/fesm/seeders/template-generator.js +0 -257
- package/seeders/template-generator.d.ts +0 -16
|
@@ -9,27 +9,23 @@ Object.defineProperty(exports, "DataGenerator", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _faker = require("@faker-js/faker");
|
|
12
|
+
const _fieldpatterns = require("./field-patterns");
|
|
12
13
|
let DataGenerator = class DataGenerator {
|
|
13
14
|
/**
|
|
14
15
|
* Generate value for a single column based on its metadata
|
|
15
16
|
*/ generateValue(column) {
|
|
16
|
-
|
|
17
|
-
if (column.isGenerated) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
17
|
+
if (column.isGenerated) return undefined;
|
|
20
18
|
// Handle nullable fields (50% chance of null)
|
|
21
|
-
if (column.isNullable && _faker.faker.datatype.boolean())
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
19
|
+
if (column.isNullable && _faker.faker.datatype.boolean()) return null;
|
|
24
20
|
// Check for enum
|
|
25
21
|
if (column.enum && column.enum.length > 0) {
|
|
26
22
|
return _faker.faker.helpers.arrayElement(column.enum);
|
|
27
23
|
}
|
|
28
|
-
// Generate based on
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return value;
|
|
24
|
+
// Generate based on field pattern
|
|
25
|
+
const pattern = (0, _fieldpatterns.detectFieldPattern)(column);
|
|
26
|
+
if (pattern) {
|
|
27
|
+
const value = this.generateByPattern(pattern, column);
|
|
28
|
+
if (value !== undefined) return value;
|
|
33
29
|
}
|
|
34
30
|
// Generate based on column type
|
|
35
31
|
return this.generateByType(column);
|
|
@@ -47,143 +43,108 @@ let DataGenerator = class DataGenerator {
|
|
|
47
43
|
return entity;
|
|
48
44
|
}
|
|
49
45
|
/**
|
|
50
|
-
* Generate value based on
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
'
|
|
56
|
-
|
|
57
|
-
'
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
'
|
|
64
|
-
|
|
65
|
-
'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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();
|
|
46
|
+
* Generate value based on detected field pattern
|
|
47
|
+
*/ generateByPattern(pattern, column) {
|
|
48
|
+
switch(pattern){
|
|
49
|
+
case 'skip':
|
|
50
|
+
return undefined;
|
|
51
|
+
case 'null':
|
|
52
|
+
return null;
|
|
53
|
+
case 'boolean':
|
|
54
|
+
return _faker.faker.datatype.boolean();
|
|
55
|
+
case 'token':
|
|
56
|
+
return _faker.faker.string.alphanumeric((0, _fieldpatterns.getTokenLength)(column));
|
|
57
|
+
case 'firstName':
|
|
58
|
+
return _faker.faker.person.firstName();
|
|
59
|
+
case 'lastName':
|
|
60
|
+
return _faker.faker.person.lastName();
|
|
61
|
+
case 'fullName':
|
|
62
|
+
return _faker.faker.person.fullName();
|
|
63
|
+
case 'email':
|
|
64
|
+
return _faker.faker.internet.email().toLowerCase();
|
|
65
|
+
case 'phone':
|
|
66
|
+
return _faker.faker.phone.number();
|
|
67
|
+
case 'address':
|
|
68
|
+
return _faker.faker.location.streetAddress();
|
|
69
|
+
case 'street':
|
|
70
|
+
return _faker.faker.location.street();
|
|
71
|
+
case 'city':
|
|
72
|
+
return _faker.faker.location.city();
|
|
73
|
+
case 'state':
|
|
74
|
+
return _faker.faker.location.state();
|
|
75
|
+
case 'country':
|
|
76
|
+
return _faker.faker.location.country();
|
|
77
|
+
case 'zipCode':
|
|
78
|
+
return _faker.faker.location.zipCode();
|
|
79
|
+
case 'url':
|
|
80
|
+
return _faker.faker.internet.url();
|
|
81
|
+
case 'domain':
|
|
82
|
+
return _faker.faker.internet.domainName();
|
|
83
|
+
case 'slug':
|
|
84
|
+
return _faker.faker.helpers.slugify(_faker.faker.lorem.words(3)).toLowerCase();
|
|
85
|
+
case 'description':
|
|
86
|
+
return _faker.faker.lorem.paragraph();
|
|
87
|
+
case 'summary':
|
|
88
|
+
return _faker.faker.lorem.sentence();
|
|
89
|
+
case 'content':
|
|
90
|
+
return _faker.faker.lorem.paragraphs(3);
|
|
91
|
+
case 'title':
|
|
92
|
+
return _faker.faker.lorem.sentence();
|
|
93
|
+
case 'username':
|
|
94
|
+
return _faker.faker.internet.username();
|
|
95
|
+
case 'password':
|
|
96
|
+
return '$2b$12$dummy.hashed.password.value';
|
|
97
|
+
case 'birthdate':
|
|
98
|
+
return _faker.faker.date.birthdate({
|
|
99
|
+
min: 18,
|
|
100
|
+
max: 80,
|
|
101
|
+
mode: 'age'
|
|
102
|
+
});
|
|
103
|
+
case 'futureDate':
|
|
104
|
+
return _faker.faker.date.future();
|
|
105
|
+
case 'recentDateOrNull':
|
|
106
|
+
return _faker.faker.datatype.boolean() ? _faker.faker.date.recent() : null;
|
|
107
|
+
case 'serial':
|
|
108
|
+
return _faker.faker.number.int({
|
|
109
|
+
min: 1,
|
|
110
|
+
max: 100
|
|
111
|
+
});
|
|
112
|
+
case 'company':
|
|
113
|
+
return _faker.faker.company.name();
|
|
114
|
+
default:
|
|
115
|
+
return undefined;
|
|
132
116
|
}
|
|
133
|
-
return undefined;
|
|
134
117
|
}
|
|
135
118
|
/**
|
|
136
119
|
* Generate value based on column type
|
|
137
120
|
*/ generateByType(column) {
|
|
138
|
-
const
|
|
139
|
-
switch(
|
|
140
|
-
// String types
|
|
141
|
-
case 'varchar':
|
|
142
|
-
case 'character varying':
|
|
143
|
-
case 'text':
|
|
121
|
+
const category = (0, _fieldpatterns.detectTypeCategory)(column.type);
|
|
122
|
+
switch(category){
|
|
144
123
|
case 'string':
|
|
145
124
|
return this.generateString(column);
|
|
146
|
-
// Number types
|
|
147
|
-
case 'int':
|
|
148
125
|
case 'integer':
|
|
149
|
-
case 'smallint':
|
|
150
|
-
case 'bigint':
|
|
151
126
|
return _faker.faker.number.int({
|
|
152
127
|
min: 1,
|
|
153
128
|
max: 1000
|
|
154
129
|
});
|
|
155
130
|
case 'decimal':
|
|
156
|
-
case 'numeric':
|
|
157
|
-
case 'float':
|
|
158
|
-
case 'double':
|
|
159
|
-
case 'real':
|
|
160
131
|
return _faker.faker.number.float({
|
|
161
132
|
min: 0,
|
|
162
133
|
max: 10000,
|
|
163
134
|
fractionDigits: column.scale || 2
|
|
164
135
|
});
|
|
165
|
-
// Boolean
|
|
166
136
|
case 'boolean':
|
|
167
|
-
case 'bool':
|
|
168
137
|
return _faker.faker.datatype.boolean();
|
|
169
|
-
// Date/Time
|
|
170
138
|
case 'date':
|
|
171
|
-
return _faker.faker.date.recent({
|
|
172
|
-
days: 30
|
|
173
|
-
});
|
|
174
139
|
case 'timestamp':
|
|
175
|
-
case 'datetime':
|
|
176
140
|
return _faker.faker.date.recent({
|
|
177
141
|
days: 30
|
|
178
142
|
});
|
|
179
143
|
case 'time':
|
|
180
144
|
return _faker.faker.date.recent().toTimeString().split(' ')[0];
|
|
181
|
-
// UUID
|
|
182
145
|
case 'uuid':
|
|
183
146
|
return _faker.faker.string.uuid();
|
|
184
|
-
// JSON
|
|
185
147
|
case 'json':
|
|
186
|
-
case 'jsonb':
|
|
187
148
|
return {
|
|
188
149
|
key1: _faker.faker.lorem.word(),
|
|
189
150
|
key2: _faker.faker.number.int({
|
|
@@ -191,13 +152,11 @@ let DataGenerator = class DataGenerator {
|
|
|
191
152
|
max: 100
|
|
192
153
|
})
|
|
193
154
|
};
|
|
194
|
-
// Array
|
|
195
155
|
case 'array':
|
|
196
156
|
return [
|
|
197
157
|
_faker.faker.lorem.word(),
|
|
198
158
|
_faker.faker.lorem.word()
|
|
199
159
|
];
|
|
200
|
-
// Default
|
|
201
160
|
default:
|
|
202
161
|
return _faker.faker.lorem.word();
|
|
203
162
|
}
|
|
@@ -206,42 +165,37 @@ let DataGenerator = class DataGenerator {
|
|
|
206
165
|
* Generate string value respecting length constraints
|
|
207
166
|
*/ generateString(column) {
|
|
208
167
|
const maxLength = typeof column.length === 'number' ? column.length : 255;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
168
|
+
const category = (0, _fieldpatterns.getStringLengthCategory)(column.length);
|
|
169
|
+
switch(category){
|
|
170
|
+
case 'word':
|
|
171
|
+
return _faker.faker.lorem.word().substring(0, maxLength);
|
|
172
|
+
case 'sentence':
|
|
173
|
+
return _faker.faker.lorem.sentence().substring(0, maxLength);
|
|
174
|
+
case 'paragraph':
|
|
175
|
+
return _faker.faker.lorem.paragraph().substring(0, maxLength);
|
|
215
176
|
}
|
|
216
177
|
}
|
|
217
178
|
/**
|
|
218
179
|
* Generate related entity ID (for foreign keys)
|
|
219
|
-
* @param relatedEntities Array of entities to pick from
|
|
220
180
|
*/ generateRelationId(relatedEntities) {
|
|
221
|
-
if (relatedEntities.length === 0)
|
|
222
|
-
return null;
|
|
223
|
-
}
|
|
181
|
+
if (relatedEntities.length === 0) return null;
|
|
224
182
|
return _faker.faker.helpers.arrayElement(relatedEntities).id;
|
|
225
183
|
}
|
|
226
184
|
/**
|
|
227
185
|
* 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
186
|
*/ generateRelationIds(relatedEntities, min = 1, max = 3) {
|
|
232
|
-
if (relatedEntities.length === 0)
|
|
233
|
-
return [];
|
|
234
|
-
}
|
|
187
|
+
if (relatedEntities.length === 0) return [];
|
|
235
188
|
const count = _faker.faker.number.int({
|
|
236
189
|
min,
|
|
237
190
|
max: Math.min(max, relatedEntities.length)
|
|
238
191
|
});
|
|
239
|
-
|
|
240
|
-
return selected.map((e)=>e.id);
|
|
192
|
+
return _faker.faker.helpers.arrayElements(relatedEntities, count).map((e)=>e.id);
|
|
241
193
|
}
|
|
242
194
|
constructor(locale = 'en'){
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
195
|
+
_faker.faker.setDefaultRefDate(new Date());
|
|
196
|
+
if (locale !== 'en') {
|
|
197
|
+
// @ts-expect-error - faker locale property access
|
|
198
|
+
_faker.faker.locale = locale;
|
|
199
|
+
}
|
|
246
200
|
}
|
|
247
201
|
};
|
|
@@ -53,23 +53,6 @@ let EntityReader = class EntityReader {
|
|
|
53
53
|
return this.topologicalSort(graph);
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Check if entity has required columns populated
|
|
57
|
-
* Used to determine if entity is ready for seeding
|
|
58
|
-
*/ hasRequiredDependencies(entityName, dataSource) {
|
|
59
|
-
const info = this.getEntityInfo(entityName);
|
|
60
|
-
for (const relation of info.relations){
|
|
61
|
-
if (!relation.isNullable && relation.type === 'many-to-one') {
|
|
62
|
-
const targetRepo = dataSource.getRepository(relation.targetEntity);
|
|
63
|
-
if (targetRepo) {
|
|
64
|
-
// Check if target entity has data
|
|
65
|
-
// Note: This is a simplified check, actual implementation may need async
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
56
|
* Find entity metadata by name or table name
|
|
74
57
|
*/ findEntityMetadata(entityName) {
|
|
75
58
|
return this.getAllEntities().find((e)=>e.name === entityName || e.tableName === entityName);
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get AUDIT_FIELDS () {
|
|
13
|
+
return AUDIT_FIELDS;
|
|
14
|
+
},
|
|
15
|
+
get BOOLEAN_KEYWORDS () {
|
|
16
|
+
return BOOLEAN_KEYWORDS;
|
|
17
|
+
},
|
|
18
|
+
get IDENTITY_FIELDS () {
|
|
19
|
+
return IDENTITY_FIELDS;
|
|
20
|
+
},
|
|
21
|
+
get SYSTEM_FIELDS () {
|
|
22
|
+
return SYSTEM_FIELDS;
|
|
23
|
+
},
|
|
24
|
+
get detectFieldPattern () {
|
|
25
|
+
return detectFieldPattern;
|
|
26
|
+
},
|
|
27
|
+
get detectTypeCategory () {
|
|
28
|
+
return detectTypeCategory;
|
|
29
|
+
},
|
|
30
|
+
get getStringLengthCategory () {
|
|
31
|
+
return getStringLengthCategory;
|
|
32
|
+
},
|
|
33
|
+
get getTokenLength () {
|
|
34
|
+
return getTokenLength;
|
|
35
|
+
},
|
|
36
|
+
get isSystemField () {
|
|
37
|
+
return isSystemField;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const SYSTEM_FIELDS = [
|
|
41
|
+
'id',
|
|
42
|
+
'createdAt',
|
|
43
|
+
'updatedAt',
|
|
44
|
+
'deletedAt',
|
|
45
|
+
'createdById',
|
|
46
|
+
'updatedById',
|
|
47
|
+
'deletedById'
|
|
48
|
+
];
|
|
49
|
+
const AUDIT_FIELDS = [
|
|
50
|
+
'createdbyid',
|
|
51
|
+
'updatedbyid',
|
|
52
|
+
'deletedbyid'
|
|
53
|
+
];
|
|
54
|
+
const IDENTITY_FIELDS = [
|
|
55
|
+
'id',
|
|
56
|
+
'createdat',
|
|
57
|
+
'updatedat',
|
|
58
|
+
'deletedat'
|
|
59
|
+
];
|
|
60
|
+
const BOOLEAN_KEYWORDS = [
|
|
61
|
+
'verified',
|
|
62
|
+
'active',
|
|
63
|
+
'enabled',
|
|
64
|
+
'public',
|
|
65
|
+
'readonly',
|
|
66
|
+
'valid'
|
|
67
|
+
];
|
|
68
|
+
function detectFieldPattern(column) {
|
|
69
|
+
const nameLower = column.propertyName.toLowerCase();
|
|
70
|
+
const typeLower = column.type.toLowerCase();
|
|
71
|
+
// Identity fields (skip)
|
|
72
|
+
if (IDENTITY_FIELDS.includes(nameLower)) return 'skip';
|
|
73
|
+
// Audit fields (null)
|
|
74
|
+
if (AUDIT_FIELDS.includes(nameLower)) return 'null';
|
|
75
|
+
// Boolean fields with specific keywords
|
|
76
|
+
if ((typeLower === 'boolean' || typeLower === 'bool') && BOOLEAN_KEYWORDS.some((k)=>nameLower.includes(k))) {
|
|
77
|
+
return 'boolean';
|
|
78
|
+
}
|
|
79
|
+
// Token fields
|
|
80
|
+
if (nameLower.includes('token')) return 'token';
|
|
81
|
+
// Name fields
|
|
82
|
+
if (nameLower.includes('firstname')) return 'firstName';
|
|
83
|
+
if (nameLower.includes('lastname')) return 'lastName';
|
|
84
|
+
if (nameLower.includes('fullname') || nameLower === 'name') return 'fullName';
|
|
85
|
+
// Contact fields
|
|
86
|
+
if (nameLower.includes('email') && typeLower !== 'boolean') return 'email';
|
|
87
|
+
if (nameLower.includes('phone') || nameLower.includes('mobile')) return 'phone';
|
|
88
|
+
// Location fields
|
|
89
|
+
if (nameLower.includes('address')) return 'address';
|
|
90
|
+
if (nameLower.includes('street')) return 'street';
|
|
91
|
+
if (nameLower.includes('city')) return 'city';
|
|
92
|
+
if (nameLower.includes('state')) return 'state';
|
|
93
|
+
if (nameLower.includes('country')) return 'country';
|
|
94
|
+
if (nameLower.includes('zipcode') || nameLower.includes('postalcode')) return 'zipCode';
|
|
95
|
+
// URL/Web fields
|
|
96
|
+
if (nameLower.includes('url') || nameLower.includes('website')) return 'url';
|
|
97
|
+
if (nameLower.includes('domain')) return 'domain';
|
|
98
|
+
if (nameLower.includes('slug')) return 'slug';
|
|
99
|
+
// Text fields
|
|
100
|
+
if (nameLower.includes('description')) return 'description';
|
|
101
|
+
if (nameLower.includes('summary')) return 'summary';
|
|
102
|
+
if (nameLower.includes('content')) return 'content';
|
|
103
|
+
if (nameLower.includes('title')) return 'title';
|
|
104
|
+
// User fields
|
|
105
|
+
if (nameLower.includes('username')) return 'username';
|
|
106
|
+
if (nameLower.includes('password')) return 'password';
|
|
107
|
+
// Boolean status fields (fallback)
|
|
108
|
+
if (nameLower.includes('isactive') || nameLower.includes('isenabled') || nameLower.includes('ispublic') || nameLower.includes('isverified')) {
|
|
109
|
+
return 'boolean';
|
|
110
|
+
}
|
|
111
|
+
// Date fields
|
|
112
|
+
if (nameLower.includes('birthdate') || nameLower.includes('dateofbirth')) return 'birthdate';
|
|
113
|
+
if (nameLower.includes('expiresat') || nameLower.includes('expirydate')) return 'futureDate';
|
|
114
|
+
if (nameLower.includes('verifiedat')) return 'recentDateOrNull';
|
|
115
|
+
// Serial/Order fields
|
|
116
|
+
if (nameLower.includes('serial') || nameLower.includes('order')) return 'serial';
|
|
117
|
+
// Company
|
|
118
|
+
if (nameLower.includes('company') && !nameLower.includes('id')) return 'company';
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
function detectTypeCategory(type) {
|
|
122
|
+
const typeLower = type.toLowerCase();
|
|
123
|
+
if ([
|
|
124
|
+
'varchar',
|
|
125
|
+
'character varying',
|
|
126
|
+
'text',
|
|
127
|
+
'string'
|
|
128
|
+
].includes(typeLower)) return 'string';
|
|
129
|
+
if ([
|
|
130
|
+
'int',
|
|
131
|
+
'integer',
|
|
132
|
+
'smallint',
|
|
133
|
+
'bigint'
|
|
134
|
+
].includes(typeLower)) return 'integer';
|
|
135
|
+
if ([
|
|
136
|
+
'decimal',
|
|
137
|
+
'numeric',
|
|
138
|
+
'float',
|
|
139
|
+
'double',
|
|
140
|
+
'real'
|
|
141
|
+
].includes(typeLower)) return 'decimal';
|
|
142
|
+
if ([
|
|
143
|
+
'boolean',
|
|
144
|
+
'bool'
|
|
145
|
+
].includes(typeLower)) return 'boolean';
|
|
146
|
+
if (typeLower === 'date') return 'date';
|
|
147
|
+
if ([
|
|
148
|
+
'timestamp',
|
|
149
|
+
'datetime'
|
|
150
|
+
].includes(typeLower)) return 'timestamp';
|
|
151
|
+
if (typeLower === 'time') return 'time';
|
|
152
|
+
if (typeLower === 'uuid') return 'uuid';
|
|
153
|
+
if ([
|
|
154
|
+
'json',
|
|
155
|
+
'jsonb'
|
|
156
|
+
].includes(typeLower)) return 'json';
|
|
157
|
+
if (typeLower === 'array') return 'array';
|
|
158
|
+
return 'unknown';
|
|
159
|
+
}
|
|
160
|
+
function getStringLengthCategory(length) {
|
|
161
|
+
const maxLength = typeof length === 'number' ? length : 255;
|
|
162
|
+
if (maxLength <= 50) return 'word';
|
|
163
|
+
if (maxLength <= 255) return 'sentence';
|
|
164
|
+
return 'paragraph';
|
|
165
|
+
}
|
|
166
|
+
function isSystemField(fieldName) {
|
|
167
|
+
return SYSTEM_FIELDS.includes(fieldName);
|
|
168
|
+
}
|
|
169
|
+
function getTokenLength(column) {
|
|
170
|
+
const maxLength = typeof column.length === 'number' ? column.length : 64;
|
|
171
|
+
return Math.min(maxLength, 32);
|
|
172
|
+
}
|
package/cjs/seeders/index.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Seed System Exports
|
|
3
|
-
*
|
|
4
|
-
* Public API for seed data generation system.
|
|
5
|
-
*/ "use strict";
|
|
1
|
+
"use strict";
|
|
6
2
|
Object.defineProperty(exports, "__esModule", {
|
|
7
3
|
value: true
|
|
8
4
|
});
|
|
@@ -43,21 +39,33 @@ _export(exports, {
|
|
|
43
39
|
get ISeederLogger () {
|
|
44
40
|
return _seedrunner.ISeederLogger;
|
|
45
41
|
},
|
|
42
|
+
get SYSTEM_FIELDS () {
|
|
43
|
+
return _fieldpatterns.SYSTEM_FIELDS;
|
|
44
|
+
},
|
|
46
45
|
get SeedRunner () {
|
|
47
46
|
return _seedrunner.SeedRunner;
|
|
48
47
|
},
|
|
49
|
-
get
|
|
50
|
-
return
|
|
48
|
+
get configureSeedConfig () {
|
|
49
|
+
return _seedconfig.configureSeedConfig;
|
|
51
50
|
},
|
|
52
51
|
get defaultLogger () {
|
|
53
52
|
return _seedrunner.defaultLogger;
|
|
54
53
|
},
|
|
54
|
+
get detectFieldPattern () {
|
|
55
|
+
return _fieldpatterns.detectFieldPattern;
|
|
56
|
+
},
|
|
57
|
+
get detectTypeCategory () {
|
|
58
|
+
return _fieldpatterns.detectTypeCategory;
|
|
59
|
+
},
|
|
55
60
|
get getEntityCount () {
|
|
56
61
|
return _seedconfig.getEntityCount;
|
|
57
62
|
},
|
|
58
63
|
get getSeedingOrder () {
|
|
59
64
|
return _seedconfig.getSeedingOrder;
|
|
60
65
|
},
|
|
66
|
+
get isSystemField () {
|
|
67
|
+
return _fieldpatterns.isSystemField;
|
|
68
|
+
},
|
|
61
69
|
get runSeedCli () {
|
|
62
70
|
return _cli.runSeedCli;
|
|
63
71
|
},
|
|
@@ -71,7 +79,7 @@ _export(exports, {
|
|
|
71
79
|
const _baseseeder = require("./base-seeder");
|
|
72
80
|
const _entityreader = require("./entity-reader");
|
|
73
81
|
const _datagenerator = require("./data-generator");
|
|
74
|
-
const _templategenerator = require("./template-generator");
|
|
75
82
|
const _seedrunner = require("./seed-runner");
|
|
76
83
|
const _seedconfig = require("./seed-config");
|
|
84
|
+
const _fieldpatterns = require("./field-patterns");
|
|
77
85
|
const _cli = require("./cli");
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Seed Configuration
|
|
3
|
-
*
|
|
4
|
-
* Configuration for seed data generation.
|
|
5
|
-
* Customize record counts, seeding order, and behavior.
|
|
6
|
-
*/ "use strict";
|
|
1
|
+
"use strict";
|
|
7
2
|
Object.defineProperty(exports, "__esModule", {
|
|
8
3
|
value: true
|
|
9
4
|
});
|
|
@@ -14,6 +9,9 @@ function _export(target, all) {
|
|
|
14
9
|
});
|
|
15
10
|
}
|
|
16
11
|
_export(exports, {
|
|
12
|
+
get configureSeedConfig () {
|
|
13
|
+
return configureSeedConfig;
|
|
14
|
+
},
|
|
17
15
|
get getEntityCount () {
|
|
18
16
|
return getEntityCount;
|
|
19
17
|
},
|
|
@@ -28,55 +26,20 @@ _export(exports, {
|
|
|
28
26
|
}
|
|
29
27
|
});
|
|
30
28
|
const seedConfig = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Auth entities
|
|
34
|
-
Company: 10,
|
|
35
|
-
CompanyBranch: 25,
|
|
36
|
-
User: 50,
|
|
37
|
-
// IAM entities
|
|
38
|
-
Role: 8,
|
|
39
|
-
Permission: 45,
|
|
40
|
-
Action: 30,
|
|
41
|
-
Menu: 20,
|
|
42
|
-
UserIAMPermission: 50,
|
|
43
|
-
UserCompanyPermission: 100,
|
|
44
|
-
// Storage entities
|
|
45
|
-
StorageConfig: 5,
|
|
46
|
-
Folder: 20,
|
|
47
|
-
FileManager: 100
|
|
48
|
-
},
|
|
49
|
-
// Entity seeding order (respects FK constraints)
|
|
50
|
-
// Parent entities must come before child entities
|
|
51
|
-
order: [
|
|
52
|
-
// Auth - foundational
|
|
53
|
-
'Company',
|
|
54
|
-
'CompanyBranch',
|
|
55
|
-
'User',
|
|
56
|
-
// IAM - permissions system
|
|
57
|
-
'Action',
|
|
58
|
-
'Role',
|
|
59
|
-
'Permission',
|
|
60
|
-
'Menu',
|
|
61
|
-
'UserIAMPermission',
|
|
62
|
-
'UserCompanyPermission',
|
|
63
|
-
// Storage - file system
|
|
64
|
-
'StorageConfig',
|
|
65
|
-
'Folder',
|
|
66
|
-
'FileManager'
|
|
67
|
-
],
|
|
68
|
-
// Skip these entities (system tables, migrations)
|
|
29
|
+
counts: {},
|
|
30
|
+
order: [],
|
|
69
31
|
skipEntities: [
|
|
70
32
|
'migrations',
|
|
71
33
|
'typeorm_metadata',
|
|
72
34
|
'Migration',
|
|
73
35
|
'Typeorm_Metadata'
|
|
74
36
|
],
|
|
75
|
-
// Faker locale (en, ar, es, fr, de, etc.)
|
|
76
37
|
locale: 'en',
|
|
77
|
-
// Respect soft delete when clearing data
|
|
78
38
|
respectSoftDelete: true
|
|
79
39
|
};
|
|
40
|
+
function configureSeedConfig(config) {
|
|
41
|
+
Object.assign(seedConfig, config);
|
|
42
|
+
}
|
|
80
43
|
function getEntityCount(entityName, config = seedConfig) {
|
|
81
44
|
return config.counts[entityName] || 10;
|
|
82
45
|
}
|
|
@@ -85,13 +48,11 @@ function shouldSkipEntity(entityName, config = seedConfig) {
|
|
|
85
48
|
}
|
|
86
49
|
function getSeedingOrder(availableEntities, config = seedConfig) {
|
|
87
50
|
const ordered = [];
|
|
88
|
-
// Add entities in configured order
|
|
89
51
|
for (const entityName of config.order){
|
|
90
52
|
if (availableEntities.includes(entityName) && !shouldSkipEntity(entityName, config)) {
|
|
91
53
|
ordered.push(entityName);
|
|
92
54
|
}
|
|
93
55
|
}
|
|
94
|
-
// Add remaining entities not in order configuration
|
|
95
56
|
for (const entityName of availableEntities){
|
|
96
57
|
if (!ordered.includes(entityName) && !shouldSkipEntity(entityName, config)) {
|
|
97
58
|
ordered.push(entityName);
|