@deepstorm/cli 0.10.1 → 0.11.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/dist/cli.js CHANGED
@@ -1187,13 +1187,13 @@ var require_ast = __commonJS({
1187
1187
  helperExpression: function helperExpression(node) {
1188
1188
  return node.type === "SubExpression" || (node.type === "MustacheStatement" || node.type === "BlockStatement") && !!(node.params && node.params.length || node.hash);
1189
1189
  },
1190
- scopedId: function scopedId(path24) {
1191
- return /^\.|this\b/.test(path24.original);
1190
+ scopedId: function scopedId(path26) {
1191
+ return /^\.|this\b/.test(path26.original);
1192
1192
  },
1193
1193
  // an ID is simple if it only has one part, and that part is not
1194
1194
  // `..` or `this`.
1195
- simpleId: function simpleId(path24) {
1196
- return path24.parts.length === 1 && !AST.helpers.scopedId(path24) && !path24.depth;
1195
+ simpleId: function simpleId(path26) {
1196
+ return path26.parts.length === 1 && !AST.helpers.scopedId(path26) && !path26.depth;
1197
1197
  }
1198
1198
  }
1199
1199
  };
@@ -2263,12 +2263,12 @@ var require_helpers2 = __commonJS({
2263
2263
  loc
2264
2264
  };
2265
2265
  }
2266
- function prepareMustache(path24, params, hash, open, strip, locInfo) {
2266
+ function prepareMustache(path26, params, hash, open, strip, locInfo) {
2267
2267
  var escapeFlag = open.charAt(3) || open.charAt(2), escaped = escapeFlag !== "{" && escapeFlag !== "&";
2268
2268
  var decorator = /\*/.test(open);
2269
2269
  return {
2270
2270
  type: decorator ? "Decorator" : "MustacheStatement",
2271
- path: path24,
2271
+ path: path26,
2272
2272
  params,
2273
2273
  hash,
2274
2274
  escaped,
@@ -2586,9 +2586,9 @@ var require_compiler = __commonJS({
2586
2586
  },
2587
2587
  DecoratorBlock: function DecoratorBlock(decorator) {
2588
2588
  var program2 = decorator.program && this.compileProgram(decorator.program);
2589
- var params = this.setupFullMustacheParams(decorator, program2, void 0), path24 = decorator.path;
2589
+ var params = this.setupFullMustacheParams(decorator, program2, void 0), path26 = decorator.path;
2590
2590
  this.useDecorators = true;
2591
- this.opcode("registerDecorator", params.length, path24.original);
2591
+ this.opcode("registerDecorator", params.length, path26.original);
2592
2592
  },
2593
2593
  PartialStatement: function PartialStatement(partial) {
2594
2594
  this.usePartial = true;
@@ -2652,46 +2652,46 @@ var require_compiler = __commonJS({
2652
2652
  }
2653
2653
  },
2654
2654
  ambiguousSexpr: function ambiguousSexpr(sexpr, program2, inverse) {
2655
- var path24 = sexpr.path, name = path24.parts[0], isBlock = program2 != null || inverse != null;
2656
- this.opcode("getContext", path24.depth);
2655
+ var path26 = sexpr.path, name = path26.parts[0], isBlock = program2 != null || inverse != null;
2656
+ this.opcode("getContext", path26.depth);
2657
2657
  this.opcode("pushProgram", program2);
2658
2658
  this.opcode("pushProgram", inverse);
2659
- path24.strict = true;
2660
- this.accept(path24);
2659
+ path26.strict = true;
2660
+ this.accept(path26);
2661
2661
  this.opcode("invokeAmbiguous", name, isBlock);
2662
2662
  },
2663
2663
  simpleSexpr: function simpleSexpr(sexpr) {
2664
- var path24 = sexpr.path;
2665
- path24.strict = true;
2666
- this.accept(path24);
2664
+ var path26 = sexpr.path;
2665
+ path26.strict = true;
2666
+ this.accept(path26);
2667
2667
  this.opcode("resolvePossibleLambda");
2668
2668
  },
2669
2669
  helperSexpr: function helperSexpr(sexpr, program2, inverse) {
2670
- var params = this.setupFullMustacheParams(sexpr, program2, inverse), path24 = sexpr.path, name = path24.parts[0];
2670
+ var params = this.setupFullMustacheParams(sexpr, program2, inverse), path26 = sexpr.path, name = path26.parts[0];
2671
2671
  if (this.options.knownHelpers[name]) {
2672
2672
  this.opcode("invokeKnownHelper", params.length, name);
2673
2673
  } else if (this.options.knownHelpersOnly) {
2674
2674
  throw new _exception2["default"]("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
2675
2675
  } else {
2676
- path24.strict = true;
2677
- path24.falsy = true;
2678
- this.accept(path24);
2679
- this.opcode("invokeHelper", params.length, path24.original, _ast2["default"].helpers.simpleId(path24));
2676
+ path26.strict = true;
2677
+ path26.falsy = true;
2678
+ this.accept(path26);
2679
+ this.opcode("invokeHelper", params.length, path26.original, _ast2["default"].helpers.simpleId(path26));
2680
2680
  }
2681
2681
  },
2682
- PathExpression: function PathExpression(path24) {
2683
- this.addDepth(path24.depth);
2684
- this.opcode("getContext", path24.depth);
2685
- var name = path24.parts[0], scoped = _ast2["default"].helpers.scopedId(path24), blockParamId = !path24.depth && !scoped && this.blockParamIndex(name);
2682
+ PathExpression: function PathExpression(path26) {
2683
+ this.addDepth(path26.depth);
2684
+ this.opcode("getContext", path26.depth);
2685
+ var name = path26.parts[0], scoped = _ast2["default"].helpers.scopedId(path26), blockParamId = !path26.depth && !scoped && this.blockParamIndex(name);
2686
2686
  if (blockParamId) {
2687
- this.opcode("lookupBlockParam", blockParamId, path24.parts);
2687
+ this.opcode("lookupBlockParam", blockParamId, path26.parts);
2688
2688
  } else if (!name) {
2689
2689
  this.opcode("pushContext");
2690
- } else if (path24.data) {
2690
+ } else if (path26.data) {
2691
2691
  this.options.data = true;
2692
- this.opcode("lookupData", path24.depth, path24.parts, path24.strict);
2692
+ this.opcode("lookupData", path26.depth, path26.parts, path26.strict);
2693
2693
  } else {
2694
- this.opcode("lookupOnContext", path24.parts, path24.falsy, path24.strict, scoped);
2694
+ this.opcode("lookupOnContext", path26.parts, path26.falsy, path26.strict, scoped);
2695
2695
  }
2696
2696
  },
2697
2697
  StringLiteral: function StringLiteral(string) {
@@ -3041,16 +3041,16 @@ var require_util = __commonJS({
3041
3041
  }
3042
3042
  exports2.urlGenerate = urlGenerate;
3043
3043
  function normalize(aPath) {
3044
- var path24 = aPath;
3044
+ var path26 = aPath;
3045
3045
  var url = urlParse(aPath);
3046
3046
  if (url) {
3047
3047
  if (!url.path) {
3048
3048
  return aPath;
3049
3049
  }
3050
- path24 = url.path;
3050
+ path26 = url.path;
3051
3051
  }
3052
- var isAbsolute = exports2.isAbsolute(path24);
3053
- var parts = path24.split(/\/+/);
3052
+ var isAbsolute = exports2.isAbsolute(path26);
3053
+ var parts = path26.split(/\/+/);
3054
3054
  for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
3055
3055
  part = parts[i];
3056
3056
  if (part === ".") {
@@ -3067,18 +3067,18 @@ var require_util = __commonJS({
3067
3067
  }
3068
3068
  }
3069
3069
  }
3070
- path24 = parts.join("/");
3071
- if (path24 === "") {
3072
- path24 = isAbsolute ? "/" : ".";
3070
+ path26 = parts.join("/");
3071
+ if (path26 === "") {
3072
+ path26 = isAbsolute ? "/" : ".";
3073
3073
  }
3074
3074
  if (url) {
3075
- url.path = path24;
3075
+ url.path = path26;
3076
3076
  return urlGenerate(url);
3077
3077
  }
3078
- return path24;
3078
+ return path26;
3079
3079
  }
3080
3080
  exports2.normalize = normalize;
3081
- function join22(aRoot, aPath) {
3081
+ function join24(aRoot, aPath) {
3082
3082
  if (aRoot === "") {
3083
3083
  aRoot = ".";
3084
3084
  }
@@ -3110,7 +3110,7 @@ var require_util = __commonJS({
3110
3110
  }
3111
3111
  return joined;
3112
3112
  }
3113
- exports2.join = join22;
3113
+ exports2.join = join24;
3114
3114
  exports2.isAbsolute = function(aPath) {
3115
3115
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
3116
3116
  };
@@ -3283,7 +3283,7 @@ var require_util = __commonJS({
3283
3283
  parsed.path = parsed.path.substring(0, index + 1);
3284
3284
  }
3285
3285
  }
3286
- sourceURL = join22(urlGenerate(parsed), sourceURL);
3286
+ sourceURL = join24(urlGenerate(parsed), sourceURL);
3287
3287
  }
3288
3288
  return normalize(sourceURL);
3289
3289
  }
@@ -5858,8 +5858,8 @@ var require_printer = __commonJS({
5858
5858
  return this.accept(sexpr.path) + " " + params + hash;
5859
5859
  };
5860
5860
  PrintVisitor.prototype.PathExpression = function(id) {
5861
- var path24 = id.parts.join("/");
5862
- return (id.data ? "@" : "") + "PATH:" + path24;
5861
+ var path26 = id.parts.join("/");
5862
+ return (id.data ? "@" : "") + "PATH:" + path26;
5863
5863
  };
5864
5864
  PrintVisitor.prototype.StringLiteral = function(string) {
5865
5865
  return '"' + string.value + '"';
@@ -5898,8 +5898,8 @@ var require_lib = __commonJS({
5898
5898
  handlebars.print = printer.print;
5899
5899
  module2.exports = handlebars;
5900
5900
  function extension(module3, filename) {
5901
- var fs28 = require("fs");
5902
- var templateString = fs28.readFileSync(filename, "utf8");
5901
+ var fs30 = require("fs");
5902
+ var templateString = fs30.readFileSync(filename, "utf8");
5903
5903
  module3.exports = handlebars.compile(templateString);
5904
5904
  }
5905
5905
  if (typeof require !== "undefined" && require.extensions) {
@@ -5911,8 +5911,8 @@ var require_lib = __commonJS({
5911
5911
 
5912
5912
  // src/index.ts
5913
5913
  var import_commander = require("commander");
5914
- var fs27 = __toESM(require("node:fs"));
5915
- var path23 = __toESM(require("node:path"));
5914
+ var fs29 = __toESM(require("node:fs"));
5915
+ var path25 = __toESM(require("node:path"));
5916
5916
 
5917
5917
  // src/commands/setup.ts
5918
5918
  var path9 = __toESM(require("node:path"));
@@ -6570,14 +6570,21 @@ async function runInit(baseDir, opts) {
6570
6570
  const hasNodeBackend = opts.backend === "nodejs";
6571
6571
  const hasBackend = hasJavaBackend || hasNodeBackend;
6572
6572
  try {
6573
- if (hasFrontend) {
6574
- renderAngularTemplate(projectDir, ctx);
6575
- }
6576
- if (hasJavaBackend) {
6577
- renderJavaTemplate(projectDir, ctx);
6578
- }
6579
- if (hasNodeBackend) {
6580
- renderNestJSTemplate(projectDir, ctx, opts);
6573
+ const isMonorepo = hasFrontend && hasNodeBackend;
6574
+ if (isMonorepo) {
6575
+ renderAngularTemplate(path2.join(projectDir, "client"), ctx, true);
6576
+ renderNestJSTemplate(path2.join(projectDir, "server"), ctx, opts);
6577
+ renderMonorepoRoot(projectDir, ctx);
6578
+ } else {
6579
+ if (hasFrontend) {
6580
+ renderAngularTemplate(projectDir, ctx);
6581
+ }
6582
+ if (hasJavaBackend) {
6583
+ renderJavaTemplate(projectDir, ctx);
6584
+ }
6585
+ if (hasNodeBackend) {
6586
+ renderNestJSTemplate(projectDir, ctx, opts);
6587
+ }
6581
6588
  }
6582
6589
  renderCommonFiles(projectDir, ctx, opts);
6583
6590
  console.log(`
@@ -6586,9 +6593,15 @@ async function runInit(baseDir, opts) {
6586
6593
  if (!inPlace) {
6587
6594
  console.log(` cd ${opts.projectName}`);
6588
6595
  }
6589
- if (opts.frontend) console.log(` pnpm install # \u5B89\u88C5\u524D\u7AEF\u4F9D\u8D56`);
6590
- if (hasJavaBackend) console.log(` ./gradlew build # \u6784\u5EFA\u540E\u7AEF`);
6591
- if (hasNodeBackend) console.log(` pnpm install # \u5B89\u88C5\u4F9D\u8D56`);
6596
+ if (isMonorepo) {
6597
+ console.log(` cd client && pnpm install # \u5B89\u88C5\u524D\u7AEF\u4F9D\u8D56`);
6598
+ console.log(` cd server && pnpm install # \u5B89\u88C5\u540E\u7AEF\u4F9D\u8D56`);
6599
+ console.log(` pnpm dev # \u542F\u52A8\u524D\u540E\u7AEF\u5F00\u53D1\u670D\u52A1\u5668`);
6600
+ } else {
6601
+ if (opts.frontend) console.log(` pnpm install # \u5B89\u88C5\u524D\u7AEF\u4F9D\u8D56`);
6602
+ if (hasJavaBackend) console.log(` ./gradlew build # \u6784\u5EFA\u540E\u7AEF`);
6603
+ if (hasNodeBackend) console.log(` pnpm install # \u5B89\u88C5\u4F9D\u8D56`);
6604
+ }
6592
6605
  console.log();
6593
6606
  printProjectTree(projectDir, hasFrontend, hasJavaBackend, hasNodeBackend);
6594
6607
  if (inPlace) {
@@ -6601,9 +6614,10 @@ async function runInit(baseDir, opts) {
6601
6614
  throw err;
6602
6615
  }
6603
6616
  }
6604
- function renderAngularTemplate(projectDir, ctx) {
6617
+ function renderAngularTemplate(projectDir, ctx, subPkg = false) {
6605
6618
  const hasPrimeng = ctx.uiLib === "primeng";
6606
6619
  const hasTailwind = ctx.cssFramework === "tailwind";
6620
+ const webRoot = subPkg ? "src" : "src/main/web";
6607
6621
  writeTemplate(projectDir, "angular.json", JSON.stringify({
6608
6622
  $schema: "./node_modules/@angular/cli/lib/config/schema.json",
6609
6623
  version: 1,
@@ -6612,19 +6626,19 @@ function renderAngularTemplate(projectDir, ctx) {
6612
6626
  [ctx.packageName]: {
6613
6627
  projectType: "application",
6614
6628
  root: "",
6615
- sourceRoot: "src/main/web",
6629
+ sourceRoot: webRoot,
6616
6630
  prefix: "app",
6617
6631
  architect: {
6618
6632
  build: {
6619
6633
  builder: "@angular-devkit/build-angular:application",
6620
6634
  options: {
6621
6635
  outputPath: "build",
6622
- index: "src/main/web/index.html",
6623
- browser: "src/main/web/main.ts",
6636
+ index: `${webRoot}/index.html`,
6637
+ browser: `${webRoot}/main.ts`,
6624
6638
  polyfills: ["zone.js"],
6625
6639
  tsConfig: "tsconfig.app.json",
6626
6640
  assets: [{ glob: "**/*", input: "public" }],
6627
- styles: getAngularStyles(hasPrimeng),
6641
+ styles: getAngularStyles(hasPrimeng, webRoot),
6628
6642
  scripts: []
6629
6643
  },
6630
6644
  configurations: {
@@ -6641,7 +6655,7 @@ function renderAngularTemplate(projectDir, ctx) {
6641
6655
  },
6642
6656
  test: {
6643
6657
  builder: "@angular-devkit/build-angular:karma",
6644
- options: { polyfills: ["zone.js", "zone.js/testing"], tsConfig: "tsconfig.spec.json", assets: [{ glob: "**/*", input: "public" }], styles: getAngularStyles(hasPrimeng), scripts: [] }
6658
+ options: { polyfills: ["zone.js", "zone.js/testing"], tsConfig: "tsconfig.spec.json", assets: [{ glob: "**/*", input: "public" }], styles: getAngularStyles(hasPrimeng, webRoot), scripts: [] }
6645
6659
  }
6646
6660
  }
6647
6661
  }
@@ -6679,7 +6693,7 @@ function renderAngularTemplate(projectDir, ctx) {
6679
6693
  writeTemplate(projectDir, "tsconfig.app.json", JSON.stringify({
6680
6694
  extends: "./tsconfig.json",
6681
6695
  compilerOptions: { outDir: "./out-tsc/app", types: [] },
6682
- files: ["src/main/web/main.ts"],
6696
+ files: [`${webRoot}/main.ts`],
6683
6697
  include: ["src/**/*.d.ts"]
6684
6698
  }, null, 2));
6685
6699
  writeTemplate(projectDir, "tsconfig.spec.json", JSON.stringify({
@@ -6745,8 +6759,8 @@ export default [
6745
6759
  ];
6746
6760
  `);
6747
6761
  ensureDir2(path2.join(projectDir, "public"));
6748
- ensureDir2(path2.join(projectDir, "src/main/web/app"));
6749
- writeTemplate(projectDir, "src/main/web/index.html", `<!doctype html>
6762
+ ensureDir2(path2.join(projectDir, webRoot, "app"));
6763
+ writeTemplate(projectDir, `${webRoot}/index.html`, `<!doctype html>
6750
6764
  <html lang="zh-CN">
6751
6765
  <head>
6752
6766
  <meta charset="utf-8">
@@ -6760,7 +6774,7 @@ export default [
6760
6774
  </body>
6761
6775
  </html>
6762
6776
  `);
6763
- writeTemplate(projectDir, "src/main/web/main.ts", `import { bootstrapApplication } from '@angular/platform-browser';
6777
+ writeTemplate(projectDir, `${webRoot}/main.ts`, `import { bootstrapApplication } from '@angular/platform-browser';
6764
6778
  import { appConfig } from './app/app.config';
6765
6779
  import { App } from './app/app';
6766
6780
 
@@ -6771,8 +6785,8 @@ bootstrapApplication(App, appConfig).catch((err) => console.error(err));
6771
6785
  /* \u5168\u5C40\u6837\u5F0F */
6772
6786
  ` : `/* \u5168\u5C40\u6837\u5F0F */
6773
6787
  `;
6774
- writeTemplate(projectDir, "src/main/web/styles.css", stylesContent);
6775
- writeTemplate(projectDir, "src/main/web/app/app.ts", `import { Component } from '@angular/core';
6788
+ writeTemplate(projectDir, `${webRoot}/styles.css`, stylesContent);
6789
+ writeTemplate(projectDir, `${webRoot}/app/app.ts`, `import { Component } from '@angular/core';
6776
6790
  import { RouterOutlet } from '@angular/router';
6777
6791
 
6778
6792
  @Component({
@@ -6783,7 +6797,7 @@ import { RouterOutlet } from '@angular/router';
6783
6797
  })
6784
6798
  export class App {}
6785
6799
  `);
6786
- writeTemplate(projectDir, "src/main/web/app/app.config.ts", `import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
6800
+ writeTemplate(projectDir, `${webRoot}/app/app.config.ts`, `import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
6787
6801
  import { provideRouter } from '@angular/router';
6788
6802
  import { routes } from './app.routes';
6789
6803
 
@@ -6794,7 +6808,7 @@ export const appConfig: ApplicationConfig = {
6794
6808
  ],
6795
6809
  };
6796
6810
  `);
6797
- writeTemplate(projectDir, "src/main/web/app/app.routes.ts", `import { Routes } from '@angular/router';
6811
+ writeTemplate(projectDir, `${webRoot}/app/app.routes.ts`, `import { Routes } from '@angular/router';
6798
6812
 
6799
6813
  export const routes: Routes = [];
6800
6814
  `);
@@ -6804,14 +6818,33 @@ export const routes: Routes = [];
6804
6818
  }, null, 2));
6805
6819
  }
6806
6820
  }
6807
- function getAngularStyles(hasPrimeng) {
6821
+ function getAngularStyles(hasPrimeng, webRoot) {
6808
6822
  const styles = [];
6809
6823
  if (hasPrimeng) {
6810
6824
  styles.push("@primeng/themes/aura/aura.css");
6811
6825
  }
6812
- styles.push("src/main/web/styles.css");
6826
+ styles.push(`${webRoot}/styles.css`);
6813
6827
  return styles;
6814
6828
  }
6829
+ function renderMonorepoRoot(projectDir, ctx) {
6830
+ writeTemplate(projectDir, "package.json", JSON.stringify({
6831
+ name: ctx.packageName,
6832
+ version: "0.1.0",
6833
+ private: true,
6834
+ description: "",
6835
+ scripts: {
6836
+ dev: "pnpm --filter server dev & pnpm --filter client dev",
6837
+ build: "pnpm --filter server build",
6838
+ lint: "pnpm --filter server lint",
6839
+ format: "pnpm --filter server format",
6840
+ test: "pnpm --filter server test"
6841
+ }
6842
+ }, null, 2));
6843
+ writeTemplate(projectDir, "pnpm-workspace.yaml", `packages:
6844
+ - "server"
6845
+ - "client"
6846
+ `);
6847
+ }
6815
6848
  function renderJavaTemplate(projectDir, ctx) {
6816
6849
  const hasOrm = ctx.orm === "hibernate";
6817
6850
  const hasLiquibase = ctx.migration === "liquibase";
@@ -7511,14 +7544,22 @@ function generateReadme(ctx, opts) {
7511
7544
  }
7512
7545
  lines.push("");
7513
7546
  lines.push("## \u5FEB\u901F\u5F00\u59CB", "");
7514
- if (ctx.frontend) {
7547
+ if (ctx.frontend && hasNodeBackend) {
7548
+ lines.push("```bash");
7549
+ lines.push("# \u5B89\u88C5\u6240\u6709\u4F9D\u8D56");
7550
+ lines.push("pnpm install");
7551
+ lines.push("");
7552
+ lines.push("# \u542F\u52A8\u524D\u540E\u7AEF\u5F00\u53D1\u670D\u52A1\u5668");
7553
+ lines.push("pnpm dev");
7554
+ lines.push("```", "");
7555
+ } else if (ctx.frontend) {
7515
7556
  lines.push("### \u524D\u7AEF", "");
7516
7557
  lines.push("```bash");
7517
7558
  lines.push("pnpm install");
7518
7559
  lines.push("pnpm start");
7519
7560
  lines.push("```", "");
7520
7561
  }
7521
- if (hasNodeBackend) {
7562
+ if (hasNodeBackend && !ctx.frontend) {
7522
7563
  lines.push("### \u540E\u7AEF", "");
7523
7564
  lines.push("```bash");
7524
7565
  lines.push("pnpm install");
@@ -7534,10 +7575,16 @@ function generateReadme(ctx, opts) {
7534
7575
  lines.push("## \u9879\u76EE\u7ED3\u6784", "");
7535
7576
  lines.push("```");
7536
7577
  if (ctx.frontend && hasNodeBackend) {
7537
- lines.push("\u251C\u2500\u2500 src/ # NestJS + Angular");
7538
- lines.push("\u251C\u2500\u2500 angular.json # Angular \u914D\u7F6E");
7539
- lines.push("\u251C\u2500\u2500 nest-cli.json # NestJS \u914D\u7F6E");
7540
- lines.push("\u251C\u2500\u2500 tsconfig.json");
7578
+ lines.push("\u251C\u2500\u2500 server/ # NestJS \u540E\u7AEF");
7579
+ lines.push("\u2502 \u251C\u2500\u2500 src/");
7580
+ lines.push("\u2502 \u251C\u2500\u2500 nest-cli.json");
7581
+ lines.push("\u2502 \u2514\u2500\u2500 package.json");
7582
+ lines.push("\u251C\u2500\u2500 client/ # Angular \u524D\u7AEF");
7583
+ lines.push("\u2502 \u251C\u2500\u2500 src/");
7584
+ lines.push("\u2502 \u251C\u2500\u2500 public/");
7585
+ lines.push("\u2502 \u251C\u2500\u2500 angular.json");
7586
+ lines.push("\u2502 \u2514\u2500\u2500 package.json");
7587
+ lines.push("\u251C\u2500\u2500 pnpm-workspace.yaml");
7541
7588
  lines.push("\u2514\u2500\u2500 package.json");
7542
7589
  } else if (ctx.frontend && ctx.backend) {
7543
7590
  lines.push("\u251C\u2500\u2500 src/main/web/ # Angular \u524D\u7AEF");
@@ -7600,19 +7647,33 @@ function printProjectTree(projectDir, hasFrontend, hasJavaBackend, hasNodeBacken
7600
7647
  console.log(" \u251C\u2500\u2500 angular.json");
7601
7648
  console.log(" \u2514\u2500\u2500 package.json");
7602
7649
  } else if (hasFrontend && hasNodeBackend) {
7603
- console.log(" \u251C\u2500\u2500 src/");
7604
- console.log(" \u2502 \u251C\u2500\u2500 app.controller.ts");
7605
- console.log(" \u2502 \u251C\u2500\u2500 app.module.ts");
7606
- console.log(" \u2502 \u251C\u2500\u2500 app.service.ts");
7607
- console.log(" \u2502 \u251C\u2500\u2500 main.ts");
7608
- console.log(" \u2502 \u251C\u2500\u2500 prisma/ # Prisma ORM");
7609
- console.log(" \u2502 \u2514\u2500\u2500 agent/ # Claude Agent SDK");
7610
- console.log(" \u251C\u2500\u2500 prisma/");
7611
- console.log(" \u2502 \u2514\u2500\u2500 schema.prisma");
7612
- console.log(" \u251C\u2500\u2500 nest-cli.json");
7613
- console.log(" \u251C\u2500\u2500 tsconfig.json");
7614
- console.log(" \u251C\u2500\u2500 angular.json");
7615
- console.log(" \u2514\u2500\u2500 package.json");
7650
+ console.log(" \u251C\u2500\u2500 server/ # NestJS \u540E\u7AEF");
7651
+ console.log(" \u2502 \u251C\u2500\u2500 src/");
7652
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 app.controller.ts");
7653
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 app.module.ts");
7654
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 app.service.ts");
7655
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 main.ts");
7656
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 prisma/ # Prisma ORM");
7657
+ console.log(" \u2502 \u2502 \u2514\u2500\u2500 agent/ # Claude Agent SDK");
7658
+ console.log(" \u2502 \u251C\u2500\u2500 prisma/");
7659
+ console.log(" \u2502 \u2502 \u2514\u2500\u2500 schema.prisma");
7660
+ console.log(" \u2502 \u251C\u2500\u2500 nest-cli.json");
7661
+ console.log(" \u2502 \u251C\u2500\u2500 tsconfig.json");
7662
+ console.log(" \u2502 \u2514\u2500\u2500 package.json");
7663
+ console.log(" \u251C\u2500\u2500 client/ # Angular \u524D\u7AEF");
7664
+ console.log(" \u2502 \u251C\u2500\u2500 src/");
7665
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 index.html");
7666
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 main.ts");
7667
+ console.log(" \u2502 \u2502 \u251C\u2500\u2500 styles.css");
7668
+ console.log(" \u2502 \u2502 \u2514\u2500\u2500 app/");
7669
+ console.log(" \u2502 \u251C\u2500\u2500 public/");
7670
+ console.log(" \u2502 \u251C\u2500\u2500 angular.json");
7671
+ console.log(" \u2502 \u251C\u2500\u2500 tsconfig.json");
7672
+ console.log(" \u2502 \u2514\u2500\u2500 package.json");
7673
+ console.log(" \u251C\u2500\u2500 pnpm-workspace.yaml");
7674
+ console.log(" \u251C\u2500\u2500 package.json");
7675
+ console.log(" \u251C\u2500\u2500 .env");
7676
+ console.log(" \u2514\u2500\u2500 .gitignore");
7616
7677
  } else if (hasFrontend) {
7617
7678
  console.log(" \u251C\u2500\u2500 src/main/web/ # Angular \u524D\u7AEF");
7618
7679
  console.log(" \u251C\u2500\u2500 angular.json");
@@ -10446,13 +10507,380 @@ function registerPilotCommands(program2) {
10446
10507
  (0, import_pilot.registerPilotCommands)(program2);
10447
10508
  }
10448
10509
 
10449
- // src/commands/doctor.ts
10450
- var fs25 = __toESM(require("node:fs"));
10510
+ // src/record/browser-recorder.ts
10511
+ var path22 = __toESM(require("node:path"));
10512
+ var fs26 = __toESM(require("node:fs"));
10513
+ var import_playwright = require("playwright");
10514
+
10515
+ // src/record/recorder.ts
10451
10516
  var path21 = __toESM(require("node:path"));
10517
+ var fs25 = __toESM(require("node:fs"));
10518
+ function filterNoiseEvents(events) {
10519
+ const noiseTypes = [];
10520
+ const noiseSet = new Set(noiseTypes);
10521
+ return events.filter((e) => !noiseSet.has(e.type));
10522
+ }
10523
+ function eventGroupKey(e) {
10524
+ const selector = e.data?.cssSelector || "";
10525
+ return { cssSelector: selector, type: e.type };
10526
+ }
10527
+ function dedupEvents(events) {
10528
+ if (events.length === 0) return [];
10529
+ const result = [];
10530
+ const inputElements = /* @__PURE__ */ new Map();
10531
+ for (let i = 0; i < events.length; i++) {
10532
+ const current = events[i];
10533
+ if (current.type === "input" || current.type === "select") {
10534
+ const key = eventGroupKey(current);
10535
+ const dedupKey = `${key.cssSelector}|${key.type}`;
10536
+ inputElements.set(dedupKey, current);
10537
+ continue;
10538
+ }
10539
+ if (current.type === "click") {
10540
+ const lastEvent = result.length > 0 ? result[result.length - 1] : null;
10541
+ if (lastEvent && lastEvent.type === "click") {
10542
+ const currentKey = eventGroupKey(current);
10543
+ const lastKey = eventGroupKey(lastEvent);
10544
+ const sameElement = currentKey.cssSelector === lastKey.cssSelector;
10545
+ const withinThreshold = current.ts - lastEvent.ts <= 500;
10546
+ if (sameElement && withinThreshold) {
10547
+ continue;
10548
+ }
10549
+ }
10550
+ }
10551
+ result.push(current);
10552
+ }
10553
+ inputElements.forEach((event) => {
10554
+ result.push(event);
10555
+ });
10556
+ result.sort((a, b) => a.ts - b.ts);
10557
+ return result;
10558
+ }
10559
+ function serializeRecording(data) {
10560
+ return JSON.stringify(data, null, 2);
10561
+ }
10562
+ function buildRecordingFileName(seq = 1) {
10563
+ const now = /* @__PURE__ */ new Date();
10564
+ const pad = (n) => String(n).padStart(2, "0");
10565
+ const dateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
10566
+ const seqStr = seq > 1 ? `-${seq}` : "";
10567
+ return `${dateTime}${seqStr}.recording.json`;
10568
+ }
10569
+ function recordingsDir() {
10570
+ return path21.join(process.cwd(), ".deepstorm", "recordings");
10571
+ }
10572
+ function getNextSeq(datePrefix) {
10573
+ const dir = recordingsDir();
10574
+ if (!fs25.existsSync(dir)) return 1;
10575
+ const files = fs25.readdirSync(dir).filter((f) => f.startsWith(datePrefix));
10576
+ if (files.length === 0) return 1;
10577
+ let maxSeq = 0;
10578
+ for (const f of files) {
10579
+ const match = f.match(/(?:-(\d+))?\.recording\.json$/);
10580
+ if (match) {
10581
+ const s = match[1] ? parseInt(match[1], 10) : 1;
10582
+ maxSeq = Math.max(maxSeq, s);
10583
+ }
10584
+ }
10585
+ return maxSeq + 1;
10586
+ }
10587
+
10588
+ // src/record/browser-recorder.ts
10589
+ async function recordBrowserSession(url) {
10590
+ let targetUrl;
10591
+ try {
10592
+ targetUrl = new URL(url);
10593
+ } catch {
10594
+ throw new Error(`\u65E0\u6548\u7684 URL: ${url}`);
10595
+ }
10596
+ if (!await isPlaywrightAvailable()) {
10597
+ console.error("Playwright \u6D4F\u89C8\u5668\u672A\u5B89\u88C5\uFF0C\u8BF7\u6267\u884C npx playwright install");
10598
+ process.exit(1);
10599
+ }
10600
+ const startTime = Date.now();
10601
+ const browser = await import_playwright.chromium.launch({ headless: false });
10602
+ const context = await browser.newContext();
10603
+ const page = await context.newPage();
10604
+ const events = [];
10605
+ const requestMethods = /* @__PURE__ */ new Map();
10606
+ const cdpSession = await context.newCDPSession(page);
10607
+ cdpSession.on("Network.requestWillBeSent", (params) => {
10608
+ const { request, type, requestId } = params;
10609
+ requestMethods.set(requestId, request.method);
10610
+ if (type === "XHR" || type === "Fetch") {
10611
+ events.push({
10612
+ ts: Date.now() - startTime,
10613
+ type: "network",
10614
+ data: {
10615
+ url: request.url,
10616
+ method: request.method,
10617
+ type: "request"
10618
+ }
10619
+ });
10620
+ }
10621
+ });
10622
+ cdpSession.on("Network.responseReceived", (params) => {
10623
+ const { response, type, requestId } = params;
10624
+ const method = requestMethods.get(requestId) ?? "GET";
10625
+ if (type === "XHR" || type === "Fetch") {
10626
+ events.push({
10627
+ ts: Date.now() - startTime,
10628
+ type: "network",
10629
+ data: {
10630
+ url: response.url,
10631
+ method,
10632
+ statusCode: response.status,
10633
+ type: "response"
10634
+ }
10635
+ });
10636
+ }
10637
+ });
10638
+ cdpSession.on("Page.frameNavigated", (params) => {
10639
+ const { frame } = params;
10640
+ if (frame.parentId === void 0 || frame.parentId === null) {
10641
+ events.push({
10642
+ ts: Date.now() - startTime,
10643
+ type: "navigation",
10644
+ data: {
10645
+ url: frame.url,
10646
+ title: frame.name || frame.url,
10647
+ type: "full"
10648
+ }
10649
+ });
10650
+ }
10651
+ });
10652
+ cdpSession.on("Page.navigatedWithinDocument", (params) => {
10653
+ events.push({
10654
+ ts: Date.now() - startTime,
10655
+ type: "navigation",
10656
+ data: {
10657
+ url: params.url,
10658
+ type: "spa"
10659
+ }
10660
+ });
10661
+ });
10662
+ await page.exposeFunction("__deepstorm_recordEvent", (type, data) => {
10663
+ events.push({
10664
+ ts: Date.now() - startTime,
10665
+ type,
10666
+ data
10667
+ });
10668
+ });
10669
+ await page.goto(targetUrl.href);
10670
+ await page.evaluate(`(function() {
10671
+ var send = window.__deepstorm_recordEvent;
10672
+
10673
+ // Click listener (capture phase)
10674
+ document.addEventListener('click', function(e) {
10675
+ var target = e.target;
10676
+ if (!target || target === document.body || target === document.documentElement) return;
10677
+
10678
+ var info = {
10679
+ tagName: target.tagName.toLowerCase(),
10680
+ id: target.id || undefined,
10681
+ className: (target.className || '').toString().slice(0, 100) || undefined,
10682
+ textContent: (target.textContent || '').trim().slice(0, 100) || undefined
10683
+ };
10684
+
10685
+ var role = target.getAttribute('role');
10686
+ if (role) info.role = role;
10687
+ var ariaLabel = target.getAttribute('aria-label');
10688
+ if (ariaLabel) info.ariaLabel = ariaLabel;
10689
+ var placeholder = target.getAttribute('placeholder');
10690
+ if (placeholder) info.placeholder = placeholder;
10691
+ var dataTestId = target.getAttribute('data-testid');
10692
+ if (dataTestId) info.dataTestId = dataTestId;
10693
+
10694
+ info.cssSelector = buildSimpleSelector(target);
10695
+ send('click', info);
10696
+ }, true);
10697
+
10698
+ // Input listener (change event for final value)
10699
+ document.addEventListener('change', function(e) {
10700
+ var target = e.target;
10701
+ if (!target) return;
10702
+
10703
+ if (target.tagName === 'SELECT') {
10704
+ send('select', {
10705
+ tagName: 'select',
10706
+ value: target.value,
10707
+ name: target.name || undefined,
10708
+ cssSelector: buildSimpleSelector(target)
10709
+ });
10710
+ return;
10711
+ }
10712
+
10713
+ if (target.type === 'password') {
10714
+ send('input', {
10715
+ tagName: target.tagName.toLowerCase(),
10716
+ type: 'password',
10717
+ value: '****',
10718
+ name: target.name || undefined,
10719
+ placeholder: target.placeholder || undefined,
10720
+ cssSelector: buildSimpleSelector(target)
10721
+ });
10722
+ return;
10723
+ }
10724
+
10725
+ send('input', {
10726
+ tagName: target.tagName.toLowerCase(),
10727
+ type: target.type || undefined,
10728
+ value: target.value,
10729
+ name: target.name || undefined,
10730
+ placeholder: target.placeholder || undefined,
10731
+ cssSelector: buildSimpleSelector(target)
10732
+ });
10733
+ }, true);
10734
+
10735
+ // Submit listener
10736
+ document.addEventListener('submit', function(e) {
10737
+ var form = e.target;
10738
+ if (!form) return;
10739
+ send('submit', {
10740
+ cssSelector: buildSimpleSelector(form),
10741
+ id: form.id || undefined,
10742
+ action: form.action || undefined
10743
+ });
10744
+ }, true);
10745
+
10746
+ // Helper: build simple CSS selector
10747
+ function buildSimpleSelector(el) {
10748
+ if (el.id) return '#' + CSS.escape(el.id);
10749
+ var testId = el.getAttribute('data-testid');
10750
+ if (testId) return '[data-testid="' + CSS.escape(testId) + '"]';
10751
+ var tag = el.tagName.toLowerCase();
10752
+ var cls = '';
10753
+ for (var i = 0; i < el.classList.length; i++) {
10754
+ cls += '.' + CSS.escape(el.classList[i]);
10755
+ }
10756
+ if (cls) return tag + cls;
10757
+ var parent = el.parentElement;
10758
+ if (parent) {
10759
+ var siblings = Array.from(parent.children).filter(function(s) {
10760
+ return s.tagName === el.tagName;
10761
+ });
10762
+ if (siblings.length > 1) {
10763
+ var idx = siblings.indexOf(el) + 1;
10764
+ return tag + ':nth-child(' + idx + ')';
10765
+ }
10766
+ }
10767
+ return tag;
10768
+ }
10769
+ })();`);
10770
+ console.log("\u{1F3A5} \u5F55\u5236\u4E2D... \u6309 Ctrl+D \u505C\u6B62");
10771
+ const stopPromise = new Promise((resolve4) => {
10772
+ const wasRaw = process.stdin.isRaw;
10773
+ process.stdin.setRawMode?.(true);
10774
+ process.stdin.resume();
10775
+ process.stdin.on("data", (chunk) => {
10776
+ if (chunk.length === 1 && chunk[0] === 4) {
10777
+ cleanup();
10778
+ resolve4();
10779
+ }
10780
+ });
10781
+ process.stdin.on("end", () => {
10782
+ cleanup();
10783
+ resolve4();
10784
+ });
10785
+ function cleanup() {
10786
+ process.stdin.setRawMode?.(wasRaw ?? false);
10787
+ process.stdin.pause();
10788
+ }
10789
+ });
10790
+ const crashPromise = new Promise((_resolve, reject) => {
10791
+ browser.on("disconnected", () => {
10792
+ reject(new Error("\u6D4F\u89C8\u5668\u8FDE\u63A5\u65AD\u5F00"));
10793
+ });
10794
+ });
10795
+ try {
10796
+ await Promise.race([stopPromise, crashPromise]);
10797
+ } catch (err) {
10798
+ console.error("\n\u6D4F\u89C8\u5668\u8FDE\u63A5\u65AD\u5F00\uFF0C\u5F55\u5236\u5DF2\u7EC8\u6B62");
10799
+ throw err;
10800
+ } finally {
10801
+ process.stdin.setRawMode?.(false);
10802
+ process.stdin.pause();
10803
+ }
10804
+ const duration = Date.now() - startTime;
10805
+ try {
10806
+ const screenshotBuffer = await page.screenshot({ type: "jpeg", quality: 70 });
10807
+ events.push({
10808
+ ts: Date.now() - startTime,
10809
+ type: "screenshot",
10810
+ data: {
10811
+ label: "final",
10812
+ data: screenshotBuffer.toString("base64")
10813
+ }
10814
+ });
10815
+ } catch {
10816
+ }
10817
+ await browser.close();
10818
+ const filteredEvents = dedupEvents(filterNoiseEvents(events));
10819
+ const recordingData = {
10820
+ meta: {
10821
+ url: targetUrl.href,
10822
+ recordedAt: new Date(startTime).toISOString(),
10823
+ duration,
10824
+ browser: `Playwright Chromium ${browser.version()}`
10825
+ },
10826
+ events: filteredEvents
10827
+ };
10828
+ const dir = recordingsDir();
10829
+ fs26.mkdirSync(dir, { recursive: true });
10830
+ const datePrefix = buildRecordingFileName().replace(".recording.json", "");
10831
+ const seq = getNextSeq(datePrefix);
10832
+ const fileName = buildRecordingFileName(seq);
10833
+ const filePath = path22.join(dir, fileName);
10834
+ fs26.writeFileSync(filePath, serializeRecording(recordingData), "utf-8");
10835
+ console.log(`
10836
+ \u2705 \u5F55\u5236\u5B8C\u6210`);
10837
+ console.log(` \u6301\u7EED\u65F6\u95F4: ${(duration / 1e3).toFixed(1)} \u79D2`);
10838
+ console.log(` \u4E8B\u4EF6\u603B\u6570: ${filteredEvents.length}`);
10839
+ console.log(` \u6587\u4EF6\u8DEF\u5F84: ${filePath}`);
10840
+ return filePath;
10841
+ }
10842
+ async function isPlaywrightAvailable() {
10843
+ try {
10844
+ const { execSync: execSync3 } = await import("node:child_process");
10845
+ execSync3(
10846
+ "npx playwright install --dry-run 2>/dev/null || npx playwright --version 2>/dev/null",
10847
+ { stdio: "ignore" }
10848
+ );
10849
+ const browser = await import_playwright.chromium.launch({ headless: true });
10850
+ await browser.close();
10851
+ return true;
10852
+ } catch {
10853
+ return false;
10854
+ }
10855
+ }
10856
+
10857
+ // src/commands/record.ts
10858
+ function registerRecordCommand(program2) {
10859
+ const recordCmd = program2.command("record").description("\u6D4F\u89C8\u5668\u64CD\u4F5C\u5F55\u5236 \u2014 \u542F\u52A8 headed \u6D4F\u89C8\u5668\u5F55\u5236\u7528\u6237\u64CD\u4F5C\uFF0C\u8F93\u51FA .recording.json");
10860
+ recordCmd.command("start").description("\u5F00\u59CB\u5F55\u5236 \u2014 \u542F\u52A8 headed \u6D4F\u89C8\u5668\u5E76\u6253\u5F00\u6307\u5B9A URL").option("-u, --url <url>", "\u76EE\u6807 URL").action(async (options) => {
10861
+ if (!options.url) {
10862
+ console.error("\u8BF7\u4F7F\u7528 -u <url> \u6307\u5B9A\u76EE\u6807 URL");
10863
+ process.exit(1);
10864
+ }
10865
+ try {
10866
+ await recordBrowserSession(options.url);
10867
+ } catch (err) {
10868
+ console.error("\u5F55\u5236\u5931\u8D25:", err instanceof Error ? err.message : err);
10869
+ process.exit(1);
10870
+ }
10871
+ });
10872
+ recordCmd.command("stop").description("\u505C\u6B62\u5F55\u5236 \u2014 \u505C\u6B62\u5F53\u524D\u5F55\u5236\u5E76\u5199\u5165\u6587\u4EF6").action(() => {
10873
+ console.log("\u8BF7\u5728\u5F55\u5236\u7EC8\u7AEF\u6309 Ctrl+D \u505C\u6B62\u5F55\u5236");
10874
+ });
10875
+ }
10876
+
10877
+ // src/commands/doctor.ts
10878
+ var fs27 = __toESM(require("node:fs"));
10879
+ var path23 = __toESM(require("node:path"));
10452
10880
  function getInstalledSkills(targetDir) {
10453
10881
  const settingsPath = getDeepStormConfigPath(targetDir);
10454
10882
  try {
10455
- const settings = JSON.parse(fs25.readFileSync(settingsPath, "utf-8"));
10883
+ const settings = JSON.parse(fs27.readFileSync(settingsPath, "utf-8"));
10456
10884
  return settings.installedSkills || [];
10457
10885
  } catch {
10458
10886
  return [];
@@ -10469,7 +10897,7 @@ function runDoctor(targetDir) {
10469
10897
  message: `v${version}\uFF08\u8FD0\u884C deepstorm update \u68C0\u67E5\u6700\u65B0\u7248\u672C\uFF09`
10470
10898
  });
10471
10899
  let hasDeepStorm = false;
10472
- if (!fs25.existsSync(settingsPath)) {
10900
+ if (!fs27.existsSync(settingsPath)) {
10473
10901
  checks.push({
10474
10902
  name: "\u914D\u7F6E\u6587\u4EF6",
10475
10903
  status: "warn",
@@ -10477,7 +10905,7 @@ function runDoctor(targetDir) {
10477
10905
  });
10478
10906
  } else {
10479
10907
  try {
10480
- const config = JSON.parse(fs25.readFileSync(settingsPath, "utf-8"));
10908
+ const config = JSON.parse(fs27.readFileSync(settingsPath, "utf-8"));
10481
10909
  if (config && Object.keys(config).length > 0) {
10482
10910
  hasDeepStorm = true;
10483
10911
  checks.push({
@@ -10500,20 +10928,20 @@ function runDoctor(targetDir) {
10500
10928
  });
10501
10929
  }
10502
10930
  }
10503
- const skillsDir = path21.join(targetDir, ".claude", "skills");
10504
- if (fs25.existsSync(skillsDir)) {
10505
- const skillDirs = fs25.readdirSync(skillsDir).filter(
10506
- (n) => fs25.statSync(path21.join(skillsDir, n)).isDirectory()
10931
+ const skillsDir = path23.join(targetDir, ".claude", "skills");
10932
+ if (fs27.existsSync(skillsDir)) {
10933
+ const skillDirs = fs27.readdirSync(skillsDir).filter(
10934
+ (n) => fs27.statSync(path23.join(skillsDir, n)).isDirectory()
10507
10935
  );
10508
10936
  let validCount = 0;
10509
10937
  let invalidCount = 0;
10510
10938
  for (const skillName of skillDirs) {
10511
- const skillMd = path21.join(skillsDir, skillName, "SKILL.md");
10512
- if (!fs25.existsSync(skillMd)) {
10939
+ const skillMd = path23.join(skillsDir, skillName, "SKILL.md");
10940
+ if (!fs27.existsSync(skillMd)) {
10513
10941
  invalidCount++;
10514
10942
  continue;
10515
10943
  }
10516
- const content = fs25.readFileSync(skillMd, "utf-8");
10944
+ const content = fs27.readFileSync(skillMd, "utf-8");
10517
10945
  const frontmatter = parseFrontmatter(content);
10518
10946
  if (frontmatter && frontmatter.name) {
10519
10947
  validCount++;
@@ -10543,7 +10971,7 @@ function runDoctor(targetDir) {
10543
10971
  const installedSkills = getInstalledSkills(targetDir);
10544
10972
  const missingSkills = [];
10545
10973
  for (const skillId of installedSkills) {
10546
- if (!fs25.existsSync(path21.join(skillsDir, skillId))) {
10974
+ if (!fs27.existsSync(path23.join(skillsDir, skillId))) {
10547
10975
  missingSkills.push(skillId);
10548
10976
  }
10549
10977
  }
@@ -10567,10 +10995,10 @@ function runDoctor(targetDir) {
10567
10995
  message: ".claude/skills/ \u4E0D\u5B58\u5728"
10568
10996
  });
10569
10997
  }
10570
- const mcpPath = path21.join(targetDir, ".mcp.json");
10571
- if (fs25.existsSync(mcpPath)) {
10998
+ const mcpPath = path23.join(targetDir, ".mcp.json");
10999
+ if (fs27.existsSync(mcpPath)) {
10572
11000
  try {
10573
- const mcp = JSON.parse(fs25.readFileSync(mcpPath, "utf-8"));
11001
+ const mcp = JSON.parse(fs27.readFileSync(mcpPath, "utf-8"));
10574
11002
  const hasServers = mcp.mcpServers && Object.keys(mcp.mcpServers).length > 0;
10575
11003
  checks.push({
10576
11004
  name: "MCP \u670D\u52A1\u5668",
@@ -10591,12 +11019,12 @@ function runDoctor(targetDir) {
10591
11019
  message: ".mcp.json \u4E0D\u5B58\u5728"
10592
11020
  });
10593
11021
  }
10594
- if (hasDeepStorm && fs25.existsSync(settingsPath)) {
11022
+ if (hasDeepStorm && fs27.existsSync(settingsPath)) {
10595
11023
  try {
10596
- const config = JSON.parse(fs25.readFileSync(settingsPath, "utf-8"));
11024
+ const config = JSON.parse(fs27.readFileSync(settingsPath, "utf-8"));
10597
11025
  const installedMcp = config.installedMcpServers;
10598
11026
  if (installedMcp && installedMcp.length > 0) {
10599
- const mcpExists = fs25.existsSync(mcpPath);
11027
+ const mcpExists = fs27.existsSync(mcpPath);
10600
11028
  if (!mcpExists) {
10601
11029
  checks.push({
10602
11030
  name: "MCP \u4E00\u81F4\u6027",
@@ -10605,7 +11033,7 @@ function runDoctor(targetDir) {
10605
11033
  });
10606
11034
  } else {
10607
11035
  try {
10608
- const mcpConfig = JSON.parse(fs25.readFileSync(mcpPath, "utf-8"));
11036
+ const mcpConfig = JSON.parse(fs27.readFileSync(mcpPath, "utf-8"));
10609
11037
  const servers = mcpConfig.mcpServers || {};
10610
11038
  const missing = [];
10611
11039
  for (const toolName of installedMcp) {
@@ -10633,9 +11061,9 @@ function runDoctor(targetDir) {
10633
11061
  } catch {
10634
11062
  }
10635
11063
  }
10636
- if (hasDeepStorm && fs25.existsSync(settingsPath)) {
11064
+ if (hasDeepStorm && fs27.existsSync(settingsPath)) {
10637
11065
  try {
10638
- const config = JSON.parse(fs25.readFileSync(settingsPath, "utf-8"));
11066
+ const config = JSON.parse(fs27.readFileSync(settingsPath, "utf-8"));
10639
11067
  const validKeys = loadValidConfigKeys();
10640
11068
  if (validKeys.size > 0 && config) {
10641
11069
  const configKeys = [];
@@ -10688,18 +11116,18 @@ function printDoctorReport(report) {
10688
11116
  }
10689
11117
 
10690
11118
  // src/commands/uninstall.ts
10691
- var fs26 = __toESM(require("node:fs"));
10692
- var path22 = __toESM(require("node:path"));
11119
+ var fs28 = __toESM(require("node:fs"));
11120
+ var path24 = __toESM(require("node:path"));
10693
11121
  var import_prompts4 = require("@clack/prompts");
10694
11122
  async function uninstallDeepStorm(targetDir) {
10695
11123
  const settingsPath = getDeepStormConfigPath(targetDir);
10696
- if (!fs26.existsSync(settingsPath)) {
11124
+ if (!fs28.existsSync(settingsPath)) {
10697
11125
  console.log("DeepStorm \u5C1A\u672A\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D");
10698
11126
  return;
10699
11127
  }
10700
11128
  let hasDeepStorm = false;
10701
11129
  try {
10702
- const settings = JSON.parse(fs26.readFileSync(settingsPath, "utf-8"));
11130
+ const settings = JSON.parse(fs28.readFileSync(settingsPath, "utf-8"));
10703
11131
  hasDeepStorm = !!settings && Object.keys(settings).length > 0;
10704
11132
  } catch {
10705
11133
  }
@@ -10709,14 +11137,14 @@ async function uninstallDeepStorm(targetDir) {
10709
11137
  }
10710
11138
  cleanInstalled(targetDir);
10711
11139
  resetConfig(targetDir);
10712
- const templatesDir = path22.join(targetDir, ".deepstorm", "templates");
10713
- if (fs26.existsSync(templatesDir)) {
11140
+ const templatesDir = path24.join(targetDir, ".deepstorm", "templates");
11141
+ if (fs28.existsSync(templatesDir)) {
10714
11142
  const shouldDelete = await (0, import_prompts4.confirm)({
10715
11143
  message: "\u662F\u5426\u5220\u9664 .deepstorm/templates/ \u76EE\u5F55\uFF1F",
10716
11144
  initialValue: false
10717
11145
  });
10718
11146
  if (shouldDelete) {
10719
- fs26.rmSync(templatesDir, { recursive: true, force: true });
11147
+ fs28.rmSync(templatesDir, { recursive: true, force: true });
10720
11148
  console.log("\u2714 .deepstorm/templates/ \u5DF2\u5220\u9664");
10721
11149
  } else {
10722
11150
  console.log("\u4FDD\u7559 .deepstorm/templates/");
@@ -10729,9 +11157,9 @@ async function uninstallDeepStorm(targetDir) {
10729
11157
  var program = new import_commander.Command();
10730
11158
  program.name("deepstorm").description("DeepStorm CLI \u2014 \u4E00\u952E\u914D\u7F6E\u9879\u76EE\u5F00\u53D1\u73AF\u5883").version(getCliVersion(), "-v, --version", "\u8F93\u51FA\u7248\u672C\u53F7");
10731
11159
  function loadRegistry() {
10732
- const registryPath = path23.join(__dirname, "registry.json");
11160
+ const registryPath = path25.join(__dirname, "registry.json");
10733
11161
  try {
10734
- const raw = fs27.readFileSync(registryPath, "utf-8");
11162
+ const raw = fs29.readFileSync(registryPath, "utf-8");
10735
11163
  return JSON.parse(raw);
10736
11164
  } catch {
10737
11165
  return { version: "1", tools: {}, wizards: {}, skills: {} };
@@ -10745,6 +11173,7 @@ registerConfigCommand(program, registry);
10745
11173
  registerTemplateCommand(program, registry);
10746
11174
  registerUpdateCommand(program);
10747
11175
  registerPilotCommands(program);
11176
+ registerRecordCommand(program);
10748
11177
  program.command("doctor").description("\u8BCA\u65AD\u9879\u76EE DeepStorm \u914D\u7F6E\u72B6\u6001").action(() => {
10749
11178
  const report = runDoctor(process.cwd());
10750
11179
  printDoctorReport(report);