@vobs/cli 1.7.8 → 1.8.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/banner.cjs +22 -3
- package/dist/banner.cjs.map +1 -1
- package/dist/banner.d.cts +6 -2
- package/dist/banner.d.ts +6 -2
- package/dist/banner.js +20 -3
- package/dist/banner.js.map +1 -1
- package/dist/cli.cjs +361 -21
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +10 -1
- package/dist/cli.d.ts +10 -1
- package/dist/cli.js +351 -12
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.cjs +2 -2
- package/dist/commands/add.cjs.map +1 -1
- package/dist/commands/add.js +2 -2
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/build.cjs +2 -2
- package/dist/commands/build.cjs.map +1 -1
- package/dist/commands/build.js +2 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.cjs +382 -0
- package/dist/commands/check.cjs.map +1 -0
- package/dist/commands/check.d.cts +34 -0
- package/dist/commands/check.d.ts +34 -0
- package/dist/commands/check.js +343 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/dev.cjs +2 -2
- package/dist/commands/dev.cjs.map +1 -1
- package/dist/commands/dev.js +2 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/dsh.cjs +2 -2
- package/dist/commands/dsh.cjs.map +1 -1
- package/dist/commands/dsh.js +2 -2
- package/dist/commands/dsh.js.map +1 -1
- package/dist/commands/generate.cjs +2 -2
- package/dist/commands/generate.cjs.map +1 -1
- package/dist/commands/generate.js +2 -2
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/index.cjs +34 -17
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.js +25 -8
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.cjs +20 -3
- package/dist/commands/init.cjs.map +1 -1
- package/dist/commands/init.js +20 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/index.cjs +399 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +388 -14
- package/dist/index.js.map +1 -1
- package/dist/repl.cjs +34 -17
- package/dist/repl.cjs.map +1 -1
- package/dist/repl.js +25 -8
- package/dist/repl.js.map +1 -1
- package/dist/start.cjs +399 -25
- package/dist/start.cjs.map +1 -1
- package/dist/start.d.cts +8 -1
- package/dist/start.d.ts +8 -1
- package/dist/start.js +388 -14
- package/dist/start.js.map +1 -1
- package/dist/utils/logger.cjs +2 -2
- package/dist/utils/logger.cjs.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/version.cjs +47 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.d.cts +3 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/package.json +3 -2
- package/src/banner.ts +11 -5
- package/src/cli-process.test.ts +139 -0
- package/src/cli.ts +30 -2
- package/src/commands/check.test.ts +238 -0
- package/src/commands/check.ts +461 -0
- package/src/commands/init.ts +2 -1
- package/src/start.ts +66 -5
- package/src/utils/logger.ts +14 -2
- package/src/version.ts +27 -0
package/dist/start.cjs
CHANGED
|
@@ -51,7 +51,7 @@ function timestamp() {
|
|
|
51
51
|
}
|
|
52
52
|
__name(timestamp, "timestamp");
|
|
53
53
|
function info(msg) {
|
|
54
|
-
console.
|
|
54
|
+
console.error(`${timestamp()} ${import_picocolors.default.cyan("\u2139")} ${msg}`);
|
|
55
55
|
}
|
|
56
56
|
__name(info, "info");
|
|
57
57
|
function success(msg) {
|
|
@@ -59,7 +59,7 @@ function success(msg) {
|
|
|
59
59
|
}
|
|
60
60
|
__name(success, "success");
|
|
61
61
|
function warn(msg) {
|
|
62
|
-
console.
|
|
62
|
+
console.error(`${timestamp()} ${import_picocolors.default.yellow("\u26A0")} ${msg}`);
|
|
63
63
|
}
|
|
64
64
|
__name(warn, "warn");
|
|
65
65
|
function error(msg) {
|
|
@@ -163,6 +163,23 @@ function addPackage(targetDir, pm, pkg, dev) {
|
|
|
163
163
|
}
|
|
164
164
|
__name(addPackage, "addPackage");
|
|
165
165
|
|
|
166
|
+
// packages/cli/src/version.ts
|
|
167
|
+
var import_node_fs3 = require("fs");
|
|
168
|
+
var cached;
|
|
169
|
+
function cliVersion() {
|
|
170
|
+
if (cached !== void 0) return cached;
|
|
171
|
+
try {
|
|
172
|
+
const manifest = JSON.parse(
|
|
173
|
+
(0, import_node_fs3.readFileSync)(new URL("../package.json", __VOBS_CJS_FILE_URL), "utf8")
|
|
174
|
+
);
|
|
175
|
+
cached = manifest.version ?? "0.0.0";
|
|
176
|
+
} catch {
|
|
177
|
+
cached = "0.0.0";
|
|
178
|
+
}
|
|
179
|
+
return cached;
|
|
180
|
+
}
|
|
181
|
+
__name(cliVersion, "cliVersion");
|
|
182
|
+
|
|
166
183
|
// packages/cli/src/commands/init.ts
|
|
167
184
|
async function initCommand(options) {
|
|
168
185
|
const projectName = options.name || await p.text({
|
|
@@ -208,7 +225,7 @@ async function initCommand(options) {
|
|
|
208
225
|
name: projectName,
|
|
209
226
|
packageName: projectName.toLowerCase().replace(/\s+/g, "-"),
|
|
210
227
|
typescript: useTypescript,
|
|
211
|
-
vobsVersion:
|
|
228
|
+
vobsVersion: cliVersion()
|
|
212
229
|
});
|
|
213
230
|
logger.success("Project scaffolded");
|
|
214
231
|
logger.step("Installing dependencies...");
|
|
@@ -360,7 +377,7 @@ async function addCommand(options) {
|
|
|
360
377
|
__name(addCommand, "addCommand");
|
|
361
378
|
|
|
362
379
|
// packages/cli/src/commands/dsh.ts
|
|
363
|
-
var
|
|
380
|
+
var import_node_fs4 = require("fs");
|
|
364
381
|
var import_promises = require("fs/promises");
|
|
365
382
|
var import_node_child_process3 = require("child_process");
|
|
366
383
|
var import_node_http = require("http");
|
|
@@ -371,7 +388,7 @@ var PLATFORM_MODULES = ["react", "react-dom"];
|
|
|
371
388
|
var vobsVersion = /* @__PURE__ */ __name(() => {
|
|
372
389
|
try {
|
|
373
390
|
const manifest = JSON.parse(
|
|
374
|
-
(0,
|
|
391
|
+
(0, import_node_fs4.readFileSync)(new URL("../../package.json", __VOBS_CJS_FILE_URL), "utf8")
|
|
375
392
|
);
|
|
376
393
|
return manifest.version ?? "1.7.5";
|
|
377
394
|
} catch {
|
|
@@ -413,7 +430,7 @@ async function dshInitCommand(target, options) {
|
|
|
413
430
|
"dsh-plugin"
|
|
414
431
|
);
|
|
415
432
|
ensureDir(targetDir);
|
|
416
|
-
(0,
|
|
433
|
+
(0, import_node_fs4.writeFileSync)(
|
|
417
434
|
(0, import_node_path5.resolve)(targetDir, ".gitignore"),
|
|
418
435
|
["node_modules/", "*.log", "*.tsbuildinfo", "", "# lib/ \u662F\u6784\u5EFA\u4EA7\u7269\uFF0C\u5FC5\u987B\u63D0\u4EA4\uFF1ADSH \u5B89\u88C5\u65F6\u4E0D\u4F1A\u6784\u5EFA\u4F60\u7684\u5305\u3002", ""].join("\n"),
|
|
419
436
|
"utf8"
|
|
@@ -440,7 +457,7 @@ __name(dshInitCommand, "dshInitCommand");
|
|
|
440
457
|
async function dshBuildCommand() {
|
|
441
458
|
const projectDir = process.cwd();
|
|
442
459
|
const configFile = (0, import_node_path5.resolve)(projectDir, "vite.config.ts");
|
|
443
|
-
if (!(0,
|
|
460
|
+
if (!(0, import_node_fs4.existsSync)(configFile)) {
|
|
444
461
|
logger.error("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 vite.config.ts\uFF0C\u8BF7\u5728\u63D2\u4EF6\u9879\u76EE\u6839\u76EE\u5F55\u8FD0\u884C\u3002");
|
|
445
462
|
process.exitCode = 1;
|
|
446
463
|
return;
|
|
@@ -463,7 +480,7 @@ async function dshBuildCommand() {
|
|
|
463
480
|
logger.info("\u6784\u5EFA Host \u4EA7\u7269 \u2026");
|
|
464
481
|
const hostTarget = (0, import_node_path5.resolve)(projectDir, hostEntry.replace(/^\.\//u, ""));
|
|
465
482
|
const hostEntrySource = (0, import_node_path5.resolve)(projectDir, "src", "host", "index.ts");
|
|
466
|
-
if (!(0,
|
|
483
|
+
if (!(0, import_node_fs4.existsSync)(hostEntrySource)) {
|
|
467
484
|
logger.warn(`\u6CA1\u6709\u627E\u5230 ${hostEntrySource}\uFF0C\u8DF3\u8FC7 Host \u6784\u5EFA\u3002`);
|
|
468
485
|
return;
|
|
469
486
|
}
|
|
@@ -576,7 +593,7 @@ async function dshDevCommand(options) {
|
|
|
576
593
|
packageRoot = (0, import_node_path5.dirname)((0, import_node_path5.dirname)(projectRequire.resolve("@vobs/dsh")));
|
|
577
594
|
}
|
|
578
595
|
const candidate = (0, import_node_path5.join)(packageRoot, "dist", "preview.js");
|
|
579
|
-
previewFile = (0,
|
|
596
|
+
previewFile = (0, import_node_fs4.existsSync)(candidate) ? candidate : void 0;
|
|
580
597
|
} catch {
|
|
581
598
|
previewFile = void 0;
|
|
582
599
|
}
|
|
@@ -648,7 +665,7 @@ data: 1
|
|
|
648
665
|
return;
|
|
649
666
|
}
|
|
650
667
|
if (url === "/client.js") {
|
|
651
|
-
if (!(0,
|
|
668
|
+
if (!(0, import_node_fs4.existsSync)(clientFile)) {
|
|
652
669
|
response.writeHead(503, { "content-type": "text/plain; charset=utf-8" });
|
|
653
670
|
response.end(`\u8FD8\u6CA1\u6709\u4EA7\u7269\uFF1A${clientEntry}
|
|
654
671
|
${buildError ?? ""}`);
|
|
@@ -669,7 +686,7 @@ ${buildError ?? ""}`);
|
|
|
669
686
|
__name(dshDevCommand, "dshDevCommand");
|
|
670
687
|
function readManifest(dir) {
|
|
671
688
|
try {
|
|
672
|
-
return JSON.parse((0,
|
|
689
|
+
return JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path5.resolve)(dir, "package.json"), "utf8"));
|
|
673
690
|
} catch {
|
|
674
691
|
return void 0;
|
|
675
692
|
}
|
|
@@ -692,10 +709,10 @@ function collectIssues(dir) {
|
|
|
692
709
|
result.errors.push("\u7F3A\u5C11 dsh.bundle.patch \u2014\u2014 DSH \u4E0D\u4F1A\u628A\u8FD9\u4E2A\u5305\u5F53\u4F5C\u7EC4\u5408\u5305\uFF08bundle\uFF09");
|
|
693
710
|
} else {
|
|
694
711
|
const patchPath = (0, import_node_path5.resolve)(dir, bundle.patch.replace(/^\.\//u, ""));
|
|
695
|
-
if (!(0,
|
|
712
|
+
if (!(0, import_node_fs4.existsSync)(patchPath)) {
|
|
696
713
|
result.errors.push(`dsh.bundle.patch \u6307\u5411\u7684 ${bundle.patch} \u4E0D\u5B58\u5728`);
|
|
697
714
|
} else {
|
|
698
|
-
const text5 = (0,
|
|
715
|
+
const text5 = (0, import_node_fs4.readFileSync)(patchPath, "utf8");
|
|
699
716
|
if (!text5.includes("insert:")) result.errors.push("cordis.patch.yml \u91CC\u6CA1\u6709 insert: \u6BB5\u843D\uFF0C\u63D2\u4EF6\u884C\u4E0D\u4F1A\u8FDB\u7EC4\u5408\u6811");
|
|
700
717
|
else if (name !== "" && !text5.includes(name)) {
|
|
701
718
|
result.warnings.push(`cordis.patch.yml \u91CC\u6CA1\u6709\u51FA\u73B0\u5305\u540D ${name}\uFF0C\u786E\u8BA4 insert \u7684 name \u5199\u5BF9\u4E86`);
|
|
@@ -709,7 +726,7 @@ function collectIssues(dir) {
|
|
|
709
726
|
const hostEntry = exportsField["."];
|
|
710
727
|
const clientEntry = exportsField["./client"];
|
|
711
728
|
if (typeof hostEntry !== "string") result.errors.push('exports["."] \u672A\u58F0\u660E \u2014\u2014 DSH \u52A0\u8F7D\u4E0D\u5230 Host \u4FA7\u63D2\u4EF6');
|
|
712
|
-
else if (!(0,
|
|
729
|
+
else if (!(0, import_node_fs4.existsSync)((0, import_node_path5.resolve)(dir, hostEntry.replace(/^\.\//u, "")))) {
|
|
713
730
|
result.errors.push(`exports["."] \u6307\u5411\u7684 ${hostEntry} \u4E0D\u5B58\u5728\uFF0C\u5148\u6784\u5EFA`);
|
|
714
731
|
} else result.passed.push("Host \u5165\u53E3\u5B58\u5728");
|
|
715
732
|
if (typeof clientEntry !== "string") result.errors.push('exports["./client"] \u672A\u58F0\u660E \u2014\u2014 \u9875\u9762\u62FF\u4E0D\u5230\u5BA2\u6237\u7AEF bundle');
|
|
@@ -727,10 +744,10 @@ function collectIssues(dir) {
|
|
|
727
744
|
} else result.passed.push("\u6CA1\u6709 workspace: \u534F\u8BAE\u4F9D\u8D56");
|
|
728
745
|
if (typeof clientEntry === "string") {
|
|
729
746
|
const clientPath = (0, import_node_path5.resolve)(dir, clientEntry.replace(/^\.\//u, ""));
|
|
730
|
-
if (!(0,
|
|
747
|
+
if (!(0, import_node_fs4.existsSync)(clientPath)) {
|
|
731
748
|
result.errors.push(`\u5BA2\u6237\u7AEF\u4EA7\u7269 ${clientEntry} \u4E0D\u5B58\u5728\uFF0C\u5148\u8FD0\u884C\u6784\u5EFA`);
|
|
732
749
|
} else {
|
|
733
|
-
const code = (0,
|
|
750
|
+
const code = (0, import_node_fs4.readFileSync)(clientPath, "utf8");
|
|
734
751
|
const loads = (code.match(/__ModuleLoader__\.load\(/gu) ?? []).length;
|
|
735
752
|
if (loads !== 1) result.errors.push(`\u5BA2\u6237\u7AEF\u4EA7\u7269\u91CC __ModuleLoader__.load \u51FA\u73B0 ${loads} \u6B21\uFF0C\u5E94\u4E3A 1 \u6B21\uFF08\u5148\u6784\u5EFA\uFF09`);
|
|
736
753
|
else result.passed.push("\u4EA7\u7269\u5F62\u6001\u662F DSH \u5BA2\u6237\u7AEF\u6A21\u5757\u534F\u8BAE");
|
|
@@ -781,7 +798,7 @@ function buildInstallSpec(options) {
|
|
|
781
798
|
if (options.spec !== void 0) return { spec: options.spec };
|
|
782
799
|
if (options.from !== void 0) {
|
|
783
800
|
const target = (0, import_node_path5.resolve)(options.from);
|
|
784
|
-
if (!(0,
|
|
801
|
+
if (!(0, import_node_fs4.existsSync)(target)) return { error: `--from \u6307\u5411\u7684\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${target}` };
|
|
785
802
|
return { spec: target };
|
|
786
803
|
}
|
|
787
804
|
if (options.repo !== void 0) {
|
|
@@ -888,8 +905,309 @@ async function dshCommand(action, target, options) {
|
|
|
888
905
|
}
|
|
889
906
|
__name(dshCommand, "dshCommand");
|
|
890
907
|
|
|
908
|
+
// packages/cli/src/commands/check.ts
|
|
909
|
+
var import_promises2 = require("fs/promises");
|
|
910
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
911
|
+
var import_typescript = __toESM(require("typescript"), 1);
|
|
912
|
+
var REPORT_PATH = ".vobs/check.json";
|
|
913
|
+
var TEST_FILE = /(?:^|\/)(?:[^/]*\.(?:test|spec)\.tsx?|__tests__\/)/u;
|
|
914
|
+
var VOBS_C210 = "VOBS_C210";
|
|
915
|
+
var VOBS_C232 = "VOBS_C232";
|
|
916
|
+
var VOBS_C118 = "VOBS_C118";
|
|
917
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "lib", "build", ".git", ".vobs", "coverage"]);
|
|
918
|
+
async function collectSources(root) {
|
|
919
|
+
let rootStat;
|
|
920
|
+
try {
|
|
921
|
+
rootStat = await (0, import_promises2.stat)(root);
|
|
922
|
+
} catch {
|
|
923
|
+
throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
924
|
+
}
|
|
925
|
+
if (!rootStat.isDirectory()) {
|
|
926
|
+
throw new Error(`\u4E0D\u662F\u76EE\u5F55\uFF1A${root}\uFF08vobs check \u63A5\u53D7\u4E00\u4E2A\u76EE\u5F55\uFF09`);
|
|
927
|
+
}
|
|
928
|
+
const found = [];
|
|
929
|
+
const walk = /* @__PURE__ */ __name(async (dir) => {
|
|
930
|
+
let entries;
|
|
931
|
+
try {
|
|
932
|
+
entries = await (0, import_promises2.readdir)(dir, { withFileTypes: true });
|
|
933
|
+
} catch (error2) {
|
|
934
|
+
if (dir === root) {
|
|
935
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF1A${root}\uFF08${error2 instanceof Error ? error2.message : String(error2)}\uFF09`);
|
|
936
|
+
}
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
for (const entry of entries) {
|
|
940
|
+
if (entry.isDirectory()) {
|
|
941
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
942
|
+
await walk(import_node_path6.default.join(dir, entry.name));
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
945
|
+
if (!entry.isFile()) continue;
|
|
946
|
+
if (!/\.tsx?$/u.test(entry.name) || entry.name.endsWith(".d.ts")) continue;
|
|
947
|
+
found.push(import_node_path6.default.join(dir, entry.name));
|
|
948
|
+
}
|
|
949
|
+
}, "walk");
|
|
950
|
+
await walk(root);
|
|
951
|
+
return found.sort();
|
|
952
|
+
}
|
|
953
|
+
__name(collectSources, "collectSources");
|
|
954
|
+
function returnsJsx(node) {
|
|
955
|
+
let seen = false;
|
|
956
|
+
const visit = /* @__PURE__ */ __name((child) => {
|
|
957
|
+
if (seen) return;
|
|
958
|
+
if (import_typescript.default.isJsxElement(child) || import_typescript.default.isJsxSelfClosingElement(child) || import_typescript.default.isJsxFragment(child)) {
|
|
959
|
+
seen = true;
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
if (child !== node && import_typescript.default.isFunctionLike(child)) return;
|
|
963
|
+
import_typescript.default.forEachChild(child, visit);
|
|
964
|
+
}, "visit");
|
|
965
|
+
import_typescript.default.forEachChild(node, visit);
|
|
966
|
+
return seen;
|
|
967
|
+
}
|
|
968
|
+
__name(returnsJsx, "returnsJsx");
|
|
969
|
+
function signalNameOf(node) {
|
|
970
|
+
if (!import_typescript.default.isPropertyAccessExpression(node)) return void 0;
|
|
971
|
+
if (node.name.text !== "value") return void 0;
|
|
972
|
+
return node.expression.getText();
|
|
973
|
+
}
|
|
974
|
+
__name(signalNameOf, "signalNameOf");
|
|
975
|
+
function lineSnippet(source, node) {
|
|
976
|
+
const { line } = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
977
|
+
return (source.text.split(/\r?\n/u)[line] ?? "").trim();
|
|
978
|
+
}
|
|
979
|
+
__name(lineSnippet, "lineSnippet");
|
|
980
|
+
function diagnosticAt(source, file, node, rest) {
|
|
981
|
+
const { line, character } = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
982
|
+
return {
|
|
983
|
+
...rest,
|
|
984
|
+
file,
|
|
985
|
+
line: line + 1,
|
|
986
|
+
column: character + 1,
|
|
987
|
+
snippet: lineSnippet(source, node)
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
__name(diagnosticAt, "diagnosticAt");
|
|
991
|
+
var isWriteOperator = /* @__PURE__ */ __name((kind) => kind === import_typescript.default.SyntaxKind.EqualsToken || kind === import_typescript.default.SyntaxKind.PlusEqualsToken || kind === import_typescript.default.SyntaxKind.MinusEqualsToken || kind === import_typescript.default.SyntaxKind.AsteriskEqualsToken || kind === import_typescript.default.SyntaxKind.SlashEqualsToken, "isWriteOperator");
|
|
992
|
+
function ruleEffectSelfSubscription(source, file) {
|
|
993
|
+
const found = [];
|
|
994
|
+
const inspectEffectBody = /* @__PURE__ */ __name((body) => {
|
|
995
|
+
const reads = /* @__PURE__ */ new Map();
|
|
996
|
+
const writes = /* @__PURE__ */ new Map();
|
|
997
|
+
const visit2 = /* @__PURE__ */ __name((node, insideUntrack) => {
|
|
998
|
+
if (node !== body && import_typescript.default.isFunctionLike(node)) return;
|
|
999
|
+
const nextUntracked = insideUntrack || import_typescript.default.isCallExpression(node) && import_typescript.default.isIdentifier(node.expression) && node.expression.text === "untrack";
|
|
1000
|
+
if (import_typescript.default.isBinaryExpression(node) && isWriteOperator(node.operatorToken.kind)) {
|
|
1001
|
+
const name = signalNameOf(node.left);
|
|
1002
|
+
if (name !== void 0 && !nextUntracked) writes.set(name, node);
|
|
1003
|
+
} else if ((import_typescript.default.isPrefixUnaryExpression(node) || import_typescript.default.isPostfixUnaryExpression(node)) && (node.operator === import_typescript.default.SyntaxKind.PlusPlusToken || node.operator === import_typescript.default.SyntaxKind.MinusMinusToken)) {
|
|
1004
|
+
const name = signalNameOf(node.operand);
|
|
1005
|
+
if (name !== void 0) {
|
|
1006
|
+
if (!nextUntracked) writes.set(name, node);
|
|
1007
|
+
reads.set(name, node);
|
|
1008
|
+
}
|
|
1009
|
+
} else if (import_typescript.default.isCallExpression(node) && import_typescript.default.isPropertyAccessExpression(node.expression) && node.expression.name.text === "set") {
|
|
1010
|
+
if (!nextUntracked) writes.set(node.expression.expression.getText(), node);
|
|
1011
|
+
} else {
|
|
1012
|
+
const name = signalNameOf(node);
|
|
1013
|
+
if (name !== void 0) {
|
|
1014
|
+
const parent = node.parent;
|
|
1015
|
+
const isAssignmentTarget = import_typescript.default.isBinaryExpression(parent) && isWriteOperator(parent.operatorToken.kind) && parent.left === node;
|
|
1016
|
+
if (!isAssignmentTarget) reads.set(name, node);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
import_typescript.default.forEachChild(node, (child) => visit2(child, nextUntracked));
|
|
1020
|
+
}, "visit");
|
|
1021
|
+
visit2(body, false);
|
|
1022
|
+
for (const [name, writeNode] of writes) {
|
|
1023
|
+
if (!reads.has(name)) continue;
|
|
1024
|
+
found.push(diagnosticAt(source, file, writeNode, {
|
|
1025
|
+
code: VOBS_C210,
|
|
1026
|
+
severity: "error",
|
|
1027
|
+
message: `effect \u5199\u5165\u4E86\u5B83\u81EA\u5DF1\u4F9D\u8D56\u7684\u4FE1\u53F7 "${name}" \u2014\u2014 \u8FD9\u6B21\u5199\u5165\u4F1A\u628A\u5B83\u91CD\u65B0\u8C03\u5EA6\uFF0C\u5F62\u6210\u81EA\u8BA2\u9605\u5FAA\u73AF`,
|
|
1028
|
+
fix: `\u628A\u8FD9\u6B21\u5199\u5165\u5305\u8FDB untrack\uFF1Auntrack(() => { ${name}.value = next })\uFF1B\u5982\u679C\u8FD9\u4E2A effect \u672C\u6765\u5C31\u53EA\u8BE5\u505A\u526F\u4F5C\u7528\uFF0C\u68C0\u67E5\u662F\u4E0D\u662F\u8BEF\u8BFB\u4E86\u4E0D\u8BE5\u8BFB\u7684\u4FE1\u53F7\u3002`
|
|
1029
|
+
}));
|
|
1030
|
+
}
|
|
1031
|
+
}, "inspectEffectBody");
|
|
1032
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1033
|
+
if (import_typescript.default.isCallExpression(node) && import_typescript.default.isIdentifier(node.expression) && (node.expression.text === "effect" || node.expression.text === "renderEffect")) {
|
|
1034
|
+
const callback = node.arguments[0];
|
|
1035
|
+
if (callback !== void 0 && (import_typescript.default.isArrowFunction(callback) || import_typescript.default.isFunctionExpression(callback))) {
|
|
1036
|
+
inspectEffectBody(callback.body);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1040
|
+
}, "visit");
|
|
1041
|
+
visit(source);
|
|
1042
|
+
return found;
|
|
1043
|
+
}
|
|
1044
|
+
__name(ruleEffectSelfSubscription, "ruleEffectSelfSubscription");
|
|
1045
|
+
function isKeyedListCall(node) {
|
|
1046
|
+
if (!import_typescript.default.isCallExpression(node)) return false;
|
|
1047
|
+
if (!import_typescript.default.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "map") return false;
|
|
1048
|
+
const callback = node.arguments[0];
|
|
1049
|
+
return callback !== void 0 && import_typescript.default.isFunctionLike(callback) && returnsJsx(callback);
|
|
1050
|
+
}
|
|
1051
|
+
__name(isKeyedListCall, "isKeyedListCall");
|
|
1052
|
+
function ruleListInBranch(source, file) {
|
|
1053
|
+
const found = [];
|
|
1054
|
+
const message = "list \u5199\u5728\u4E09\u5143/&& \u7684\u5206\u652F\u91CC \u2014\u2014 \u4F1A\u8D70\u591A\u6001\u63D2\u5165\uFF0C\u5931\u53BB keyed \u590D\u7528";
|
|
1055
|
+
const fix = "\u628A list \u63D0\u6210**\u76F4\u63A5\u7684**\u5B50\u8868\u8FBE\u5F0F\uFF1A\u5148\u5199\u6761\u4EF6\u5206\u652F\uFF0C\u518D\u5355\u72EC\u5199 {items.map(...)}\u3002\u4E09\u5143\u91CC\u540C\u65F6\u6709\u8282\u70B9\u4E0E list \u65F6\uFF0Clist \u90A3\u4E00\u652F\u4E0D\u4F1A\u7F16\u8BD1\u6210 insertList\u3002";
|
|
1056
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1057
|
+
if (import_typescript.default.isConditionalExpression(node)) {
|
|
1058
|
+
for (const branch of [node.whenTrue, node.whenFalse]) {
|
|
1059
|
+
if (isKeyedListCall(branch)) {
|
|
1060
|
+
found.push(diagnosticAt(source, file, branch, { code: VOBS_C232, severity: "warning", message, fix }));
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
} else if (import_typescript.default.isBinaryExpression(node) && node.operatorToken.kind === import_typescript.default.SyntaxKind.AmpersandAmpersandToken && isKeyedListCall(node.right)) {
|
|
1064
|
+
found.push(diagnosticAt(source, file, node.right, { code: VOBS_C232, severity: "warning", message, fix }));
|
|
1065
|
+
}
|
|
1066
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1067
|
+
}, "visit");
|
|
1068
|
+
visit(source);
|
|
1069
|
+
return found;
|
|
1070
|
+
}
|
|
1071
|
+
__name(ruleListInBranch, "ruleListInBranch");
|
|
1072
|
+
function containsSignalRead(node) {
|
|
1073
|
+
let seen = false;
|
|
1074
|
+
const visit = /* @__PURE__ */ __name((child) => {
|
|
1075
|
+
if (seen) return;
|
|
1076
|
+
if (import_typescript.default.isFunctionLike(child)) return;
|
|
1077
|
+
if (signalNameOf(child) !== void 0) {
|
|
1078
|
+
seen = true;
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
import_typescript.default.forEachChild(child, visit);
|
|
1082
|
+
}, "visit");
|
|
1083
|
+
visit(node);
|
|
1084
|
+
return seen;
|
|
1085
|
+
}
|
|
1086
|
+
__name(containsSignalRead, "containsSignalRead");
|
|
1087
|
+
function ruleSignalCapturedInBody(source, file) {
|
|
1088
|
+
const found = [];
|
|
1089
|
+
const inspectComponent = /* @__PURE__ */ __name((fn) => {
|
|
1090
|
+
const body = fn.body;
|
|
1091
|
+
if (body === void 0 || !import_typescript.default.isBlock(body) || !returnsJsx(fn)) return;
|
|
1092
|
+
const captured = [];
|
|
1093
|
+
for (const statement of body.statements) {
|
|
1094
|
+
if (!import_typescript.default.isVariableStatement(statement)) continue;
|
|
1095
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1096
|
+
if (!import_typescript.default.isIdentifier(declaration.name) || declaration.initializer === void 0) continue;
|
|
1097
|
+
if (containsSignalRead(declaration.initializer)) {
|
|
1098
|
+
captured.push({ name: declaration.name.text, node: declaration });
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
if (captured.length === 0) return;
|
|
1103
|
+
const usedInJsx = /* @__PURE__ */ new Set();
|
|
1104
|
+
const visit2 = /* @__PURE__ */ __name((node) => {
|
|
1105
|
+
if (import_typescript.default.isJsxExpression(node) && node.expression !== void 0) {
|
|
1106
|
+
const scan = /* @__PURE__ */ __name((child) => {
|
|
1107
|
+
if (import_typescript.default.isIdentifier(child)) usedInJsx.add(child.text);
|
|
1108
|
+
import_typescript.default.forEachChild(child, scan);
|
|
1109
|
+
}, "scan");
|
|
1110
|
+
scan(node.expression);
|
|
1111
|
+
}
|
|
1112
|
+
import_typescript.default.forEachChild(node, visit2);
|
|
1113
|
+
}, "visit");
|
|
1114
|
+
visit2(body);
|
|
1115
|
+
for (const item of captured) {
|
|
1116
|
+
if (!usedInJsx.has(item.name)) continue;
|
|
1117
|
+
found.push(diagnosticAt(source, file, item.node, {
|
|
1118
|
+
code: VOBS_C118,
|
|
1119
|
+
severity: "warning",
|
|
1120
|
+
message: `\u7EC4\u4EF6\u4F53\u91CC\u8BFB\u4E86\u4FE1\u53F7\u5E76\u5B58\u8FDB "${item.name}" \u2014\u2014 \u7EC4\u4EF6\u4F53\u53EA\u6267\u884C\u4E00\u6B21\uFF0C\u8FD9\u4E2A\u503C\u4E4B\u540E\u6C38\u8FDC\u4E0D\u4F1A\u66F4\u65B0`,
|
|
1121
|
+
fix: `\u628A\u8BFB\u53D6\u653E\u8FDB\u52A8\u6001\u8868\u8FBE\u5F0F\uFF08\u76F4\u63A5\u5728 JSX \u91CC\u7528 .value\uFF09\uFF0C\u6216\u6539\u6210 memo \u6D3E\u751F\u503C\uFF1Aconst ${item.name} = memo(() => ...)\u3002`
|
|
1122
|
+
}));
|
|
1123
|
+
}
|
|
1124
|
+
}, "inspectComponent");
|
|
1125
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1126
|
+
if (import_typescript.default.isFunctionDeclaration(node) || import_typescript.default.isFunctionExpression(node) || import_typescript.default.isArrowFunction(node)) {
|
|
1127
|
+
inspectComponent(node);
|
|
1128
|
+
}
|
|
1129
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1130
|
+
}, "visit");
|
|
1131
|
+
visit(source);
|
|
1132
|
+
return found;
|
|
1133
|
+
}
|
|
1134
|
+
__name(ruleSignalCapturedInBody, "ruleSignalCapturedInBody");
|
|
1135
|
+
var IGNORE_NEXT_LINE = /vobs-check-ignore-next-line/u;
|
|
1136
|
+
function suppressedLines(text5) {
|
|
1137
|
+
const suppressed = /* @__PURE__ */ new Set();
|
|
1138
|
+
const lines = text5.split(/\r?\n/u);
|
|
1139
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1140
|
+
if (IGNORE_NEXT_LINE.test(lines[index])) suppressed.add(index + 2);
|
|
1141
|
+
}
|
|
1142
|
+
return suppressed;
|
|
1143
|
+
}
|
|
1144
|
+
__name(suppressedLines, "suppressedLines");
|
|
1145
|
+
function analyzeSource(text5, file) {
|
|
1146
|
+
const source = import_typescript.default.createSourceFile(file, text5, import_typescript.default.ScriptTarget.Latest, true, import_typescript.default.ScriptKind.TSX);
|
|
1147
|
+
const suppressed = suppressedLines(text5);
|
|
1148
|
+
return [
|
|
1149
|
+
...ruleEffectSelfSubscription(source, file),
|
|
1150
|
+
...ruleListInBranch(source, file),
|
|
1151
|
+
...ruleSignalCapturedInBody(source, file)
|
|
1152
|
+
].filter((item) => !suppressed.has(item.line)).sort((a, b) => a.line - b.line || a.column - b.column);
|
|
1153
|
+
}
|
|
1154
|
+
__name(analyzeSource, "analyzeSource");
|
|
1155
|
+
async function checkCommand(options = {}) {
|
|
1156
|
+
const root = import_node_path6.default.resolve(options.dir ?? process.cwd());
|
|
1157
|
+
let all;
|
|
1158
|
+
try {
|
|
1159
|
+
all = await collectSources(root);
|
|
1160
|
+
} catch (error2) {
|
|
1161
|
+
logger.error(error2 instanceof Error ? error2.message : String(error2));
|
|
1162
|
+
process.exitCode = 1;
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const files = options.includeTests === true ? all : all.filter((file) => !TEST_FILE.test(import_node_path6.default.relative(root, file).split(import_node_path6.default.sep).join("/")));
|
|
1166
|
+
const skipped = all.length - files.length;
|
|
1167
|
+
const diagnostics = [];
|
|
1168
|
+
for (const absolute of files) {
|
|
1169
|
+
const text5 = await (0, import_promises2.readFile)(absolute, "utf8");
|
|
1170
|
+
const relative2 = import_node_path6.default.relative(root, absolute).split(import_node_path6.default.sep).join("/");
|
|
1171
|
+
diagnostics.push(...analyzeSource(text5, relative2));
|
|
1172
|
+
}
|
|
1173
|
+
const errors = diagnostics.filter((item) => item.severity === "error");
|
|
1174
|
+
const report = { root, files: files.length, skippedTests: skipped, diagnostics };
|
|
1175
|
+
if (options.write === true) {
|
|
1176
|
+
const target = import_node_path6.default.join(root, REPORT_PATH);
|
|
1177
|
+
await (0, import_promises2.mkdir)(import_node_path6.default.dirname(target), { recursive: true });
|
|
1178
|
+
await (0, import_promises2.writeFile)(target, `${JSON.stringify(report, null, 2)}
|
|
1179
|
+
`, "utf8");
|
|
1180
|
+
logger.info(`\u62A5\u544A\u5199\u5165 ${REPORT_PATH}\uFF08\u5F00\u53D1\u53F0\u9762\u677F\u8BFB\u5B83\u663E\u793A\u300C\u9879\u76EE\u300D\u9875\uFF09`);
|
|
1181
|
+
}
|
|
1182
|
+
if (options.json === true) {
|
|
1183
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1184
|
+
if (errors.length > 0) process.exitCode = 1;
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
if (diagnostics.length === 0) {
|
|
1188
|
+
logger.success(`\u68C0\u67E5\u901A\u8FC7 \u2014\u2014 ${files.length} \u4E2A\u6587\u4EF6${skipped > 0 ? `\uFF08\u8DF3\u8FC7 ${skipped} \u4E2A\u6D4B\u8BD5\u6587\u4EF6\uFF09` : ""}\uFF0C\u6CA1\u6709\u53D1\u73B0\u95EE\u9898`);
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
console.log("");
|
|
1192
|
+
for (const item of diagnostics) {
|
|
1193
|
+
const mark = item.severity === "error" ? "\u2716" : "!";
|
|
1194
|
+
console.log(` ${mark} ${item.file}:${item.line}:${item.column} ${item.code}`);
|
|
1195
|
+
console.log(` ${item.message}`);
|
|
1196
|
+
if (item.snippet !== "") console.log(` ${item.snippet}`);
|
|
1197
|
+
console.log(` \u2192 ${item.fix}`);
|
|
1198
|
+
console.log("");
|
|
1199
|
+
}
|
|
1200
|
+
const warnings = diagnostics.length - errors.length;
|
|
1201
|
+
console.log(
|
|
1202
|
+
` ${errors.length} \u4E2A\u9519\u8BEF \xB7 ${warnings} \u4E2A\u8B66\u544A \xB7 \u5171\u68C0\u67E5 ${files.length} \u4E2A\u6587\u4EF6${skipped > 0 ? `\uFF08\u8DF3\u8FC7 ${skipped} \u4E2A\u6D4B\u8BD5\u6587\u4EF6\uFF0C\u7528 --include-tests \u7EB3\u5165\uFF09` : ""}
|
|
1203
|
+
`
|
|
1204
|
+
);
|
|
1205
|
+
if (errors.length > 0) process.exitCode = 1;
|
|
1206
|
+
}
|
|
1207
|
+
__name(checkCommand, "checkCommand");
|
|
1208
|
+
|
|
891
1209
|
// packages/cli/src/banner.ts
|
|
892
|
-
var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC}
|
|
1210
|
+
var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC}";
|
|
893
1211
|
var BANNER_TAGLINE = "Signals First \xB7 Zero Re-renders \xB7 Ultra Lightweight";
|
|
894
1212
|
var INDENT = " ";
|
|
895
1213
|
var DIM = "\x1B[2m";
|
|
@@ -905,12 +1223,12 @@ function showLogo() {
|
|
|
905
1223
|
}
|
|
906
1224
|
__name(showLogo, "showLogo");
|
|
907
1225
|
function showBanner() {
|
|
908
|
-
console.log(`${INDENT}${BANNER_LINE1}`);
|
|
1226
|
+
console.log(`${INDENT}${BANNER_LINE1} v${cliVersion()}`);
|
|
909
1227
|
}
|
|
910
1228
|
__name(showBanner, "showBanner");
|
|
911
1229
|
function showDevBanner() {
|
|
912
1230
|
console.log();
|
|
913
|
-
console.log(`${INDENT}${BANNER_LINE1}`);
|
|
1231
|
+
console.log(`${INDENT}${BANNER_LINE1} v${cliVersion()}`);
|
|
914
1232
|
console.log();
|
|
915
1233
|
}
|
|
916
1234
|
__name(showDevBanner, "showDevBanner");
|
|
@@ -964,6 +1282,14 @@ function createCLI() {
|
|
|
964
1282
|
dev: options.dev
|
|
965
1283
|
});
|
|
966
1284
|
});
|
|
1285
|
+
cli.command("check [dir]", "\u9759\u6001\u68C0\u67E5\u6E90\u7801\uFF1Aeffect \u81EA\u8BA2\u9605 / \u5217\u8868\u5199\u8FDB\u5206\u652F / \u7EC4\u4EF6\u4F53\u91CC\u8BFB\u4FE1\u53F7\uFF08\u884C\u5185\u6291\u5236\uFF1A\u4E0A\u4E00\u884C\u5199 // vobs-check-ignore-next-line\uFF09").option("--json", "\u4EE5 JSON \u8F93\u51FA\uFF08\u7ED9 AI \u4E0E\u5DE5\u5177\u6D88\u8D39\uFF09").option("--write", `\u628A\u7ED3\u679C\u5199\u5230 ${".vobs/check.json"}\uFF08\u5F00\u53D1\u53F0\u9762\u677F\u8BFB\u5B83\uFF09`).option("--include-tests", "\u628A\u6D4B\u8BD5\u6587\u4EF6\u4E5F\u7EB3\u5165\u68C0\u67E5\uFF08\u9ED8\u8BA4\u8DF3\u8FC7\uFF09").action(async (dir, options) => {
|
|
1286
|
+
await checkCommand({
|
|
1287
|
+
dir,
|
|
1288
|
+
json: options.json === true,
|
|
1289
|
+
write: options.write === true,
|
|
1290
|
+
includeTests: options.includeTests === true
|
|
1291
|
+
});
|
|
1292
|
+
});
|
|
967
1293
|
cli.command("dsh [action] [target]", "DSH \u63D2\u4EF6\u5DE5\u5177\u94FE\uFF08init / dev / build / check / install\uFF09").option("--dir <dir>", "init\uFF1A\u76EE\u6807\u76EE\u5F55").option("--pm <pm>", "init\uFF1A\u5305\u7BA1\u7406\u5668\uFF08pnpm/npm\uFF09").option("--port <port>", "dev\uFF1A\u9884\u89C8\u7AEF\u53E3", { default: 5199 }).option("--profile <name>", "install\uFF1ADSH profile \u540D", { default: "desktop" }).option("--spec <spec>", "install\uFF1A\u5B8C\u6574\u5B89\u88C5 spec").option("--repo <owner/name>", "install\uFF1AGitHub owner/name").option("--tag <ref>", "install\uFF1AGit tag / \u5206\u652F / commit").option("--subpath <path>", "install\uFF1A\u4ED3\u5E93\u5185\u5B50\u76EE\u5F55").option("--from <path>", "install\uFF1A\u4ECE\u672C\u5730\u76EE\u5F55\u5B89\u88C5").option("--dry", "install\uFF1A\u53EA\u6253\u5370\u547D\u4EE4\uFF0C\u4E0D\u6267\u884C").action(async (action, target, options) => {
|
|
968
1294
|
await dshCommand(action, target, {
|
|
969
1295
|
dir: options.dir,
|
|
@@ -985,18 +1311,30 @@ function createCLI() {
|
|
|
985
1311
|
showBanner();
|
|
986
1312
|
});
|
|
987
1313
|
cli.help();
|
|
988
|
-
cli.version(
|
|
1314
|
+
cli.version(cliVersion());
|
|
989
1315
|
return cli;
|
|
990
1316
|
}
|
|
991
1317
|
__name(createCLI, "createCLI");
|
|
1318
|
+
var KNOWN_SUBCOMMANDS = [
|
|
1319
|
+
"init",
|
|
1320
|
+
"create",
|
|
1321
|
+
"dev",
|
|
1322
|
+
"build",
|
|
1323
|
+
"generate",
|
|
1324
|
+
"g",
|
|
1325
|
+
"add",
|
|
1326
|
+
"check",
|
|
1327
|
+
"dsh",
|
|
1328
|
+
"logo"
|
|
1329
|
+
];
|
|
992
1330
|
|
|
993
1331
|
// packages/cli/src/repl.ts
|
|
994
|
-
var
|
|
1332
|
+
var import_promises3 = require("readline/promises");
|
|
995
1333
|
var import_node_process = require("process");
|
|
996
1334
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
997
1335
|
async function startRepl() {
|
|
998
1336
|
showLogo();
|
|
999
|
-
const rl = (0,
|
|
1337
|
+
const rl = (0, import_promises3.createInterface)({
|
|
1000
1338
|
input: import_node_process.stdin,
|
|
1001
1339
|
output: import_node_process.stdout,
|
|
1002
1340
|
prompt: ` ${import_picocolors2.default.magenta("\u276F")} `,
|
|
@@ -1107,16 +1445,52 @@ function splitArgs(line) {
|
|
|
1107
1445
|
__name(splitArgs, "splitArgs");
|
|
1108
1446
|
|
|
1109
1447
|
// packages/cli/src/start.ts
|
|
1448
|
+
var META_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
|
|
1449
|
+
function isFlag(token) {
|
|
1450
|
+
return token.startsWith("-") && token !== "-";
|
|
1451
|
+
}
|
|
1452
|
+
__name(isFlag, "isFlag");
|
|
1110
1453
|
async function start(args) {
|
|
1111
1454
|
if (args.length === 0 || args[0] === "cli") {
|
|
1112
1455
|
await startRepl();
|
|
1113
1456
|
return;
|
|
1114
1457
|
}
|
|
1115
|
-
|
|
1458
|
+
const first = args[0];
|
|
1459
|
+
const hasSubcommand = KNOWN_SUBCOMMANDS.includes(first);
|
|
1460
|
+
if (!hasSubcommand && (args.includes("--version") || args.includes("-V"))) {
|
|
1116
1461
|
showBanner();
|
|
1117
1462
|
return;
|
|
1118
1463
|
}
|
|
1119
|
-
|
|
1464
|
+
if (!hasSubcommand && !isFlag(first)) {
|
|
1465
|
+
process.stderr.write(`\u2716 \u672A\u77E5\u547D\u4EE4\uFF1A${first}
|
|
1466
|
+
|
|
1467
|
+
`);
|
|
1468
|
+
try {
|
|
1469
|
+
createCLI().parse(["node", "vobs", "--help"]);
|
|
1470
|
+
} catch {
|
|
1471
|
+
}
|
|
1472
|
+
process.exitCode = 1;
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
if (!hasSubcommand && isFlag(first) && !META_FLAGS.has(first)) {
|
|
1476
|
+
process.stderr.write(`\u2716 \u672A\u77E5\u9009\u9879\uFF1A${first}
|
|
1477
|
+
|
|
1478
|
+
`);
|
|
1479
|
+
try {
|
|
1480
|
+
createCLI().parse(["node", "vobs", "--help"]);
|
|
1481
|
+
} catch {
|
|
1482
|
+
}
|
|
1483
|
+
process.exitCode = 1;
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
try {
|
|
1487
|
+
createCLI().parse();
|
|
1488
|
+
} catch (error2) {
|
|
1489
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
1490
|
+
process.stderr.write(`\u2716 ${message}
|
|
1491
|
+
`);
|
|
1492
|
+
process.exitCode = 1;
|
|
1493
|
+
}
|
|
1120
1494
|
}
|
|
1121
1495
|
__name(start, "start");
|
|
1122
1496
|
// Annotate the CommonJS export names for ESM import in node:
|