@flusys/nestjs-core 1.0.0-rc → 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 +482 -73
- package/cjs/docs/docs.config.js +77 -3
- package/cjs/docs/index.js +0 -1
- package/cjs/migration/migration.runner.js +37 -65
- package/cjs/seeders/cli.js +65 -172
- package/cjs/seeders/data-generator.js +91 -139
- package/cjs/seeders/field-patterns.js +172 -0
- package/cjs/seeders/index.js +13 -4
- package/cjs/seeders/seed-runner.js +8 -14
- package/docs/docs.config.d.ts +7 -0
- package/docs/index.d.ts +0 -1
- package/fesm/docs/docs.config.js +68 -0
- package/fesm/docs/index.js +0 -1
- package/fesm/migration/migration.runner.js +37 -65
- package/fesm/seeders/cli.js +65 -182
- package/fesm/seeders/data-generator.js +91 -146
- package/fesm/seeders/field-patterns.js +143 -0
- package/fesm/seeders/index.js +1 -1
- package/fesm/seeders/seed-runner.js +8 -14
- package/package.json +1 -1
- package/seeders/data-generator.d.ts +1 -1
- package/seeders/field-patterns.d.ts +12 -0
- package/seeders/index.d.ts +1 -1
- package/seeders/seed-runner.d.ts +1 -0
- 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
|
@@ -1,37 +1,26 @@
|
|
|
1
1
|
import { faker } from '@faker-js/faker';
|
|
2
|
+
import { detectFieldPattern, detectTypeCategory, getStringLengthCategory, getTokenLength } from './field-patterns';
|
|
2
3
|
/**
|
|
3
4
|
* Data Generator Service
|
|
4
5
|
*
|
|
5
6
|
* Generates realistic sample data based on column metadata.
|
|
6
7
|
* Uses @faker-js/faker for data generation with intelligent field detection.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* ```typescript
|
|
10
|
-
* const generator = new DataGenerator();
|
|
11
|
-
* const value = generator.generateValue(columnInfo);
|
|
12
|
-
* const entity = generator.generateEntity(columns);
|
|
13
|
-
* ```
|
|
14
8
|
*/ export class DataGenerator {
|
|
15
9
|
/**
|
|
16
10
|
* Generate value for a single column based on its metadata
|
|
17
11
|
*/ generateValue(column) {
|
|
18
|
-
|
|
19
|
-
if (column.isGenerated) {
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
12
|
+
if (column.isGenerated) return undefined;
|
|
22
13
|
// Handle nullable fields (50% chance of null)
|
|
23
|
-
if (column.isNullable && faker.datatype.boolean())
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
14
|
+
if (column.isNullable && faker.datatype.boolean()) return null;
|
|
26
15
|
// Check for enum
|
|
27
16
|
if (column.enum && column.enum.length > 0) {
|
|
28
17
|
return faker.helpers.arrayElement(column.enum);
|
|
29
18
|
}
|
|
30
|
-
// Generate based on
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return value;
|
|
19
|
+
// Generate based on field pattern
|
|
20
|
+
const pattern = detectFieldPattern(column);
|
|
21
|
+
if (pattern) {
|
|
22
|
+
const value = this.generateByPattern(pattern, column);
|
|
23
|
+
if (value !== undefined) return value;
|
|
35
24
|
}
|
|
36
25
|
// Generate based on column type
|
|
37
26
|
return this.generateByType(column);
|
|
@@ -49,143 +38,108 @@ import { faker } from '@faker-js/faker';
|
|
|
49
38
|
return entity;
|
|
50
39
|
}
|
|
51
40
|
/**
|
|
52
|
-
* Generate value based on
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
return faker.datatype.boolean() ? faker.date.recent() : null;
|
|
123
|
-
}
|
|
124
|
-
// Serial/Order fields
|
|
125
|
-
if (nameLower.includes('serial') || nameLower.includes('order')) {
|
|
126
|
-
return faker.number.int({
|
|
127
|
-
min: 1,
|
|
128
|
-
max: 100
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
// Company/Organization
|
|
132
|
-
if (nameLower.includes('company') && !nameLower.includes('id')) {
|
|
133
|
-
return faker.company.name();
|
|
41
|
+
* Generate value based on detected field pattern
|
|
42
|
+
*/ generateByPattern(pattern, column) {
|
|
43
|
+
switch(pattern){
|
|
44
|
+
case 'skip':
|
|
45
|
+
return undefined;
|
|
46
|
+
case 'null':
|
|
47
|
+
return null;
|
|
48
|
+
case 'boolean':
|
|
49
|
+
return faker.datatype.boolean();
|
|
50
|
+
case 'token':
|
|
51
|
+
return faker.string.alphanumeric(getTokenLength(column));
|
|
52
|
+
case 'firstName':
|
|
53
|
+
return faker.person.firstName();
|
|
54
|
+
case 'lastName':
|
|
55
|
+
return faker.person.lastName();
|
|
56
|
+
case 'fullName':
|
|
57
|
+
return faker.person.fullName();
|
|
58
|
+
case 'email':
|
|
59
|
+
return faker.internet.email().toLowerCase();
|
|
60
|
+
case 'phone':
|
|
61
|
+
return faker.phone.number();
|
|
62
|
+
case 'address':
|
|
63
|
+
return faker.location.streetAddress();
|
|
64
|
+
case 'street':
|
|
65
|
+
return faker.location.street();
|
|
66
|
+
case 'city':
|
|
67
|
+
return faker.location.city();
|
|
68
|
+
case 'state':
|
|
69
|
+
return faker.location.state();
|
|
70
|
+
case 'country':
|
|
71
|
+
return faker.location.country();
|
|
72
|
+
case 'zipCode':
|
|
73
|
+
return faker.location.zipCode();
|
|
74
|
+
case 'url':
|
|
75
|
+
return faker.internet.url();
|
|
76
|
+
case 'domain':
|
|
77
|
+
return faker.internet.domainName();
|
|
78
|
+
case 'slug':
|
|
79
|
+
return faker.helpers.slugify(faker.lorem.words(3)).toLowerCase();
|
|
80
|
+
case 'description':
|
|
81
|
+
return faker.lorem.paragraph();
|
|
82
|
+
case 'summary':
|
|
83
|
+
return faker.lorem.sentence();
|
|
84
|
+
case 'content':
|
|
85
|
+
return faker.lorem.paragraphs(3);
|
|
86
|
+
case 'title':
|
|
87
|
+
return faker.lorem.sentence();
|
|
88
|
+
case 'username':
|
|
89
|
+
return faker.internet.username();
|
|
90
|
+
case 'password':
|
|
91
|
+
return '$2b$12$dummy.hashed.password.value';
|
|
92
|
+
case 'birthdate':
|
|
93
|
+
return faker.date.birthdate({
|
|
94
|
+
min: 18,
|
|
95
|
+
max: 80,
|
|
96
|
+
mode: 'age'
|
|
97
|
+
});
|
|
98
|
+
case 'futureDate':
|
|
99
|
+
return faker.date.future();
|
|
100
|
+
case 'recentDateOrNull':
|
|
101
|
+
return faker.datatype.boolean() ? faker.date.recent() : null;
|
|
102
|
+
case 'serial':
|
|
103
|
+
return faker.number.int({
|
|
104
|
+
min: 1,
|
|
105
|
+
max: 100
|
|
106
|
+
});
|
|
107
|
+
case 'company':
|
|
108
|
+
return faker.company.name();
|
|
109
|
+
default:
|
|
110
|
+
return undefined;
|
|
134
111
|
}
|
|
135
|
-
return undefined;
|
|
136
112
|
}
|
|
137
113
|
/**
|
|
138
114
|
* Generate value based on column type
|
|
139
115
|
*/ generateByType(column) {
|
|
140
|
-
const
|
|
141
|
-
switch(
|
|
142
|
-
// String types
|
|
143
|
-
case 'varchar':
|
|
144
|
-
case 'character varying':
|
|
145
|
-
case 'text':
|
|
116
|
+
const category = detectTypeCategory(column.type);
|
|
117
|
+
switch(category){
|
|
146
118
|
case 'string':
|
|
147
119
|
return this.generateString(column);
|
|
148
|
-
// Number types
|
|
149
|
-
case 'int':
|
|
150
120
|
case 'integer':
|
|
151
|
-
case 'smallint':
|
|
152
|
-
case 'bigint':
|
|
153
121
|
return faker.number.int({
|
|
154
122
|
min: 1,
|
|
155
123
|
max: 1000
|
|
156
124
|
});
|
|
157
125
|
case 'decimal':
|
|
158
|
-
case 'numeric':
|
|
159
|
-
case 'float':
|
|
160
|
-
case 'double':
|
|
161
|
-
case 'real':
|
|
162
126
|
return faker.number.float({
|
|
163
127
|
min: 0,
|
|
164
128
|
max: 10000,
|
|
165
129
|
fractionDigits: column.scale || 2
|
|
166
130
|
});
|
|
167
|
-
// Boolean
|
|
168
131
|
case 'boolean':
|
|
169
|
-
case 'bool':
|
|
170
132
|
return faker.datatype.boolean();
|
|
171
|
-
// Date/Time
|
|
172
133
|
case 'date':
|
|
173
|
-
return faker.date.recent({
|
|
174
|
-
days: 30
|
|
175
|
-
});
|
|
176
134
|
case 'timestamp':
|
|
177
|
-
case 'datetime':
|
|
178
135
|
return faker.date.recent({
|
|
179
136
|
days: 30
|
|
180
137
|
});
|
|
181
138
|
case 'time':
|
|
182
139
|
return faker.date.recent().toTimeString().split(' ')[0];
|
|
183
|
-
// UUID
|
|
184
140
|
case 'uuid':
|
|
185
141
|
return faker.string.uuid();
|
|
186
|
-
// JSON
|
|
187
142
|
case 'json':
|
|
188
|
-
case 'jsonb':
|
|
189
143
|
return {
|
|
190
144
|
key1: faker.lorem.word(),
|
|
191
145
|
key2: faker.number.int({
|
|
@@ -193,13 +147,11 @@ import { faker } from '@faker-js/faker';
|
|
|
193
147
|
max: 100
|
|
194
148
|
})
|
|
195
149
|
};
|
|
196
|
-
// Array
|
|
197
150
|
case 'array':
|
|
198
151
|
return [
|
|
199
152
|
faker.lorem.word(),
|
|
200
153
|
faker.lorem.word()
|
|
201
154
|
];
|
|
202
|
-
// Default
|
|
203
155
|
default:
|
|
204
156
|
return faker.lorem.word();
|
|
205
157
|
}
|
|
@@ -208,38 +160,31 @@ import { faker } from '@faker-js/faker';
|
|
|
208
160
|
* Generate string value respecting length constraints
|
|
209
161
|
*/ generateString(column) {
|
|
210
162
|
const maxLength = typeof column.length === 'number' ? column.length : 255;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
163
|
+
const category = getStringLengthCategory(column.length);
|
|
164
|
+
switch(category){
|
|
165
|
+
case 'word':
|
|
166
|
+
return faker.lorem.word().substring(0, maxLength);
|
|
167
|
+
case 'sentence':
|
|
168
|
+
return faker.lorem.sentence().substring(0, maxLength);
|
|
169
|
+
case 'paragraph':
|
|
170
|
+
return faker.lorem.paragraph().substring(0, maxLength);
|
|
217
171
|
}
|
|
218
172
|
}
|
|
219
173
|
/**
|
|
220
174
|
* Generate related entity ID (for foreign keys)
|
|
221
|
-
* @param relatedEntities Array of entities to pick from
|
|
222
175
|
*/ generateRelationId(relatedEntities) {
|
|
223
|
-
if (relatedEntities.length === 0)
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
176
|
+
if (relatedEntities.length === 0) return null;
|
|
226
177
|
return faker.helpers.arrayElement(relatedEntities).id;
|
|
227
178
|
}
|
|
228
179
|
/**
|
|
229
180
|
* Generate multiple related entity IDs (for many-to-many)
|
|
230
|
-
* @param relatedEntities Array of entities to pick from
|
|
231
|
-
* @param min Minimum number of relations
|
|
232
|
-
* @param max Maximum number of relations
|
|
233
181
|
*/ generateRelationIds(relatedEntities, min = 1, max = 3) {
|
|
234
|
-
if (relatedEntities.length === 0)
|
|
235
|
-
return [];
|
|
236
|
-
}
|
|
182
|
+
if (relatedEntities.length === 0) return [];
|
|
237
183
|
const count = faker.number.int({
|
|
238
184
|
min,
|
|
239
185
|
max: Math.min(max, relatedEntities.length)
|
|
240
186
|
});
|
|
241
|
-
|
|
242
|
-
return selected.map((e)=>e.id);
|
|
187
|
+
return faker.helpers.arrayElements(relatedEntities, count).map((e)=>e.id);
|
|
243
188
|
}
|
|
244
189
|
constructor(locale = 'en'){
|
|
245
190
|
faker.setDefaultRefDate(new Date());
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** System fields that should be skipped during generation */ export const SYSTEM_FIELDS = [
|
|
2
|
+
'id',
|
|
3
|
+
'createdAt',
|
|
4
|
+
'updatedAt',
|
|
5
|
+
'deletedAt',
|
|
6
|
+
'createdById',
|
|
7
|
+
'updatedById',
|
|
8
|
+
'deletedById'
|
|
9
|
+
];
|
|
10
|
+
/** Audit fields that return null */ export const AUDIT_FIELDS = [
|
|
11
|
+
'createdbyid',
|
|
12
|
+
'updatedbyid',
|
|
13
|
+
'deletedbyid'
|
|
14
|
+
];
|
|
15
|
+
/** Identity fields that are skipped */ export const IDENTITY_FIELDS = [
|
|
16
|
+
'id',
|
|
17
|
+
'createdat',
|
|
18
|
+
'updatedat',
|
|
19
|
+
'deletedat'
|
|
20
|
+
];
|
|
21
|
+
/** Boolean indicator keywords */ export const BOOLEAN_KEYWORDS = [
|
|
22
|
+
'verified',
|
|
23
|
+
'active',
|
|
24
|
+
'enabled',
|
|
25
|
+
'public',
|
|
26
|
+
'readonly',
|
|
27
|
+
'valid'
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Detect field pattern from column name
|
|
31
|
+
*/ export function detectFieldPattern(column) {
|
|
32
|
+
const nameLower = column.propertyName.toLowerCase();
|
|
33
|
+
const typeLower = column.type.toLowerCase();
|
|
34
|
+
// Identity fields (skip)
|
|
35
|
+
if (IDENTITY_FIELDS.includes(nameLower)) return 'skip';
|
|
36
|
+
// Audit fields (null)
|
|
37
|
+
if (AUDIT_FIELDS.includes(nameLower)) return 'null';
|
|
38
|
+
// Boolean fields with specific keywords
|
|
39
|
+
if ((typeLower === 'boolean' || typeLower === 'bool') && BOOLEAN_KEYWORDS.some((k)=>nameLower.includes(k))) {
|
|
40
|
+
return 'boolean';
|
|
41
|
+
}
|
|
42
|
+
// Token fields
|
|
43
|
+
if (nameLower.includes('token')) return 'token';
|
|
44
|
+
// Name fields
|
|
45
|
+
if (nameLower.includes('firstname')) return 'firstName';
|
|
46
|
+
if (nameLower.includes('lastname')) return 'lastName';
|
|
47
|
+
if (nameLower.includes('fullname') || nameLower === 'name') return 'fullName';
|
|
48
|
+
// Contact fields
|
|
49
|
+
if (nameLower.includes('email') && typeLower !== 'boolean') return 'email';
|
|
50
|
+
if (nameLower.includes('phone') || nameLower.includes('mobile')) return 'phone';
|
|
51
|
+
// Location fields
|
|
52
|
+
if (nameLower.includes('address')) return 'address';
|
|
53
|
+
if (nameLower.includes('street')) return 'street';
|
|
54
|
+
if (nameLower.includes('city')) return 'city';
|
|
55
|
+
if (nameLower.includes('state')) return 'state';
|
|
56
|
+
if (nameLower.includes('country')) return 'country';
|
|
57
|
+
if (nameLower.includes('zipcode') || nameLower.includes('postalcode')) return 'zipCode';
|
|
58
|
+
// URL/Web fields
|
|
59
|
+
if (nameLower.includes('url') || nameLower.includes('website')) return 'url';
|
|
60
|
+
if (nameLower.includes('domain')) return 'domain';
|
|
61
|
+
if (nameLower.includes('slug')) return 'slug';
|
|
62
|
+
// Text fields
|
|
63
|
+
if (nameLower.includes('description')) return 'description';
|
|
64
|
+
if (nameLower.includes('summary')) return 'summary';
|
|
65
|
+
if (nameLower.includes('content')) return 'content';
|
|
66
|
+
if (nameLower.includes('title')) return 'title';
|
|
67
|
+
// User fields
|
|
68
|
+
if (nameLower.includes('username')) return 'username';
|
|
69
|
+
if (nameLower.includes('password')) return 'password';
|
|
70
|
+
// Boolean status fields (fallback)
|
|
71
|
+
if (nameLower.includes('isactive') || nameLower.includes('isenabled') || nameLower.includes('ispublic') || nameLower.includes('isverified')) {
|
|
72
|
+
return 'boolean';
|
|
73
|
+
}
|
|
74
|
+
// Date fields
|
|
75
|
+
if (nameLower.includes('birthdate') || nameLower.includes('dateofbirth')) return 'birthdate';
|
|
76
|
+
if (nameLower.includes('expiresat') || nameLower.includes('expirydate')) return 'futureDate';
|
|
77
|
+
if (nameLower.includes('verifiedat')) return 'recentDateOrNull';
|
|
78
|
+
// Serial/Order fields
|
|
79
|
+
if (nameLower.includes('serial') || nameLower.includes('order')) return 'serial';
|
|
80
|
+
// Company
|
|
81
|
+
if (nameLower.includes('company') && !nameLower.includes('id')) return 'company';
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Detect column type category
|
|
86
|
+
*/ export function detectTypeCategory(type) {
|
|
87
|
+
const typeLower = type.toLowerCase();
|
|
88
|
+
if ([
|
|
89
|
+
'varchar',
|
|
90
|
+
'character varying',
|
|
91
|
+
'text',
|
|
92
|
+
'string'
|
|
93
|
+
].includes(typeLower)) return 'string';
|
|
94
|
+
if ([
|
|
95
|
+
'int',
|
|
96
|
+
'integer',
|
|
97
|
+
'smallint',
|
|
98
|
+
'bigint'
|
|
99
|
+
].includes(typeLower)) return 'integer';
|
|
100
|
+
if ([
|
|
101
|
+
'decimal',
|
|
102
|
+
'numeric',
|
|
103
|
+
'float',
|
|
104
|
+
'double',
|
|
105
|
+
'real'
|
|
106
|
+
].includes(typeLower)) return 'decimal';
|
|
107
|
+
if ([
|
|
108
|
+
'boolean',
|
|
109
|
+
'bool'
|
|
110
|
+
].includes(typeLower)) return 'boolean';
|
|
111
|
+
if (typeLower === 'date') return 'date';
|
|
112
|
+
if ([
|
|
113
|
+
'timestamp',
|
|
114
|
+
'datetime'
|
|
115
|
+
].includes(typeLower)) return 'timestamp';
|
|
116
|
+
if (typeLower === 'time') return 'time';
|
|
117
|
+
if (typeLower === 'uuid') return 'uuid';
|
|
118
|
+
if ([
|
|
119
|
+
'json',
|
|
120
|
+
'jsonb'
|
|
121
|
+
].includes(typeLower)) return 'json';
|
|
122
|
+
if (typeLower === 'array') return 'array';
|
|
123
|
+
return 'unknown';
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get string length category for faker generation
|
|
127
|
+
*/ export function getStringLengthCategory(length) {
|
|
128
|
+
const maxLength = typeof length === 'number' ? length : 255;
|
|
129
|
+
if (maxLength <= 50) return 'word';
|
|
130
|
+
if (maxLength <= 255) return 'sentence';
|
|
131
|
+
return 'paragraph';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if field is a system field
|
|
135
|
+
*/ export function isSystemField(fieldName) {
|
|
136
|
+
return SYSTEM_FIELDS.includes(fieldName);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get token max length respecting column constraints
|
|
140
|
+
*/ export function getTokenLength(column) {
|
|
141
|
+
const maxLength = typeof column.length === 'number' ? column.length : 64;
|
|
142
|
+
return Math.min(maxLength, 32);
|
|
143
|
+
}
|
package/fesm/seeders/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { BaseSeeder } from './base-seeder';
|
|
2
2
|
export { EntityReader, IEntityInfo, IColumnInfo, IRelationInfo } from './entity-reader';
|
|
3
3
|
export { DataGenerator } from './data-generator';
|
|
4
|
-
export { TemplateGenerator } from './template-generator';
|
|
5
4
|
export { SeedRunner, ISeedResult, ISeedOptions, ISeederLogger, defaultLogger } from './seed-runner';
|
|
6
5
|
export { seedConfig, ISeedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder, configureSeedConfig } from './seed-config';
|
|
6
|
+
export { SYSTEM_FIELDS, isSystemField, detectFieldPattern, detectTypeCategory } from './field-patterns';
|
|
7
7
|
export { runSeedCli } from './cli';
|
|
@@ -61,6 +61,12 @@ import { seedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder } from '.
|
|
|
61
61
|
*/ hasCustomSeeder(entityName) {
|
|
62
62
|
return this.customSeeders.has(entityName);
|
|
63
63
|
}
|
|
64
|
+
getSeeder(entityName, entity, dataSource, entityInfo, batchSize) {
|
|
65
|
+
if (this.customSeeders.has(entityName)) {
|
|
66
|
+
return this.customSeeders.get(entityName);
|
|
67
|
+
}
|
|
68
|
+
return new GenericSeeder(dataSource, entity, this.dataGenerator, entityInfo, batchSize);
|
|
69
|
+
}
|
|
64
70
|
/**
|
|
65
71
|
* Run seeds for all entities
|
|
66
72
|
* @param options Seeding options
|
|
@@ -125,13 +131,7 @@ import { seedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder } from '.
|
|
|
125
131
|
if (!entity) {
|
|
126
132
|
throw new Error(`Entity ${entityName} not found`);
|
|
127
133
|
}
|
|
128
|
-
|
|
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
|
-
}
|
|
134
|
+
const seeder = this.getSeeder(entityName, entity, queryRunner.manager.connection, entityInfo, options.batchSize);
|
|
135
135
|
// Dry run mode - preview without executing
|
|
136
136
|
if (options.dryRun) {
|
|
137
137
|
const count = options.count ?? getEntityCount(entityName);
|
|
@@ -203,13 +203,7 @@ import { seedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder } from '.
|
|
|
203
203
|
if (!entity) {
|
|
204
204
|
throw new Error(`Entity ${entityName} not found`);
|
|
205
205
|
}
|
|
206
|
-
|
|
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
|
-
}
|
|
206
|
+
const seeder = this.getSeeder(entityName, entity, this.dataSource, this.entityReader.getEntityInfo(entityName));
|
|
213
207
|
const countBefore = await seeder.count(true);
|
|
214
208
|
// Skip if already empty
|
|
215
209
|
if (countBefore === 0) {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ export declare class DataGenerator {
|
|
|
3
3
|
constructor(locale?: string);
|
|
4
4
|
generateValue(column: IColumnInfo): any;
|
|
5
5
|
generateEntity(columns: IColumnInfo[]): Record<string, any>;
|
|
6
|
-
private
|
|
6
|
+
private generateByPattern;
|
|
7
7
|
private generateByType;
|
|
8
8
|
private generateString;
|
|
9
9
|
generateRelationId<T extends {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IColumnInfo } from './entity-reader';
|
|
2
|
+
export declare const SYSTEM_FIELDS: string[];
|
|
3
|
+
export declare const AUDIT_FIELDS: string[];
|
|
4
|
+
export declare const IDENTITY_FIELDS: string[];
|
|
5
|
+
export declare const BOOLEAN_KEYWORDS: string[];
|
|
6
|
+
export type FieldPatternType = 'skip' | 'null' | 'boolean' | 'token' | 'firstName' | 'lastName' | 'fullName' | 'email' | 'phone' | 'address' | 'street' | 'city' | 'state' | 'country' | 'zipCode' | 'url' | 'domain' | 'slug' | 'description' | 'summary' | 'content' | 'title' | 'username' | 'password' | 'birthdate' | 'futureDate' | 'recentDateOrNull' | 'serial' | 'company';
|
|
7
|
+
export type ColumnTypeCategory = 'string' | 'integer' | 'decimal' | 'boolean' | 'date' | 'timestamp' | 'time' | 'uuid' | 'json' | 'array' | 'unknown';
|
|
8
|
+
export declare function detectFieldPattern(column: IColumnInfo): FieldPatternType | undefined;
|
|
9
|
+
export declare function detectTypeCategory(type: string): ColumnTypeCategory;
|
|
10
|
+
export declare function getStringLengthCategory(length: number | string | undefined): 'word' | 'sentence' | 'paragraph';
|
|
11
|
+
export declare function isSystemField(fieldName: string): boolean;
|
|
12
|
+
export declare function getTokenLength(column: IColumnInfo): number;
|
package/seeders/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { BaseSeeder } from './base-seeder';
|
|
2
2
|
export { EntityReader, IEntityInfo, IColumnInfo, IRelationInfo } from './entity-reader';
|
|
3
3
|
export { DataGenerator } from './data-generator';
|
|
4
|
-
export { TemplateGenerator } from './template-generator';
|
|
5
4
|
export { SeedRunner, ISeedResult, ISeedOptions, ISeederLogger, defaultLogger } from './seed-runner';
|
|
6
5
|
export { seedConfig, ISeedConfig, getEntityCount, shouldSkipEntity, getSeedingOrder, configureSeedConfig } from './seed-config';
|
|
6
|
+
export { SYSTEM_FIELDS, isSystemField, detectFieldPattern, detectTypeCategory } from './field-patterns';
|
|
7
7
|
export { runSeedCli } from './cli';
|
package/seeders/seed-runner.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export declare class SeedRunner {
|
|
|
34
34
|
registerCustomSeeder(entityName: string, seeder: BaseSeeder<any>): void;
|
|
35
35
|
unregisterCustomSeeder(entityName: string): void;
|
|
36
36
|
hasCustomSeeder(entityName: string): boolean;
|
|
37
|
+
private getSeeder;
|
|
37
38
|
runAll(options?: ISeedOptions): Promise<ISeedResult[]>;
|
|
38
39
|
runSingle(entityName: string, options?: ISeedOptions): Promise<ISeedResult>;
|
|
39
40
|
clearAll(hard?: boolean, continueOnError?: boolean): Promise<ISeedResult[]>;
|
package/cjs/docs/docs.setup.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "setupSwaggerDocs", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return setupSwaggerDocs;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _docsconfig = require("./docs.config");
|
|
12
|
-
function setupSwaggerDocs(app, ...modules) {
|
|
13
|
-
(0, _docsconfig.setupModuleSwaggerDocs)(app, modules);
|
|
14
|
-
}
|