@gadmin2n/cli 0.0.158 → 0.0.159
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/actions/prisma.action.js
CHANGED
|
@@ -83,7 +83,7 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
83
83
|
new shell.ShellString(result).toEnd('server/prisma/schema.prisma');
|
|
84
84
|
}
|
|
85
85
|
handle(inputs, options) {
|
|
86
|
-
var _a;
|
|
86
|
+
var _a, _b;
|
|
87
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
88
|
// 检查 prisma schema 配置是否存在
|
|
89
89
|
const hasPrismaConfig = shell.test('-e', 'config/schema.prisma') ||
|
|
@@ -94,6 +94,18 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
94
94
|
process.exit(-1);
|
|
95
95
|
}
|
|
96
96
|
const devMode = !!((_a = options.find((option) => option.name === 'dev')) === null || _a === void 0 ? void 0 : _a.value);
|
|
97
|
+
const verbose = !!((_b = options.find((option) => option.name === 'verbose')) === null || _b === void 0 ? void 0 : _b.value);
|
|
98
|
+
// 分发过程按类别记账,收尾统一打摘要 / --verbose 打完整清单
|
|
99
|
+
const stats = {
|
|
100
|
+
serverModulesIndex: [],
|
|
101
|
+
serverModulesNew: [],
|
|
102
|
+
serverModulesSkipped: [],
|
|
103
|
+
routesNew: [],
|
|
104
|
+
routesSkipped: [],
|
|
105
|
+
generated: [],
|
|
106
|
+
generatedUnchanged: [],
|
|
107
|
+
orphansRemoved: [], // web/src/generated/** 孤儿清理
|
|
108
|
+
};
|
|
97
109
|
// 构建合并的 schema(两种模式都需要重建 schema.prisma)
|
|
98
110
|
this.buildMergedSchema();
|
|
99
111
|
// Staging 目录:generator 全量写入到 node_modules/.cache/*,CLI 再增量分发。
|
|
@@ -145,7 +157,10 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
145
157
|
// 1.1 modules.index.ts —— 顶层入口
|
|
146
158
|
const modulesIndexSrc = (0, path_1.join)(SERVER_STAGING, 'modules.index.ts');
|
|
147
159
|
if (fs.existsSync(modulesIndexSrc)) {
|
|
148
|
-
|
|
160
|
+
const rel = 'server/src/generated/modules.index.ts';
|
|
161
|
+
if ((0, sync_fs_1.copyFileIfChanged)(modulesIndexSrc, rel)) {
|
|
162
|
+
stats.serverModulesIndex.push(rel);
|
|
163
|
+
}
|
|
149
164
|
}
|
|
150
165
|
// 1.2 逐 model 首次落地到 server/src/modules/{model}(跳过 form.validator,它归 web 阶段)
|
|
151
166
|
for (const modelName of stagingModels) {
|
|
@@ -155,10 +170,13 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
155
170
|
if (rel === validatorInStaging)
|
|
156
171
|
continue;
|
|
157
172
|
const dest = (0, path_1.join)('server/src/modules', modelName, rel);
|
|
158
|
-
if (fs.existsSync(dest))
|
|
173
|
+
if (fs.existsSync(dest)) {
|
|
174
|
+
stats.serverModulesSkipped.push(dest);
|
|
159
175
|
continue;
|
|
176
|
+
}
|
|
160
177
|
fs.mkdirSync((0, path_1.dirname)(dest), { recursive: true });
|
|
161
178
|
fs.copyFileSync((0, path_1.join)(modelStaging, rel), dest);
|
|
179
|
+
stats.serverModulesNew.push(dest);
|
|
162
180
|
}
|
|
163
181
|
}
|
|
164
182
|
}
|
|
@@ -174,10 +192,20 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
174
192
|
if (!fs.existsSync(destRoutes)) {
|
|
175
193
|
fs.mkdirSync((0, path_1.dirname)(destRoutes), { recursive: true });
|
|
176
194
|
fs.copyFileSync(src, destRoutes);
|
|
195
|
+
stats.routesNew.push(destRoutes);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
stats.routesSkipped.push(destRoutes);
|
|
177
199
|
}
|
|
178
200
|
}
|
|
179
201
|
else {
|
|
180
|
-
|
|
202
|
+
const dest = (0, path_1.join)('web/src/generated', rel);
|
|
203
|
+
if ((0, sync_fs_1.copyFileIfChanged)(src, dest)) {
|
|
204
|
+
stats.generated.push(dest);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
stats.generatedUnchanged.push(dest);
|
|
208
|
+
}
|
|
181
209
|
webKeep.add(rel);
|
|
182
210
|
}
|
|
183
211
|
}
|
|
@@ -185,7 +213,13 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
185
213
|
// 2.2 form.validator.ts(server generator 产出,需搬到 web/src/generated/props/{model}/)
|
|
186
214
|
for (const modelName of stagingModels) {
|
|
187
215
|
const validatorRel = `props/${modelName}/form.validator.ts`;
|
|
188
|
-
|
|
216
|
+
const dest = (0, path_1.join)('web/src/generated', validatorRel);
|
|
217
|
+
if ((0, sync_fs_1.copyFileIfChanged)((0, path_1.join)(SERVER_STAGING, modelName, 'dto', `${modelName}.form.validator.ts`), dest)) {
|
|
218
|
+
stats.generated.push(dest);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
stats.generatedUnchanged.push(dest);
|
|
222
|
+
}
|
|
189
223
|
webKeep.add(validatorRel);
|
|
190
224
|
}
|
|
191
225
|
// 2.3 Prisma / config 类型
|
|
@@ -195,19 +229,67 @@ class PrismaAction extends abstract_action_1.AbstractAction {
|
|
|
195
229
|
let prismaContent = fs.readFileSync(prismaSrc, 'utf8');
|
|
196
230
|
prismaContent = prismaContent.replace("import * as runtime from '@prisma/client/runtime/index';", 'declare const runtime : any');
|
|
197
231
|
prismaContent = prismaContent.replace(/bigint/g, 'number');
|
|
198
|
-
|
|
232
|
+
const prismaDest = (0, path_1.join)('web/src/generated', prismaRel);
|
|
233
|
+
if ((0, sync_fs_1.writeFileIfChanged)(prismaDest, prismaContent)) {
|
|
234
|
+
stats.generated.push(prismaDest);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
stats.generatedUnchanged.push(prismaDest);
|
|
238
|
+
}
|
|
199
239
|
webKeep.add(prismaRel);
|
|
200
240
|
const configRel = 'types/config.types.d.ts';
|
|
201
|
-
|
|
241
|
+
const configDest = (0, path_1.join)('web/src/generated', configRel);
|
|
242
|
+
if ((0, sync_fs_1.copyFileIfChanged)('config/.types.d.ts', configDest)) {
|
|
243
|
+
stats.generated.push(configDest);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
stats.generatedUnchanged.push(configDest);
|
|
247
|
+
}
|
|
202
248
|
webKeep.add(configRel);
|
|
203
249
|
// 2.4 孤儿清理:删除 web/src/generated 下所有本轮未产出的文件(例如被删除的 model)
|
|
204
|
-
(0, sync_fs_1.pruneOrphans)('web/src/generated', webKeep);
|
|
250
|
+
stats.orphansRemoved = (0, sync_fs_1.pruneOrphans)('web/src/generated', webKeep).map((r) => (0, path_1.join)('web/src/generated', r));
|
|
251
|
+
// 打印摘要 / 完整清单
|
|
252
|
+
this.printReport(stats, verbose);
|
|
205
253
|
// 分发全部完成后,若 server/package.json 定义了 postgadminGenerate,
|
|
206
254
|
// 触发它。项目侧可用来做 dev server 通知、缓存清理等自定义收尾。
|
|
207
255
|
this.runProjectPostHook();
|
|
208
256
|
process.exit(0);
|
|
209
257
|
});
|
|
210
258
|
}
|
|
259
|
+
printReport(stats, verbose) {
|
|
260
|
+
const serverWritten = stats.serverModulesIndex.length + stats.serverModulesNew.length;
|
|
261
|
+
const webWritten = stats.generated.length + stats.routesNew.length;
|
|
262
|
+
console.log('');
|
|
263
|
+
console.log(chalk.bold('gadmin2 g prisma:'));
|
|
264
|
+
console.log(` ${chalk.cyan('server')}: ${serverWritten} written` +
|
|
265
|
+
` (index=${stats.serverModulesIndex.length},` +
|
|
266
|
+
` modules-new=${stats.serverModulesNew.length}),` +
|
|
267
|
+
` ${stats.serverModulesSkipped.length} skipped`);
|
|
268
|
+
console.log(` ${chalk.cyan('web')}: ${webWritten} written` +
|
|
269
|
+
` (routes-new=${stats.routesNew.length},` +
|
|
270
|
+
` generated=${stats.generated.length}),` +
|
|
271
|
+
` ${stats.routesSkipped.length + stats.generatedUnchanged.length} unchanged,` +
|
|
272
|
+
` ${stats.orphansRemoved.length} orphan removed`);
|
|
273
|
+
if (!verbose) {
|
|
274
|
+
console.log(chalk.gray(' (use -v / --verbose to list files)'));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const printGroup = (title, list, color) => {
|
|
278
|
+
if (list.length === 0)
|
|
279
|
+
return;
|
|
280
|
+
console.log(chalk.bold(`\n ${title} (${list.length}):`));
|
|
281
|
+
for (const p of list)
|
|
282
|
+
console.log(' ' + color(p));
|
|
283
|
+
};
|
|
284
|
+
printGroup('server modules.index (diff-write)', stats.serverModulesIndex, chalk.green);
|
|
285
|
+
printGroup('server modules (new)', stats.serverModulesNew, chalk.green);
|
|
286
|
+
printGroup('server modules (skipped, exists)', stats.serverModulesSkipped, chalk.gray);
|
|
287
|
+
printGroup('web routes (new)', stats.routesNew, chalk.green);
|
|
288
|
+
printGroup('web routes (skipped, exists)', stats.routesSkipped, chalk.gray);
|
|
289
|
+
printGroup('web generated (written)', stats.generated, chalk.green);
|
|
290
|
+
printGroup('web generated (unchanged)', stats.generatedUnchanged, chalk.gray);
|
|
291
|
+
printGroup('web orphans removed', stats.orphansRemoved, chalk.red);
|
|
292
|
+
}
|
|
211
293
|
runProjectPostHook() {
|
|
212
294
|
var _a;
|
|
213
295
|
const pkgPath = 'server/package.json';
|
|
@@ -32,6 +32,7 @@ class GenerateCommand extends abstract_command_1.AbstractCommand {
|
|
|
32
32
|
return { value: false, passedAsInput: true };
|
|
33
33
|
})
|
|
34
34
|
.option('-c, --collection [collectionName]', 'Schematics collection to use.')
|
|
35
|
+
.option('-v, --verbose', 'Print each affected src/ file (prisma).')
|
|
35
36
|
.action((schematic, name, path, command) => __awaiter(this, void 0, void 0, function* () {
|
|
36
37
|
const options = [];
|
|
37
38
|
options.push({ name: 'dry-run', value: !!command.dryRun });
|
|
@@ -64,6 +65,7 @@ class GenerateCommand extends abstract_command_1.AbstractCommand {
|
|
|
64
65
|
keepInputNameFormat: true,
|
|
65
66
|
},
|
|
66
67
|
});
|
|
68
|
+
options.push({ name: 'verbose', value: !!command.verbose });
|
|
67
69
|
const inputs = [];
|
|
68
70
|
inputs.push({ name: 'schematic', value: schematic });
|
|
69
71
|
inputs.push({ name: 'name', value: name });
|
|
@@ -34,6 +34,10 @@ class GadminCollection extends abstract_collection_1.AbstractCollection {
|
|
|
34
34
|
const opts = [];
|
|
35
35
|
if (name.includes(':dev'))
|
|
36
36
|
opts.push({ name: 'dev', value: true });
|
|
37
|
+
const verbose = options.find((o) => o.name === 'verbose');
|
|
38
|
+
if (verbose && verbose.value) {
|
|
39
|
+
opts.push({ name: 'verbose', value: true });
|
|
40
|
+
}
|
|
37
41
|
return yield prisma.handle([], opts);
|
|
38
42
|
}
|
|
39
43
|
const schematic = this.validate(name);
|
package/lib/utils/sync-fs.d.ts
CHANGED
|
@@ -37,5 +37,6 @@ export declare function syncDir(srcDir: string, destDir: string): {
|
|
|
37
37
|
/**
|
|
38
38
|
* 删除 destDir 下所有不在 keepFiles 里的文件(以及随之空掉的父目录)。
|
|
39
39
|
* 用于「本轮 model 目录被删」的孤儿清理场景。
|
|
40
|
+
* @returns 被删除的文件相对路径列表(相对 destDir)
|
|
40
41
|
*/
|
|
41
|
-
export declare function pruneOrphans(destDir: string, keepFiles: Set<string>):
|
|
42
|
+
export declare function pruneOrphans(destDir: string, keepFiles: Set<string>): string[];
|
package/lib/utils/sync-fs.js
CHANGED
|
@@ -115,15 +115,16 @@ exports.syncDir = syncDir;
|
|
|
115
115
|
/**
|
|
116
116
|
* 删除 destDir 下所有不在 keepFiles 里的文件(以及随之空掉的父目录)。
|
|
117
117
|
* 用于「本轮 model 目录被删」的孤儿清理场景。
|
|
118
|
+
* @returns 被删除的文件相对路径列表(相对 destDir)
|
|
118
119
|
*/
|
|
119
120
|
function pruneOrphans(destDir, keepFiles) {
|
|
120
|
-
|
|
121
|
+
const removed = [];
|
|
121
122
|
for (const rel of listFilesRecursive(destDir)) {
|
|
122
123
|
if (!keepFiles.has(rel)) {
|
|
123
124
|
removeFileAndPruneEmptyDirs(path.join(destDir, rel), destDir);
|
|
124
|
-
|
|
125
|
+
removed.push(rel);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
|
-
return
|
|
128
|
+
return removed;
|
|
128
129
|
}
|
|
129
130
|
exports.pruneOrphans = pruneOrphans;
|