speedrun-cli 2.7.9 ā 2.7.15
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/CHANGELOG.md +45 -29
- package/README.md +128 -491
- package/package.json +1 -1
- package/src/fieldManager.js +338 -191
- package/src/index.js +22 -13
- package/src/moduleGenerator.js +230 -38
- package/src/postSetup.js +4 -4
package/package.json
CHANGED
package/src/fieldManager.js
CHANGED
|
@@ -1,192 +1,339 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive Field Manager for existing modules
|
|
3
|
-
* @module fieldManager
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const inquirer = require('inquirer');
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Field Manager for existing modules
|
|
3
|
+
* @module fieldManager
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const inquirer = require('inquirer');
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const { detectOrm, getOrmFieldChoices, regenerateModuleComponents, toKebabCase } = require('./moduleGenerator');
|
|
12
|
+
const { detectPackageManager, getRunPrefix } = require('./utils');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Map a class-validator decorator name to the best ORM-native type for the given ORM.
|
|
16
|
+
* Used when round-tripping field types from the DTO file back into the field editor.
|
|
17
|
+
*/
|
|
18
|
+
function inferOrmTypeFromValidator(decoratorName, orm) {
|
|
19
|
+
switch (decoratorName) {
|
|
20
|
+
case 'IsInt':
|
|
21
|
+
return orm === 'prisma' ? 'Int' : orm === 'mongoose' ? 'Number' : 'int';
|
|
22
|
+
case 'IsNumber':
|
|
23
|
+
if (orm === 'prisma') return 'Float';
|
|
24
|
+
if (orm === 'typeorm') return 'decimal';
|
|
25
|
+
if (orm === 'drizzle') return 'numeric';
|
|
26
|
+
return 'Number'; // mongoose
|
|
27
|
+
case 'IsBoolean':
|
|
28
|
+
return orm === 'prisma' || orm === 'mongoose' ? 'Boolean' : 'boolean';
|
|
29
|
+
case 'IsDate':
|
|
30
|
+
if (orm === 'prisma') return 'DateTime';
|
|
31
|
+
if (orm === 'mongoose') return 'Date';
|
|
32
|
+
return 'timestamp'; // typeorm / drizzle
|
|
33
|
+
case 'IsObject':
|
|
34
|
+
return orm === 'prisma' ? 'Json' : orm === 'mongoose' ? 'Object' : 'json';
|
|
35
|
+
case 'IsArray':
|
|
36
|
+
return orm === 'mongoose' ? 'Array' : orm === 'prisma' ? 'Json' : 'json';
|
|
37
|
+
case 'IsString':
|
|
38
|
+
default:
|
|
39
|
+
return orm === 'prisma' || orm === 'mongoose' ? 'String' : 'varchar';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Helper to parse existing fields from the create DTO file (most accurate source)
|
|
44
|
+
async function parseExistingFields(moduleDir, kebabName, orm = 'prisma') {
|
|
45
|
+
// Prefer create DTO (has validators + real field types); fall back to response DTO
|
|
46
|
+
const createDtoPath = path.join(moduleDir, 'dto', `create-${kebabName}.dto.ts`);
|
|
47
|
+
const responseDtoPath = path.join(moduleDir, 'dto', `${kebabName}.dto.ts`);
|
|
48
|
+
|
|
49
|
+
const targetPath = (await fs.pathExists(createDtoPath)) ? createDtoPath : responseDtoPath;
|
|
50
|
+
if (!(await fs.pathExists(targetPath))) return [];
|
|
51
|
+
|
|
52
|
+
const content = await fs.readFile(targetPath, 'utf8');
|
|
53
|
+
const fields = [];
|
|
54
|
+
|
|
55
|
+
// System / PK / FK fields to exclude from editing
|
|
56
|
+
const IGNORED_EXACT = new Set(['id', 'status', 'createdAt', 'updatedAt', 'deletedAt']);
|
|
57
|
+
|
|
58
|
+
// Split into per-property blocks by splitting at each decorator line or property line
|
|
59
|
+
// Strategy: iterate line-by-line, collect decorator context then resolve property
|
|
60
|
+
const lines = content.split('\n');
|
|
61
|
+
let pendingDecorators = [];
|
|
62
|
+
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
const trimmed = line.trim();
|
|
65
|
+
|
|
66
|
+
// Collect validator decorator names (e.g. @IsString(), @IsInt())
|
|
67
|
+
const decMatch = trimmed.match(/^@(Is[A-Z][a-zA-Z]+)\(/);
|
|
68
|
+
if (decMatch) {
|
|
69
|
+
pendingDecorators.push(decMatch[1]);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Reset decorator context on non-decorator, non-property lines
|
|
74
|
+
if (trimmed.startsWith('@') || trimmed === '' || trimmed.startsWith('import') || trimmed.startsWith('export') || trimmed.startsWith('//')) {
|
|
75
|
+
if (!trimmed.match(/^([a-zA-Z0-9_]+)\??\s*:/)) {
|
|
76
|
+
pendingDecorators = [];
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Match property line: fieldName?: tsType;
|
|
82
|
+
const propMatch = trimmed.match(/^([a-zA-Z0-9_]+)(\?)?\s*:\s*([a-zA-Z_][\w\[\]]*)\s*;/);
|
|
83
|
+
if (propMatch) {
|
|
84
|
+
const [, name, optional, tsType] = propMatch;
|
|
85
|
+
|
|
86
|
+
// Skip system fields and FK / custom PK patterns
|
|
87
|
+
if (
|
|
88
|
+
IGNORED_EXACT.has(name) ||
|
|
89
|
+
/_id$/i.test(name) ||
|
|
90
|
+
/Id$/.test(name)
|
|
91
|
+
) {
|
|
92
|
+
pendingDecorators = [];
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Determine ORM type from validator decorators (most accurate) or TS type fallback
|
|
97
|
+
let ormType;
|
|
98
|
+
const validatorDec = pendingDecorators.find((d) => d.startsWith('Is'));
|
|
99
|
+
if (validatorDec) {
|
|
100
|
+
ormType = inferOrmTypeFromValidator(validatorDec, orm);
|
|
101
|
+
} else {
|
|
102
|
+
// TS-type fallback mapping
|
|
103
|
+
if (tsType === 'number') ormType = orm === 'prisma' ? 'Float' : orm === 'mongoose' ? 'Number' : 'decimal';
|
|
104
|
+
else if (tsType === 'boolean') ormType = orm === 'prisma' || orm === 'mongoose' ? 'Boolean' : 'boolean';
|
|
105
|
+
else if (tsType === 'Date') ormType = orm === 'prisma' ? 'DateTime' : orm === 'mongoose' ? 'Date' : 'timestamp';
|
|
106
|
+
else if (tsType === 'object') ormType = orm === 'prisma' ? 'Json' : orm === 'mongoose' ? 'Object' : 'json';
|
|
107
|
+
else ormType = orm === 'prisma' || orm === 'mongoose' ? 'String' : 'varchar';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fields.push({
|
|
111
|
+
name,
|
|
112
|
+
type: ormType,
|
|
113
|
+
isOptional: !!optional,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
pendingDecorators = [];
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
pendingDecorators = [];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return fields;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Executes ORM-specific database migration / schema sync
|
|
129
|
+
*/
|
|
130
|
+
async function runDatabaseMigration(targetDir, orm, packageManager) {
|
|
131
|
+
const pmPrefix = getRunPrefix(packageManager);
|
|
132
|
+
console.log(chalk.yellow(`\nā” Running database migration for ORM: ${chalk.bold(orm)}...\n`));
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
if (orm === 'prisma') {
|
|
136
|
+
execSync('npx prisma db push', { cwd: targetDir, stdio: 'inherit' });
|
|
137
|
+
} else if (orm === 'typeorm') {
|
|
138
|
+
execSync(`${pmPrefix} schema:sync`, { cwd: targetDir, stdio: 'inherit' });
|
|
139
|
+
} else if (orm === 'drizzle') {
|
|
140
|
+
execSync(`${pmPrefix} db:push`, { cwd: targetDir, stdio: 'inherit' });
|
|
141
|
+
} else if (orm === 'mongoose') {
|
|
142
|
+
console.log(chalk.green(' ā Mongoose schemas update dynamically on application startup.'));
|
|
143
|
+
}
|
|
144
|
+
console.log(chalk.green('\n ā Database migration complete!\n'));
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(chalk.red(`\n ā Database migration failed: ${error.message}\n`));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Executes ORM-specific database seed
|
|
152
|
+
*/
|
|
153
|
+
async function runDatabaseSeed(targetDir, orm, packageManager) {
|
|
154
|
+
const pmPrefix = getRunPrefix(packageManager);
|
|
155
|
+
console.log(chalk.yellow(`\nš± Seeding database for ORM: ${chalk.bold(orm)}...\n`));
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
if (orm === 'prisma') {
|
|
159
|
+
execSync(`${pmPrefix} prisma:seed`, { cwd: targetDir, stdio: 'inherit' });
|
|
160
|
+
} else if (orm === 'typeorm') {
|
|
161
|
+
execSync(`${pmPrefix} seed`, { cwd: targetDir, stdio: 'inherit' });
|
|
162
|
+
} else if (orm === 'mongoose' || orm === 'drizzle') {
|
|
163
|
+
execSync(`${pmPrefix} db:seed`, { cwd: targetDir, stdio: 'inherit' });
|
|
164
|
+
}
|
|
165
|
+
console.log(chalk.green('\n ā Database seed complete!\n'));
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(chalk.red(`\n ā Database seed failed: ${error.message}\n`));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Main Interactive Field Manager Entry Point
|
|
173
|
+
*/
|
|
174
|
+
async function manageFields(providedModuleName, targetDir = process.cwd()) {
|
|
175
|
+
try {
|
|
176
|
+
const orm = await detectOrm(targetDir);
|
|
177
|
+
const ormTypeChoices = getOrmFieldChoices(orm);
|
|
178
|
+
const pm = detectPackageManager();
|
|
179
|
+
|
|
180
|
+
let moduleName = providedModuleName;
|
|
181
|
+
|
|
182
|
+
if (!moduleName) {
|
|
183
|
+
const nameAnswer = await inquirer.prompt([{
|
|
184
|
+
type: 'input',
|
|
185
|
+
name: 'moduleName',
|
|
186
|
+
message: 'Which module do you want to manage fields for? (e.g., orders, products)',
|
|
187
|
+
validate: (input) => (input && input.trim() ? true : 'Module name is required'),
|
|
188
|
+
}]);
|
|
189
|
+
moduleName = nameAnswer.moduleName.trim();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const kebabName = toKebabCase(moduleName);
|
|
193
|
+
const moduleDir = path.join(targetDir, 'src', 'modules', kebabName);
|
|
194
|
+
|
|
195
|
+
if (!(await fs.pathExists(moduleDir))) {
|
|
196
|
+
console.error(chalk.red(`\nā Module "${kebabName}" not found at src/modules/${kebabName}`));
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Load existing fields (pass orm so type inference produces ORM-native types)
|
|
201
|
+
let fields = await parseExistingFields(moduleDir, kebabName, orm);
|
|
202
|
+
console.log(chalk.cyan(`\nš¦ Managing fields for module: ${chalk.bold(kebabName)} (Detected ORM: ${orm})`));
|
|
203
|
+
|
|
204
|
+
let managing = true;
|
|
205
|
+
|
|
206
|
+
const promptSingleField = async (initialValues = {}) => {
|
|
207
|
+
return await inquirer.prompt([
|
|
208
|
+
{
|
|
209
|
+
type: 'input',
|
|
210
|
+
name: 'fieldName',
|
|
211
|
+
message: 'Enter field name:',
|
|
212
|
+
default: initialValues.name,
|
|
213
|
+
validate: (input) => {
|
|
214
|
+
if (!input || !input.trim()) return 'Field name is required';
|
|
215
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(input.trim())) {
|
|
216
|
+
return 'Field name must be a valid identifier';
|
|
217
|
+
}
|
|
218
|
+
return true;
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
type: 'list',
|
|
223
|
+
name: 'fieldType',
|
|
224
|
+
message: (answers) => `Select field type for '${answers.fieldName}':`,
|
|
225
|
+
choices: ormTypeChoices,
|
|
226
|
+
default: initialValues.type && ormTypeChoices.includes(initialValues.type) ? initialValues.type : ormTypeChoices[0],
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
type: 'confirm',
|
|
230
|
+
name: 'isOptional',
|
|
231
|
+
message: (answers) => `Is '${answers.fieldName}' optional?`,
|
|
232
|
+
default: initialValues.isOptional !== undefined ? initialValues.isOptional : false,
|
|
233
|
+
},
|
|
234
|
+
]);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
while (managing) {
|
|
238
|
+
console.log(
|
|
239
|
+
chalk.gray(`\nCurrent Fields (${fields.length}): `) +
|
|
240
|
+
(fields.length > 0
|
|
241
|
+
? fields.map(f => chalk.yellow(`${f.name} (${f.type}${f.isOptional ? '?' : ''})`)).join(', ')
|
|
242
|
+
: chalk.gray('None'))
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
const { action } = await inquirer.prompt([{
|
|
246
|
+
type: 'list',
|
|
247
|
+
name: 'action',
|
|
248
|
+
message: 'What do you want to do?',
|
|
249
|
+
choices: [
|
|
250
|
+
{ name: 'ā Add new field', value: 'add' },
|
|
251
|
+
{ name: 'āļø Edit an existing field', value: 'edit' },
|
|
252
|
+
{ name: 'šļø Delete a field', value: 'delete' },
|
|
253
|
+
{ name: 'š¾ Save changes & update files', value: 'save' },
|
|
254
|
+
{ name: 'ā” Run database migration / schema sync', value: 'migrate' },
|
|
255
|
+
{ name: 'š± Seed database table', value: 'seed' },
|
|
256
|
+
{ name: 'ā Cancel / Exit', value: 'cancel' },
|
|
257
|
+
],
|
|
258
|
+
}]);
|
|
259
|
+
|
|
260
|
+
if (action === 'add') {
|
|
261
|
+
const newField = await promptSingleField();
|
|
262
|
+
fields.push({
|
|
263
|
+
name: newField.fieldName.trim(),
|
|
264
|
+
type: newField.fieldType,
|
|
265
|
+
isOptional: newField.isOptional,
|
|
266
|
+
});
|
|
267
|
+
} else if (action === 'edit') {
|
|
268
|
+
if (fields.length === 0) {
|
|
269
|
+
console.log(chalk.yellow('ā ļø No fields to edit.'));
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const { fieldToEditIndex } = await inquirer.prompt([{
|
|
274
|
+
type: 'list',
|
|
275
|
+
name: 'fieldToEditIndex',
|
|
276
|
+
message: 'Select field to edit:',
|
|
277
|
+
choices: fields.map((f, index) => ({
|
|
278
|
+
name: `${f.name} (${f.type}${f.isOptional ? '?' : ''})`,
|
|
279
|
+
value: index,
|
|
280
|
+
})),
|
|
281
|
+
}]);
|
|
282
|
+
|
|
283
|
+
const editedField = await promptSingleField(fields[fieldToEditIndex]);
|
|
284
|
+
fields[fieldToEditIndex] = {
|
|
285
|
+
name: editedField.fieldName.trim(),
|
|
286
|
+
type: editedField.fieldType,
|
|
287
|
+
isOptional: editedField.isOptional,
|
|
288
|
+
};
|
|
289
|
+
console.log(chalk.green(`ā Field updated.`));
|
|
290
|
+
} else if (action === 'delete') {
|
|
291
|
+
if (fields.length === 0) {
|
|
292
|
+
console.log(chalk.yellow('ā ļø No fields to delete.'));
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const { fieldToDeleteIndex } = await inquirer.prompt([{
|
|
297
|
+
type: 'list',
|
|
298
|
+
name: 'fieldToDeleteIndex',
|
|
299
|
+
message: 'Select field to delete:',
|
|
300
|
+
choices: fields.map((f, index) => ({
|
|
301
|
+
name: `${f.name} (${f.type}${f.isOptional ? '?' : ''})`,
|
|
302
|
+
value: index,
|
|
303
|
+
})),
|
|
304
|
+
}]);
|
|
305
|
+
|
|
306
|
+
const deletedName = fields[fieldToDeleteIndex].name;
|
|
307
|
+
fields.splice(fieldToDeleteIndex, 1);
|
|
308
|
+
console.log(chalk.red(`šļø Field '${deletedName}' removed.`));
|
|
309
|
+
} else if (action === 'save') {
|
|
310
|
+
await regenerateModuleComponents(moduleName, fields, targetDir);
|
|
311
|
+
console.log(chalk.green(`\nā
Successfully updated fields for module "${kebabName}"!`));
|
|
312
|
+
managing = false; // exit loop after successful save
|
|
313
|
+
|
|
314
|
+
const { runDbNow } = await inquirer.prompt([{
|
|
315
|
+
type: 'confirm',
|
|
316
|
+
name: 'runDbNow',
|
|
317
|
+
message: 'Run database migration & seed now?',
|
|
318
|
+
default: false,
|
|
319
|
+
}]);
|
|
320
|
+
|
|
321
|
+
if (runDbNow) {
|
|
322
|
+
await runDatabaseMigration(targetDir, orm, pm);
|
|
323
|
+
await runDatabaseSeed(targetDir, orm, pm);
|
|
324
|
+
}
|
|
325
|
+
} else if (action === 'migrate') {
|
|
326
|
+
await runDatabaseMigration(targetDir, orm, pm);
|
|
327
|
+
} else if (action === 'seed') {
|
|
328
|
+
await runDatabaseSeed(targetDir, orm, pm);
|
|
329
|
+
} else if (action === 'cancel') {
|
|
330
|
+
console.log(chalk.gray('Exited field manager.'));
|
|
331
|
+
managing = false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} catch (error) {
|
|
335
|
+
console.error(chalk.red('\nā Field management failed:'), error.message);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
192
339
|
module.exports = { manageFields };
|
package/src/index.js
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module exports for CLI source files
|
|
3
|
-
* @module src
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Module exports for CLI source files
|
|
3
|
+
* @module src
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const constants = require('./constants');
|
|
7
|
+
const utils = require('./utils');
|
|
8
|
+
const prompts = require('./prompts');
|
|
9
|
+
const generator = require('./generator');
|
|
10
|
+
const postSetup = require('./postSetup');
|
|
11
|
+
const moduleGenerator = require('./moduleGenerator');
|
|
12
|
+
const fieldManager = require('./fieldManager');
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
...constants,
|
|
16
|
+
...utils,
|
|
17
|
+
...prompts,
|
|
18
|
+
...generator,
|
|
19
|
+
...postSetup,
|
|
20
|
+
...moduleGenerator,
|
|
21
|
+
...fieldManager,
|
|
22
|
+
};
|