@vobs/cli 1.7.7 → 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 +364 -24
- 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 +354 -15
- 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 +4 -4
- package/dist/commands/dsh.cjs.map +1 -1
- package/dist/commands/dsh.js +4 -4
- 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 +36 -19
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.js +27 -10
- 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 +402 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +391 -17
- 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 +402 -28
- 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 +391 -17
- 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 +31 -3
- package/src/commands/check.test.ts +238 -0
- package/src/commands/check.ts +461 -0
- package/src/commands/dsh.ts +4 -2
- 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/index.cjs
CHANGED
|
@@ -69,7 +69,7 @@ function timestamp() {
|
|
|
69
69
|
}
|
|
70
70
|
__name(timestamp, "timestamp");
|
|
71
71
|
function info(msg) {
|
|
72
|
-
console.
|
|
72
|
+
console.error(`${timestamp()} ${import_picocolors.default.cyan("\u2139")} ${msg}`);
|
|
73
73
|
}
|
|
74
74
|
__name(info, "info");
|
|
75
75
|
function success(msg) {
|
|
@@ -77,7 +77,7 @@ function success(msg) {
|
|
|
77
77
|
}
|
|
78
78
|
__name(success, "success");
|
|
79
79
|
function warn(msg) {
|
|
80
|
-
console.
|
|
80
|
+
console.error(`${timestamp()} ${import_picocolors.default.yellow("\u26A0")} ${msg}`);
|
|
81
81
|
}
|
|
82
82
|
__name(warn, "warn");
|
|
83
83
|
function error(msg) {
|
|
@@ -181,6 +181,23 @@ function addPackage(targetDir, pm, pkg, dev) {
|
|
|
181
181
|
}
|
|
182
182
|
__name(addPackage, "addPackage");
|
|
183
183
|
|
|
184
|
+
// packages/cli/src/version.ts
|
|
185
|
+
var import_node_fs3 = require("fs");
|
|
186
|
+
var cached;
|
|
187
|
+
function cliVersion() {
|
|
188
|
+
if (cached !== void 0) return cached;
|
|
189
|
+
try {
|
|
190
|
+
const manifest = JSON.parse(
|
|
191
|
+
(0, import_node_fs3.readFileSync)(new URL("../package.json", __VOBS_CJS_FILE_URL), "utf8")
|
|
192
|
+
);
|
|
193
|
+
cached = manifest.version ?? "0.0.0";
|
|
194
|
+
} catch {
|
|
195
|
+
cached = "0.0.0";
|
|
196
|
+
}
|
|
197
|
+
return cached;
|
|
198
|
+
}
|
|
199
|
+
__name(cliVersion, "cliVersion");
|
|
200
|
+
|
|
184
201
|
// packages/cli/src/commands/init.ts
|
|
185
202
|
async function initCommand(options) {
|
|
186
203
|
const projectName = options.name || await p.text({
|
|
@@ -226,7 +243,7 @@ async function initCommand(options) {
|
|
|
226
243
|
name: projectName,
|
|
227
244
|
packageName: projectName.toLowerCase().replace(/\s+/g, "-"),
|
|
228
245
|
typescript: useTypescript,
|
|
229
|
-
vobsVersion:
|
|
246
|
+
vobsVersion: cliVersion()
|
|
230
247
|
});
|
|
231
248
|
logger.success("Project scaffolded");
|
|
232
249
|
logger.step("Installing dependencies...");
|
|
@@ -378,7 +395,7 @@ async function addCommand(options) {
|
|
|
378
395
|
__name(addCommand, "addCommand");
|
|
379
396
|
|
|
380
397
|
// packages/cli/src/commands/dsh.ts
|
|
381
|
-
var
|
|
398
|
+
var import_node_fs4 = require("fs");
|
|
382
399
|
var import_promises = require("fs/promises");
|
|
383
400
|
var import_node_child_process3 = require("child_process");
|
|
384
401
|
var import_node_http = require("http");
|
|
@@ -389,7 +406,7 @@ var PLATFORM_MODULES = ["react", "react-dom"];
|
|
|
389
406
|
var vobsVersion = /* @__PURE__ */ __name(() => {
|
|
390
407
|
try {
|
|
391
408
|
const manifest = JSON.parse(
|
|
392
|
-
(0,
|
|
409
|
+
(0, import_node_fs4.readFileSync)(new URL("../../package.json", __VOBS_CJS_FILE_URL), "utf8")
|
|
393
410
|
);
|
|
394
411
|
return manifest.version ?? "1.7.5";
|
|
395
412
|
} catch {
|
|
@@ -431,7 +448,7 @@ async function dshInitCommand(target, options) {
|
|
|
431
448
|
"dsh-plugin"
|
|
432
449
|
);
|
|
433
450
|
ensureDir(targetDir);
|
|
434
|
-
(0,
|
|
451
|
+
(0, import_node_fs4.writeFileSync)(
|
|
435
452
|
(0, import_node_path5.resolve)(targetDir, ".gitignore"),
|
|
436
453
|
["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"),
|
|
437
454
|
"utf8"
|
|
@@ -458,7 +475,7 @@ __name(dshInitCommand, "dshInitCommand");
|
|
|
458
475
|
async function dshBuildCommand() {
|
|
459
476
|
const projectDir = process.cwd();
|
|
460
477
|
const configFile = (0, import_node_path5.resolve)(projectDir, "vite.config.ts");
|
|
461
|
-
if (!(0,
|
|
478
|
+
if (!(0, import_node_fs4.existsSync)(configFile)) {
|
|
462
479
|
logger.error("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 vite.config.ts\uFF0C\u8BF7\u5728\u63D2\u4EF6\u9879\u76EE\u6839\u76EE\u5F55\u8FD0\u884C\u3002");
|
|
463
480
|
process.exitCode = 1;
|
|
464
481
|
return;
|
|
@@ -481,7 +498,7 @@ async function dshBuildCommand() {
|
|
|
481
498
|
logger.info("\u6784\u5EFA Host \u4EA7\u7269 \u2026");
|
|
482
499
|
const hostTarget = (0, import_node_path5.resolve)(projectDir, hostEntry.replace(/^\.\//u, ""));
|
|
483
500
|
const hostEntrySource = (0, import_node_path5.resolve)(projectDir, "src", "host", "index.ts");
|
|
484
|
-
if (!(0,
|
|
501
|
+
if (!(0, import_node_fs4.existsSync)(hostEntrySource)) {
|
|
485
502
|
logger.warn(`\u6CA1\u6709\u627E\u5230 ${hostEntrySource}\uFF0C\u8DF3\u8FC7 Host \u6784\u5EFA\u3002`);
|
|
486
503
|
return;
|
|
487
504
|
}
|
|
@@ -594,7 +611,7 @@ async function dshDevCommand(options) {
|
|
|
594
611
|
packageRoot = (0, import_node_path5.dirname)((0, import_node_path5.dirname)(projectRequire.resolve("@vobs/dsh")));
|
|
595
612
|
}
|
|
596
613
|
const candidate = (0, import_node_path5.join)(packageRoot, "dist", "preview.js");
|
|
597
|
-
previewFile = (0,
|
|
614
|
+
previewFile = (0, import_node_fs4.existsSync)(candidate) ? candidate : void 0;
|
|
598
615
|
} catch {
|
|
599
616
|
previewFile = void 0;
|
|
600
617
|
}
|
|
@@ -666,7 +683,7 @@ data: 1
|
|
|
666
683
|
return;
|
|
667
684
|
}
|
|
668
685
|
if (url === "/client.js") {
|
|
669
|
-
if (!(0,
|
|
686
|
+
if (!(0, import_node_fs4.existsSync)(clientFile)) {
|
|
670
687
|
response.writeHead(503, { "content-type": "text/plain; charset=utf-8" });
|
|
671
688
|
response.end(`\u8FD8\u6CA1\u6709\u4EA7\u7269\uFF1A${clientEntry}
|
|
672
689
|
${buildError ?? ""}`);
|
|
@@ -687,7 +704,7 @@ ${buildError ?? ""}`);
|
|
|
687
704
|
__name(dshDevCommand, "dshDevCommand");
|
|
688
705
|
function readManifest(dir) {
|
|
689
706
|
try {
|
|
690
|
-
return JSON.parse((0,
|
|
707
|
+
return JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path5.resolve)(dir, "package.json"), "utf8"));
|
|
691
708
|
} catch {
|
|
692
709
|
return void 0;
|
|
693
710
|
}
|
|
@@ -710,10 +727,10 @@ function collectIssues(dir) {
|
|
|
710
727
|
result.errors.push("\u7F3A\u5C11 dsh.bundle.patch \u2014\u2014 DSH \u4E0D\u4F1A\u628A\u8FD9\u4E2A\u5305\u5F53\u4F5C\u7EC4\u5408\u5305\uFF08bundle\uFF09");
|
|
711
728
|
} else {
|
|
712
729
|
const patchPath = (0, import_node_path5.resolve)(dir, bundle.patch.replace(/^\.\//u, ""));
|
|
713
|
-
if (!(0,
|
|
730
|
+
if (!(0, import_node_fs4.existsSync)(patchPath)) {
|
|
714
731
|
result.errors.push(`dsh.bundle.patch \u6307\u5411\u7684 ${bundle.patch} \u4E0D\u5B58\u5728`);
|
|
715
732
|
} else {
|
|
716
|
-
const text5 = (0,
|
|
733
|
+
const text5 = (0, import_node_fs4.readFileSync)(patchPath, "utf8");
|
|
717
734
|
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");
|
|
718
735
|
else if (name !== "" && !text5.includes(name)) {
|
|
719
736
|
result.warnings.push(`cordis.patch.yml \u91CC\u6CA1\u6709\u51FA\u73B0\u5305\u540D ${name}\uFF0C\u786E\u8BA4 insert \u7684 name \u5199\u5BF9\u4E86`);
|
|
@@ -727,7 +744,7 @@ function collectIssues(dir) {
|
|
|
727
744
|
const hostEntry = exportsField["."];
|
|
728
745
|
const clientEntry = exportsField["./client"];
|
|
729
746
|
if (typeof hostEntry !== "string") result.errors.push('exports["."] \u672A\u58F0\u660E \u2014\u2014 DSH \u52A0\u8F7D\u4E0D\u5230 Host \u4FA7\u63D2\u4EF6');
|
|
730
|
-
else if (!(0,
|
|
747
|
+
else if (!(0, import_node_fs4.existsSync)((0, import_node_path5.resolve)(dir, hostEntry.replace(/^\.\//u, "")))) {
|
|
731
748
|
result.errors.push(`exports["."] \u6307\u5411\u7684 ${hostEntry} \u4E0D\u5B58\u5728\uFF0C\u5148\u6784\u5EFA`);
|
|
732
749
|
} else result.passed.push("Host \u5165\u53E3\u5B58\u5728");
|
|
733
750
|
if (typeof clientEntry !== "string") result.errors.push('exports["./client"] \u672A\u58F0\u660E \u2014\u2014 \u9875\u9762\u62FF\u4E0D\u5230\u5BA2\u6237\u7AEF bundle');
|
|
@@ -745,10 +762,10 @@ function collectIssues(dir) {
|
|
|
745
762
|
} else result.passed.push("\u6CA1\u6709 workspace: \u534F\u8BAE\u4F9D\u8D56");
|
|
746
763
|
if (typeof clientEntry === "string") {
|
|
747
764
|
const clientPath = (0, import_node_path5.resolve)(dir, clientEntry.replace(/^\.\//u, ""));
|
|
748
|
-
if (!(0,
|
|
765
|
+
if (!(0, import_node_fs4.existsSync)(clientPath)) {
|
|
749
766
|
result.errors.push(`\u5BA2\u6237\u7AEF\u4EA7\u7269 ${clientEntry} \u4E0D\u5B58\u5728\uFF0C\u5148\u8FD0\u884C\u6784\u5EFA`);
|
|
750
767
|
} else {
|
|
751
|
-
const code = (0,
|
|
768
|
+
const code = (0, import_node_fs4.readFileSync)(clientPath, "utf8");
|
|
752
769
|
const loads = (code.match(/__ModuleLoader__\.load\(/gu) ?? []).length;
|
|
753
770
|
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`);
|
|
754
771
|
else result.passed.push("\u4EA7\u7269\u5F62\u6001\u662F DSH \u5BA2\u6237\u7AEF\u6A21\u5757\u534F\u8BAE");
|
|
@@ -799,7 +816,7 @@ function buildInstallSpec(options) {
|
|
|
799
816
|
if (options.spec !== void 0) return { spec: options.spec };
|
|
800
817
|
if (options.from !== void 0) {
|
|
801
818
|
const target = (0, import_node_path5.resolve)(options.from);
|
|
802
|
-
if (!(0,
|
|
819
|
+
if (!(0, import_node_fs4.existsSync)(target)) return { error: `--from \u6307\u5411\u7684\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${target}` };
|
|
803
820
|
return { spec: target };
|
|
804
821
|
}
|
|
805
822
|
if (options.repo !== void 0) {
|
|
@@ -896,18 +913,319 @@ async function dshCommand(action, target, options) {
|
|
|
896
913
|
dshInstallCommand(options);
|
|
897
914
|
return;
|
|
898
915
|
default:
|
|
899
|
-
logger.error(`\u672A\u77E5\u5B50\u547D\u4EE4: ${action
|
|
916
|
+
if (action !== void 0 && action !== "") logger.error(`\u672A\u77E5\u5B50\u547D\u4EE4: ${action}`);
|
|
900
917
|
console.log("\n \u53EF\u7528\u5B50\u547D\u4EE4\uFF1A");
|
|
901
918
|
for (const [name, description] of Object.entries(ACTIONS)) {
|
|
902
919
|
console.log(` vobs dsh ${name.padEnd(8)} ${description}`);
|
|
903
920
|
}
|
|
904
|
-
process.exitCode = 1;
|
|
921
|
+
if (action !== void 0 && action !== "") process.exitCode = 1;
|
|
905
922
|
}
|
|
906
923
|
}
|
|
907
924
|
__name(dshCommand, "dshCommand");
|
|
908
925
|
|
|
926
|
+
// packages/cli/src/commands/check.ts
|
|
927
|
+
var import_promises2 = require("fs/promises");
|
|
928
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
929
|
+
var import_typescript = __toESM(require("typescript"), 1);
|
|
930
|
+
var REPORT_PATH = ".vobs/check.json";
|
|
931
|
+
var TEST_FILE = /(?:^|\/)(?:[^/]*\.(?:test|spec)\.tsx?|__tests__\/)/u;
|
|
932
|
+
var VOBS_C210 = "VOBS_C210";
|
|
933
|
+
var VOBS_C232 = "VOBS_C232";
|
|
934
|
+
var VOBS_C118 = "VOBS_C118";
|
|
935
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "lib", "build", ".git", ".vobs", "coverage"]);
|
|
936
|
+
async function collectSources(root) {
|
|
937
|
+
let rootStat;
|
|
938
|
+
try {
|
|
939
|
+
rootStat = await (0, import_promises2.stat)(root);
|
|
940
|
+
} catch {
|
|
941
|
+
throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
942
|
+
}
|
|
943
|
+
if (!rootStat.isDirectory()) {
|
|
944
|
+
throw new Error(`\u4E0D\u662F\u76EE\u5F55\uFF1A${root}\uFF08vobs check \u63A5\u53D7\u4E00\u4E2A\u76EE\u5F55\uFF09`);
|
|
945
|
+
}
|
|
946
|
+
const found = [];
|
|
947
|
+
const walk = /* @__PURE__ */ __name(async (dir) => {
|
|
948
|
+
let entries;
|
|
949
|
+
try {
|
|
950
|
+
entries = await (0, import_promises2.readdir)(dir, { withFileTypes: true });
|
|
951
|
+
} catch (error2) {
|
|
952
|
+
if (dir === root) {
|
|
953
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF1A${root}\uFF08${error2 instanceof Error ? error2.message : String(error2)}\uFF09`);
|
|
954
|
+
}
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
for (const entry of entries) {
|
|
958
|
+
if (entry.isDirectory()) {
|
|
959
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
960
|
+
await walk(import_node_path6.default.join(dir, entry.name));
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
if (!entry.isFile()) continue;
|
|
964
|
+
if (!/\.tsx?$/u.test(entry.name) || entry.name.endsWith(".d.ts")) continue;
|
|
965
|
+
found.push(import_node_path6.default.join(dir, entry.name));
|
|
966
|
+
}
|
|
967
|
+
}, "walk");
|
|
968
|
+
await walk(root);
|
|
969
|
+
return found.sort();
|
|
970
|
+
}
|
|
971
|
+
__name(collectSources, "collectSources");
|
|
972
|
+
function returnsJsx(node) {
|
|
973
|
+
let seen = false;
|
|
974
|
+
const visit = /* @__PURE__ */ __name((child) => {
|
|
975
|
+
if (seen) return;
|
|
976
|
+
if (import_typescript.default.isJsxElement(child) || import_typescript.default.isJsxSelfClosingElement(child) || import_typescript.default.isJsxFragment(child)) {
|
|
977
|
+
seen = true;
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (child !== node && import_typescript.default.isFunctionLike(child)) return;
|
|
981
|
+
import_typescript.default.forEachChild(child, visit);
|
|
982
|
+
}, "visit");
|
|
983
|
+
import_typescript.default.forEachChild(node, visit);
|
|
984
|
+
return seen;
|
|
985
|
+
}
|
|
986
|
+
__name(returnsJsx, "returnsJsx");
|
|
987
|
+
function signalNameOf(node) {
|
|
988
|
+
if (!import_typescript.default.isPropertyAccessExpression(node)) return void 0;
|
|
989
|
+
if (node.name.text !== "value") return void 0;
|
|
990
|
+
return node.expression.getText();
|
|
991
|
+
}
|
|
992
|
+
__name(signalNameOf, "signalNameOf");
|
|
993
|
+
function lineSnippet(source, node) {
|
|
994
|
+
const { line } = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
995
|
+
return (source.text.split(/\r?\n/u)[line] ?? "").trim();
|
|
996
|
+
}
|
|
997
|
+
__name(lineSnippet, "lineSnippet");
|
|
998
|
+
function diagnosticAt(source, file, node, rest) {
|
|
999
|
+
const { line, character } = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
1000
|
+
return {
|
|
1001
|
+
...rest,
|
|
1002
|
+
file,
|
|
1003
|
+
line: line + 1,
|
|
1004
|
+
column: character + 1,
|
|
1005
|
+
snippet: lineSnippet(source, node)
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
__name(diagnosticAt, "diagnosticAt");
|
|
1009
|
+
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");
|
|
1010
|
+
function ruleEffectSelfSubscription(source, file) {
|
|
1011
|
+
const found = [];
|
|
1012
|
+
const inspectEffectBody = /* @__PURE__ */ __name((body) => {
|
|
1013
|
+
const reads = /* @__PURE__ */ new Map();
|
|
1014
|
+
const writes = /* @__PURE__ */ new Map();
|
|
1015
|
+
const visit2 = /* @__PURE__ */ __name((node, insideUntrack) => {
|
|
1016
|
+
if (node !== body && import_typescript.default.isFunctionLike(node)) return;
|
|
1017
|
+
const nextUntracked = insideUntrack || import_typescript.default.isCallExpression(node) && import_typescript.default.isIdentifier(node.expression) && node.expression.text === "untrack";
|
|
1018
|
+
if (import_typescript.default.isBinaryExpression(node) && isWriteOperator(node.operatorToken.kind)) {
|
|
1019
|
+
const name = signalNameOf(node.left);
|
|
1020
|
+
if (name !== void 0 && !nextUntracked) writes.set(name, node);
|
|
1021
|
+
} 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)) {
|
|
1022
|
+
const name = signalNameOf(node.operand);
|
|
1023
|
+
if (name !== void 0) {
|
|
1024
|
+
if (!nextUntracked) writes.set(name, node);
|
|
1025
|
+
reads.set(name, node);
|
|
1026
|
+
}
|
|
1027
|
+
} else if (import_typescript.default.isCallExpression(node) && import_typescript.default.isPropertyAccessExpression(node.expression) && node.expression.name.text === "set") {
|
|
1028
|
+
if (!nextUntracked) writes.set(node.expression.expression.getText(), node);
|
|
1029
|
+
} else {
|
|
1030
|
+
const name = signalNameOf(node);
|
|
1031
|
+
if (name !== void 0) {
|
|
1032
|
+
const parent = node.parent;
|
|
1033
|
+
const isAssignmentTarget = import_typescript.default.isBinaryExpression(parent) && isWriteOperator(parent.operatorToken.kind) && parent.left === node;
|
|
1034
|
+
if (!isAssignmentTarget) reads.set(name, node);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
import_typescript.default.forEachChild(node, (child) => visit2(child, nextUntracked));
|
|
1038
|
+
}, "visit");
|
|
1039
|
+
visit2(body, false);
|
|
1040
|
+
for (const [name, writeNode] of writes) {
|
|
1041
|
+
if (!reads.has(name)) continue;
|
|
1042
|
+
found.push(diagnosticAt(source, file, writeNode, {
|
|
1043
|
+
code: VOBS_C210,
|
|
1044
|
+
severity: "error",
|
|
1045
|
+
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`,
|
|
1046
|
+
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`
|
|
1047
|
+
}));
|
|
1048
|
+
}
|
|
1049
|
+
}, "inspectEffectBody");
|
|
1050
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1051
|
+
if (import_typescript.default.isCallExpression(node) && import_typescript.default.isIdentifier(node.expression) && (node.expression.text === "effect" || node.expression.text === "renderEffect")) {
|
|
1052
|
+
const callback = node.arguments[0];
|
|
1053
|
+
if (callback !== void 0 && (import_typescript.default.isArrowFunction(callback) || import_typescript.default.isFunctionExpression(callback))) {
|
|
1054
|
+
inspectEffectBody(callback.body);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1058
|
+
}, "visit");
|
|
1059
|
+
visit(source);
|
|
1060
|
+
return found;
|
|
1061
|
+
}
|
|
1062
|
+
__name(ruleEffectSelfSubscription, "ruleEffectSelfSubscription");
|
|
1063
|
+
function isKeyedListCall(node) {
|
|
1064
|
+
if (!import_typescript.default.isCallExpression(node)) return false;
|
|
1065
|
+
if (!import_typescript.default.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "map") return false;
|
|
1066
|
+
const callback = node.arguments[0];
|
|
1067
|
+
return callback !== void 0 && import_typescript.default.isFunctionLike(callback) && returnsJsx(callback);
|
|
1068
|
+
}
|
|
1069
|
+
__name(isKeyedListCall, "isKeyedListCall");
|
|
1070
|
+
function ruleListInBranch(source, file) {
|
|
1071
|
+
const found = [];
|
|
1072
|
+
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";
|
|
1073
|
+
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";
|
|
1074
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1075
|
+
if (import_typescript.default.isConditionalExpression(node)) {
|
|
1076
|
+
for (const branch of [node.whenTrue, node.whenFalse]) {
|
|
1077
|
+
if (isKeyedListCall(branch)) {
|
|
1078
|
+
found.push(diagnosticAt(source, file, branch, { code: VOBS_C232, severity: "warning", message, fix }));
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
} else if (import_typescript.default.isBinaryExpression(node) && node.operatorToken.kind === import_typescript.default.SyntaxKind.AmpersandAmpersandToken && isKeyedListCall(node.right)) {
|
|
1082
|
+
found.push(diagnosticAt(source, file, node.right, { code: VOBS_C232, severity: "warning", message, fix }));
|
|
1083
|
+
}
|
|
1084
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1085
|
+
}, "visit");
|
|
1086
|
+
visit(source);
|
|
1087
|
+
return found;
|
|
1088
|
+
}
|
|
1089
|
+
__name(ruleListInBranch, "ruleListInBranch");
|
|
1090
|
+
function containsSignalRead(node) {
|
|
1091
|
+
let seen = false;
|
|
1092
|
+
const visit = /* @__PURE__ */ __name((child) => {
|
|
1093
|
+
if (seen) return;
|
|
1094
|
+
if (import_typescript.default.isFunctionLike(child)) return;
|
|
1095
|
+
if (signalNameOf(child) !== void 0) {
|
|
1096
|
+
seen = true;
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
import_typescript.default.forEachChild(child, visit);
|
|
1100
|
+
}, "visit");
|
|
1101
|
+
visit(node);
|
|
1102
|
+
return seen;
|
|
1103
|
+
}
|
|
1104
|
+
__name(containsSignalRead, "containsSignalRead");
|
|
1105
|
+
function ruleSignalCapturedInBody(source, file) {
|
|
1106
|
+
const found = [];
|
|
1107
|
+
const inspectComponent = /* @__PURE__ */ __name((fn) => {
|
|
1108
|
+
const body = fn.body;
|
|
1109
|
+
if (body === void 0 || !import_typescript.default.isBlock(body) || !returnsJsx(fn)) return;
|
|
1110
|
+
const captured = [];
|
|
1111
|
+
for (const statement of body.statements) {
|
|
1112
|
+
if (!import_typescript.default.isVariableStatement(statement)) continue;
|
|
1113
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1114
|
+
if (!import_typescript.default.isIdentifier(declaration.name) || declaration.initializer === void 0) continue;
|
|
1115
|
+
if (containsSignalRead(declaration.initializer)) {
|
|
1116
|
+
captured.push({ name: declaration.name.text, node: declaration });
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
if (captured.length === 0) return;
|
|
1121
|
+
const usedInJsx = /* @__PURE__ */ new Set();
|
|
1122
|
+
const visit2 = /* @__PURE__ */ __name((node) => {
|
|
1123
|
+
if (import_typescript.default.isJsxExpression(node) && node.expression !== void 0) {
|
|
1124
|
+
const scan = /* @__PURE__ */ __name((child) => {
|
|
1125
|
+
if (import_typescript.default.isIdentifier(child)) usedInJsx.add(child.text);
|
|
1126
|
+
import_typescript.default.forEachChild(child, scan);
|
|
1127
|
+
}, "scan");
|
|
1128
|
+
scan(node.expression);
|
|
1129
|
+
}
|
|
1130
|
+
import_typescript.default.forEachChild(node, visit2);
|
|
1131
|
+
}, "visit");
|
|
1132
|
+
visit2(body);
|
|
1133
|
+
for (const item of captured) {
|
|
1134
|
+
if (!usedInJsx.has(item.name)) continue;
|
|
1135
|
+
found.push(diagnosticAt(source, file, item.node, {
|
|
1136
|
+
code: VOBS_C118,
|
|
1137
|
+
severity: "warning",
|
|
1138
|
+
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`,
|
|
1139
|
+
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`
|
|
1140
|
+
}));
|
|
1141
|
+
}
|
|
1142
|
+
}, "inspectComponent");
|
|
1143
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
1144
|
+
if (import_typescript.default.isFunctionDeclaration(node) || import_typescript.default.isFunctionExpression(node) || import_typescript.default.isArrowFunction(node)) {
|
|
1145
|
+
inspectComponent(node);
|
|
1146
|
+
}
|
|
1147
|
+
import_typescript.default.forEachChild(node, visit);
|
|
1148
|
+
}, "visit");
|
|
1149
|
+
visit(source);
|
|
1150
|
+
return found;
|
|
1151
|
+
}
|
|
1152
|
+
__name(ruleSignalCapturedInBody, "ruleSignalCapturedInBody");
|
|
1153
|
+
var IGNORE_NEXT_LINE = /vobs-check-ignore-next-line/u;
|
|
1154
|
+
function suppressedLines(text5) {
|
|
1155
|
+
const suppressed = /* @__PURE__ */ new Set();
|
|
1156
|
+
const lines = text5.split(/\r?\n/u);
|
|
1157
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1158
|
+
if (IGNORE_NEXT_LINE.test(lines[index])) suppressed.add(index + 2);
|
|
1159
|
+
}
|
|
1160
|
+
return suppressed;
|
|
1161
|
+
}
|
|
1162
|
+
__name(suppressedLines, "suppressedLines");
|
|
1163
|
+
function analyzeSource(text5, file) {
|
|
1164
|
+
const source = import_typescript.default.createSourceFile(file, text5, import_typescript.default.ScriptTarget.Latest, true, import_typescript.default.ScriptKind.TSX);
|
|
1165
|
+
const suppressed = suppressedLines(text5);
|
|
1166
|
+
return [
|
|
1167
|
+
...ruleEffectSelfSubscription(source, file),
|
|
1168
|
+
...ruleListInBranch(source, file),
|
|
1169
|
+
...ruleSignalCapturedInBody(source, file)
|
|
1170
|
+
].filter((item) => !suppressed.has(item.line)).sort((a, b) => a.line - b.line || a.column - b.column);
|
|
1171
|
+
}
|
|
1172
|
+
__name(analyzeSource, "analyzeSource");
|
|
1173
|
+
async function checkCommand(options = {}) {
|
|
1174
|
+
const root = import_node_path6.default.resolve(options.dir ?? process.cwd());
|
|
1175
|
+
let all;
|
|
1176
|
+
try {
|
|
1177
|
+
all = await collectSources(root);
|
|
1178
|
+
} catch (error2) {
|
|
1179
|
+
logger.error(error2 instanceof Error ? error2.message : String(error2));
|
|
1180
|
+
process.exitCode = 1;
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
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("/")));
|
|
1184
|
+
const skipped = all.length - files.length;
|
|
1185
|
+
const diagnostics = [];
|
|
1186
|
+
for (const absolute of files) {
|
|
1187
|
+
const text5 = await (0, import_promises2.readFile)(absolute, "utf8");
|
|
1188
|
+
const relative2 = import_node_path6.default.relative(root, absolute).split(import_node_path6.default.sep).join("/");
|
|
1189
|
+
diagnostics.push(...analyzeSource(text5, relative2));
|
|
1190
|
+
}
|
|
1191
|
+
const errors = diagnostics.filter((item) => item.severity === "error");
|
|
1192
|
+
const report = { root, files: files.length, skippedTests: skipped, diagnostics };
|
|
1193
|
+
if (options.write === true) {
|
|
1194
|
+
const target = import_node_path6.default.join(root, REPORT_PATH);
|
|
1195
|
+
await (0, import_promises2.mkdir)(import_node_path6.default.dirname(target), { recursive: true });
|
|
1196
|
+
await (0, import_promises2.writeFile)(target, `${JSON.stringify(report, null, 2)}
|
|
1197
|
+
`, "utf8");
|
|
1198
|
+
logger.info(`\u62A5\u544A\u5199\u5165 ${REPORT_PATH}\uFF08\u5F00\u53D1\u53F0\u9762\u677F\u8BFB\u5B83\u663E\u793A\u300C\u9879\u76EE\u300D\u9875\uFF09`);
|
|
1199
|
+
}
|
|
1200
|
+
if (options.json === true) {
|
|
1201
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1202
|
+
if (errors.length > 0) process.exitCode = 1;
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
if (diagnostics.length === 0) {
|
|
1206
|
+
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`);
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
console.log("");
|
|
1210
|
+
for (const item of diagnostics) {
|
|
1211
|
+
const mark = item.severity === "error" ? "\u2716" : "!";
|
|
1212
|
+
console.log(` ${mark} ${item.file}:${item.line}:${item.column} ${item.code}`);
|
|
1213
|
+
console.log(` ${item.message}`);
|
|
1214
|
+
if (item.snippet !== "") console.log(` ${item.snippet}`);
|
|
1215
|
+
console.log(` \u2192 ${item.fix}`);
|
|
1216
|
+
console.log("");
|
|
1217
|
+
}
|
|
1218
|
+
const warnings = diagnostics.length - errors.length;
|
|
1219
|
+
console.log(
|
|
1220
|
+
` ${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` : ""}
|
|
1221
|
+
`
|
|
1222
|
+
);
|
|
1223
|
+
if (errors.length > 0) process.exitCode = 1;
|
|
1224
|
+
}
|
|
1225
|
+
__name(checkCommand, "checkCommand");
|
|
1226
|
+
|
|
909
1227
|
// packages/cli/src/banner.ts
|
|
910
|
-
var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC}
|
|
1228
|
+
var BANNER_LINE1 = "\u{1D5E9}\u{1D5E2}\u{1D5D5}\u{1D5E6} \u{1D5D6}\u{1D5DF}\u{1D5DC}";
|
|
911
1229
|
var BANNER_TAGLINE = "Signals First \xB7 Zero Re-renders \xB7 Ultra Lightweight";
|
|
912
1230
|
var INDENT = " ";
|
|
913
1231
|
var DIM = "\x1B[2m";
|
|
@@ -923,12 +1241,12 @@ function showLogo() {
|
|
|
923
1241
|
}
|
|
924
1242
|
__name(showLogo, "showLogo");
|
|
925
1243
|
function showBanner() {
|
|
926
|
-
console.log(`${INDENT}${BANNER_LINE1}`);
|
|
1244
|
+
console.log(`${INDENT}${BANNER_LINE1} v${cliVersion()}`);
|
|
927
1245
|
}
|
|
928
1246
|
__name(showBanner, "showBanner");
|
|
929
1247
|
function showDevBanner() {
|
|
930
1248
|
console.log();
|
|
931
|
-
console.log(`${INDENT}${BANNER_LINE1}`);
|
|
1249
|
+
console.log(`${INDENT}${BANNER_LINE1} v${cliVersion()}`);
|
|
932
1250
|
console.log();
|
|
933
1251
|
}
|
|
934
1252
|
__name(showDevBanner, "showDevBanner");
|
|
@@ -982,7 +1300,15 @@ function createCLI() {
|
|
|
982
1300
|
dev: options.dev
|
|
983
1301
|
});
|
|
984
1302
|
});
|
|
985
|
-
cli.command("
|
|
1303
|
+
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) => {
|
|
1304
|
+
await checkCommand({
|
|
1305
|
+
dir,
|
|
1306
|
+
json: options.json === true,
|
|
1307
|
+
write: options.write === true,
|
|
1308
|
+
includeTests: options.includeTests === true
|
|
1309
|
+
});
|
|
1310
|
+
});
|
|
1311
|
+
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) => {
|
|
986
1312
|
await dshCommand(action, target, {
|
|
987
1313
|
dir: options.dir,
|
|
988
1314
|
pm: options.pm,
|
|
@@ -1003,18 +1329,30 @@ function createCLI() {
|
|
|
1003
1329
|
showBanner();
|
|
1004
1330
|
});
|
|
1005
1331
|
cli.help();
|
|
1006
|
-
cli.version(
|
|
1332
|
+
cli.version(cliVersion());
|
|
1007
1333
|
return cli;
|
|
1008
1334
|
}
|
|
1009
1335
|
__name(createCLI, "createCLI");
|
|
1336
|
+
var KNOWN_SUBCOMMANDS = [
|
|
1337
|
+
"init",
|
|
1338
|
+
"create",
|
|
1339
|
+
"dev",
|
|
1340
|
+
"build",
|
|
1341
|
+
"generate",
|
|
1342
|
+
"g",
|
|
1343
|
+
"add",
|
|
1344
|
+
"check",
|
|
1345
|
+
"dsh",
|
|
1346
|
+
"logo"
|
|
1347
|
+
];
|
|
1010
1348
|
|
|
1011
1349
|
// packages/cli/src/repl.ts
|
|
1012
|
-
var
|
|
1350
|
+
var import_promises3 = require("readline/promises");
|
|
1013
1351
|
var import_node_process = require("process");
|
|
1014
1352
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1015
1353
|
async function startRepl() {
|
|
1016
1354
|
showLogo();
|
|
1017
|
-
const rl = (0,
|
|
1355
|
+
const rl = (0, import_promises3.createInterface)({
|
|
1018
1356
|
input: import_node_process.stdin,
|
|
1019
1357
|
output: import_node_process.stdout,
|
|
1020
1358
|
prompt: ` ${import_picocolors2.default.magenta("\u276F")} `,
|
|
@@ -1125,16 +1463,52 @@ function splitArgs(line) {
|
|
|
1125
1463
|
__name(splitArgs, "splitArgs");
|
|
1126
1464
|
|
|
1127
1465
|
// packages/cli/src/start.ts
|
|
1466
|
+
var META_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
|
|
1467
|
+
function isFlag(token) {
|
|
1468
|
+
return token.startsWith("-") && token !== "-";
|
|
1469
|
+
}
|
|
1470
|
+
__name(isFlag, "isFlag");
|
|
1128
1471
|
async function start(args) {
|
|
1129
1472
|
if (args.length === 0 || args[0] === "cli") {
|
|
1130
1473
|
await startRepl();
|
|
1131
1474
|
return;
|
|
1132
1475
|
}
|
|
1133
|
-
|
|
1476
|
+
const first = args[0];
|
|
1477
|
+
const hasSubcommand = KNOWN_SUBCOMMANDS.includes(first);
|
|
1478
|
+
if (!hasSubcommand && (args.includes("--version") || args.includes("-V"))) {
|
|
1134
1479
|
showBanner();
|
|
1135
1480
|
return;
|
|
1136
1481
|
}
|
|
1137
|
-
|
|
1482
|
+
if (!hasSubcommand && !isFlag(first)) {
|
|
1483
|
+
process.stderr.write(`\u2716 \u672A\u77E5\u547D\u4EE4\uFF1A${first}
|
|
1484
|
+
|
|
1485
|
+
`);
|
|
1486
|
+
try {
|
|
1487
|
+
createCLI().parse(["node", "vobs", "--help"]);
|
|
1488
|
+
} catch {
|
|
1489
|
+
}
|
|
1490
|
+
process.exitCode = 1;
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
if (!hasSubcommand && isFlag(first) && !META_FLAGS.has(first)) {
|
|
1494
|
+
process.stderr.write(`\u2716 \u672A\u77E5\u9009\u9879\uFF1A${first}
|
|
1495
|
+
|
|
1496
|
+
`);
|
|
1497
|
+
try {
|
|
1498
|
+
createCLI().parse(["node", "vobs", "--help"]);
|
|
1499
|
+
} catch {
|
|
1500
|
+
}
|
|
1501
|
+
process.exitCode = 1;
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
try {
|
|
1505
|
+
createCLI().parse();
|
|
1506
|
+
} catch (error2) {
|
|
1507
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
1508
|
+
process.stderr.write(`\u2716 ${message}
|
|
1509
|
+
`);
|
|
1510
|
+
process.exitCode = 1;
|
|
1511
|
+
}
|
|
1138
1512
|
}
|
|
1139
1513
|
__name(start, "start");
|
|
1140
1514
|
// Annotate the CommonJS export names for ESM import in node:
|