@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.
@@ -3,5 +3,6 @@ import { AbstractAction } from './abstract.action';
3
3
  export declare class PrismaAction extends AbstractAction {
4
4
  private buildMergedSchema;
5
5
  handle(inputs: Input[], options: Input[]): Promise<void>;
6
+ private printReport;
6
7
  private runProjectPostHook;
7
8
  }
@@ -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
- (0, sync_fs_1.copyFileIfChanged)(modulesIndexSrc, 'server/src/generated/modules.index.ts');
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
- (0, sync_fs_1.copyFileIfChanged)(src, (0, path_1.join)('web/src/generated', rel));
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
- (0, sync_fs_1.copyFileIfChanged)((0, path_1.join)(SERVER_STAGING, modelName, 'dto', `${modelName}.form.validator.ts`), (0, path_1.join)('web/src/generated', validatorRel));
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
- (0, sync_fs_1.writeFileIfChanged)((0, path_1.join)('web/src/generated', prismaRel), prismaContent);
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
- (0, sync_fs_1.copyFileIfChanged)('config/.types.d.ts', (0, path_1.join)('web/src/generated', configRel));
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);
@@ -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>): number;
42
+ export declare function pruneOrphans(destDir: string, keepFiles: Set<string>): string[];
@@ -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
- let deleted = 0;
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
- deleted++;
125
+ removed.push(rel);
125
126
  }
126
127
  }
127
- return deleted;
128
+ return removed;
128
129
  }
129
130
  exports.pruneOrphans = pruneOrphans;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gadmin2n/cli",
3
- "version": "0.0.158",
3
+ "version": "0.0.159",
4
4
  "description": "Gadmin - modern, fast, powerful node.js web framework (@cli)",
5
5
  "publishConfig": {
6
6
  "access": "public"