@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(
|
|
1191
|
-
return /^\.|this\b/.test(
|
|
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(
|
|
1196
|
-
return
|
|
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(
|
|
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:
|
|
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),
|
|
2589
|
+
var params = this.setupFullMustacheParams(decorator, program2, void 0), path26 = decorator.path;
|
|
2590
2590
|
this.useDecorators = true;
|
|
2591
|
-
this.opcode("registerDecorator", params.length,
|
|
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
|
|
2656
|
-
this.opcode("getContext",
|
|
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
|
-
|
|
2660
|
-
this.accept(
|
|
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
|
|
2665
|
-
|
|
2666
|
-
this.accept(
|
|
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),
|
|
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
|
-
|
|
2677
|
-
|
|
2678
|
-
this.accept(
|
|
2679
|
-
this.opcode("invokeHelper", params.length,
|
|
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(
|
|
2683
|
-
this.addDepth(
|
|
2684
|
-
this.opcode("getContext",
|
|
2685
|
-
var 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,
|
|
2687
|
+
this.opcode("lookupBlockParam", blockParamId, path26.parts);
|
|
2688
2688
|
} else if (!name) {
|
|
2689
2689
|
this.opcode("pushContext");
|
|
2690
|
-
} else if (
|
|
2690
|
+
} else if (path26.data) {
|
|
2691
2691
|
this.options.data = true;
|
|
2692
|
-
this.opcode("lookupData",
|
|
2692
|
+
this.opcode("lookupData", path26.depth, path26.parts, path26.strict);
|
|
2693
2693
|
} else {
|
|
2694
|
-
this.opcode("lookupOnContext",
|
|
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
|
|
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
|
-
|
|
3050
|
+
path26 = url.path;
|
|
3051
3051
|
}
|
|
3052
|
-
var isAbsolute = exports2.isAbsolute(
|
|
3053
|
-
var parts =
|
|
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
|
-
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
3070
|
+
path26 = parts.join("/");
|
|
3071
|
+
if (path26 === "") {
|
|
3072
|
+
path26 = isAbsolute ? "/" : ".";
|
|
3073
3073
|
}
|
|
3074
3074
|
if (url) {
|
|
3075
|
-
url.path =
|
|
3075
|
+
url.path = path26;
|
|
3076
3076
|
return urlGenerate(url);
|
|
3077
3077
|
}
|
|
3078
|
-
return
|
|
3078
|
+
return path26;
|
|
3079
3079
|
}
|
|
3080
3080
|
exports2.normalize = normalize;
|
|
3081
|
-
function
|
|
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 =
|
|
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 =
|
|
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
|
|
5862
|
-
return (id.data ? "@" : "") + "PATH:" +
|
|
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
|
|
5902
|
-
var templateString =
|
|
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
|
|
5915
|
-
var
|
|
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
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
}
|
|
6579
|
-
|
|
6580
|
-
|
|
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 (
|
|
6590
|
-
|
|
6591
|
-
|
|
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:
|
|
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:
|
|
6623
|
-
browser:
|
|
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: [
|
|
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, "
|
|
6749
|
-
writeTemplate(projectDir,
|
|
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,
|
|
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,
|
|
6775
|
-
writeTemplate(projectDir,
|
|
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,
|
|
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,
|
|
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(
|
|
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
|
|
7538
|
-
lines.push("\u251C\u2500\u2500
|
|
7539
|
-
lines.push("\u251C\u2500\u2500 nest-cli.json
|
|
7540
|
-
lines.push("\
|
|
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
|
|
7604
|
-
console.log(" \u2502 \u251C\u2500\u2500
|
|
7605
|
-
console.log(" \u2502 \u251C\u2500\u2500 app.
|
|
7606
|
-
console.log(" \u2502 \u251C\u2500\u2500 app.
|
|
7607
|
-
console.log(" \u2502 \u251C\u2500\u2500
|
|
7608
|
-
console.log(" \u2502 \u251C\u2500\u2500
|
|
7609
|
-
console.log(" \u2502 \
|
|
7610
|
-
console.log(" \
|
|
7611
|
-
console.log(" \u2502 \
|
|
7612
|
-
console.log(" \
|
|
7613
|
-
console.log(" \u251C\u2500\u2500
|
|
7614
|
-
console.log(" \u251C\u2500\u2500
|
|
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/
|
|
10450
|
-
var
|
|
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(
|
|
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 (!
|
|
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(
|
|
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 =
|
|
10504
|
-
if (
|
|
10505
|
-
const skillDirs =
|
|
10506
|
-
(n) =>
|
|
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 =
|
|
10512
|
-
if (!
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
10571
|
-
if (
|
|
10998
|
+
const mcpPath = path23.join(targetDir, ".mcp.json");
|
|
10999
|
+
if (fs27.existsSync(mcpPath)) {
|
|
10572
11000
|
try {
|
|
10573
|
-
const mcp = JSON.parse(
|
|
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 &&
|
|
11022
|
+
if (hasDeepStorm && fs27.existsSync(settingsPath)) {
|
|
10595
11023
|
try {
|
|
10596
|
-
const config = JSON.parse(
|
|
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 =
|
|
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(
|
|
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 &&
|
|
11064
|
+
if (hasDeepStorm && fs27.existsSync(settingsPath)) {
|
|
10637
11065
|
try {
|
|
10638
|
-
const config = JSON.parse(
|
|
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
|
|
10692
|
-
var
|
|
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 (!
|
|
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(
|
|
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 =
|
|
10713
|
-
if (
|
|
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
|
-
|
|
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 =
|
|
11160
|
+
const registryPath = path25.join(__dirname, "registry.json");
|
|
10733
11161
|
try {
|
|
10734
|
-
const raw =
|
|
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);
|