contactsheet 0.1.0 → 0.1.2
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/README.md +8 -0
- package/dist/canvas/app.js +11 -2
- package/dist/canvas/app.js.map +2 -2
- package/dist/cli.js +69 -12
- package/dist/cli.js.map +2 -2
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -29,6 +29,7 @@ function loadConfig(cwd, flags) {
|
|
|
29
29
|
// 末尾斜杠去掉,后面一律靠 `${target}/xxx` 拼
|
|
30
30
|
target: String(pick("target") ?? DEFAULT_TARGET).replace(/\/+$/, ""),
|
|
31
31
|
port,
|
|
32
|
+
portExplicit: flags.port !== void 0,
|
|
32
33
|
appDir: pick("appDir") ?? detectAppDir(projectRoot),
|
|
33
34
|
designDir: pick("designDir") ?? DEFAULT_DESIGN_DIR
|
|
34
35
|
};
|
|
@@ -515,6 +516,10 @@ async function runInit(cwd, flags) {
|
|
|
515
516
|
console.log(" 1. \u7167\u5E38\u8D77\u4F60\u81EA\u5DF1\u7684 dev server(next dev),\u786E\u8BA4\u5B83\u5728 " + cfg.target);
|
|
516
517
|
console.log(" 2. \u53E6\u5F00\u4E00\u4E2A\u7EC8\u7AEF:npx contactsheet");
|
|
517
518
|
console.log(` 3. \u6253\u5F00 http://localhost:${cfg.port}/__cs`);
|
|
519
|
+
console.log("");
|
|
520
|
+
console.log("\u7AEF\u53E3\u90FD\u53EF\u4EE5\u6362:dev server \u4E0D\u5728 " + cfg.target + " \u5C31 --target <url>,");
|
|
521
|
+
console.log(` ${cfg.port} \u88AB\u5360\u5C31 --port <n>(\u6216\u6539 contactsheet.config.json \u540E\u91CD\u8DD1 init,MCP/hook \u4F1A\u8DDF\u7740\u6362)\u3002`);
|
|
522
|
+
console.log(` ${cfg.port} \u88AB\u522B\u7684\u8FDB\u7A0B\u5360\u7740\u65F6,contactsheet \u4F1A\u81EA\u52A8\u987A\u5EF6\u5230\u4E0B\u4E00\u4E2A\u7A7A\u95F2\u7AEF\u53E3\u5E76\u63D0\u793A\u3002`);
|
|
518
523
|
}
|
|
519
524
|
function assertNextProject(root) {
|
|
520
525
|
const pkgPath = join(root, "package.json");
|
|
@@ -543,11 +548,21 @@ function detectAppDir2(root) {
|
|
|
543
548
|
contactsheet v1 \u53EA\u652F\u6301 App Router(\u753B\u677F\u8DEF\u7531\u8981\u6CE8\u5165\u5230 app \u76EE\u5F55\u91CC)\u3002Pages Router \u9879\u76EE\u6682\u65F6\u7528\u4E0D\u4E86\u3002`
|
|
544
549
|
);
|
|
545
550
|
}
|
|
551
|
+
function detectDevTarget(root) {
|
|
552
|
+
try {
|
|
553
|
+
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
554
|
+
const dev = pkg.scripts?.["dev"] ?? "";
|
|
555
|
+
const m = dev.match(/(?:-p|--port)[ =](\d{2,5})/) ?? dev.match(/\bPORT=(\d{2,5})/);
|
|
556
|
+
if (m && m[1] !== "3000") return `http://localhost:${m[1]}`;
|
|
557
|
+
} catch {
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
546
561
|
function writeConfigFile(root, appDir, flags) {
|
|
547
562
|
const file = join(root, "contactsheet.config.json");
|
|
548
563
|
const existing = readJsonObject(file) ?? {};
|
|
549
564
|
const resolved = {
|
|
550
|
-
target: pickString(flags.target, existing["target"], DEFAULT_TARGET2),
|
|
565
|
+
target: pickString(flags.target, existing["target"], detectDevTarget(root) ?? DEFAULT_TARGET2),
|
|
551
566
|
port: pickNumber(flags.port, existing["port"], DEFAULT_PORT2),
|
|
552
567
|
appDir: pickString(flags.appDir, existing["appDir"], appDir),
|
|
553
568
|
designDir: pickString(flags.designDir, existing["designDir"], DEFAULT_DESIGN_DIR2)
|
|
@@ -1550,19 +1565,14 @@ async function startServer(cfg) {
|
|
|
1550
1565
|
s.on("close", () => sockets.delete(s));
|
|
1551
1566
|
});
|
|
1552
1567
|
const host = cfg.host ?? "127.0.0.1";
|
|
1553
|
-
await
|
|
1554
|
-
server.once("error", reject);
|
|
1555
|
-
server.listen(cfg.port, host, () => {
|
|
1556
|
-
server.off("error", reject);
|
|
1557
|
-
resolve2();
|
|
1558
|
-
});
|
|
1559
|
-
});
|
|
1568
|
+
const port = await listenWithFallback(server, cfg, host);
|
|
1560
1569
|
if (host !== "127.0.0.1" && host !== "localhost") {
|
|
1561
1570
|
console.warn(
|
|
1562
|
-
`[contactsheet] \u26A0\uFE0F \u76D1\u542C\u5728 ${host}:${
|
|
1571
|
+
`[contactsheet] \u26A0\uFE0F \u76D1\u542C\u5728 ${host}:${port} \u2014\u2014 \u753B\u5E03\u65E0\u9274\u6743,\u540C\u7F51\u7EDC\u7684\u4EFB\u4F55\u4EBA\u90FD\u80FD\u8BFB\u4F60\u7684\u6279\u6CE8\u3001\u5E76\u5411\u4F60\u7684 Claude Code \u4F1A\u8BDD\u63A8\u9001\u6D88\u606F\u3002\u53EA\u5728\u53EF\u4FE1\u7F51\u7EDC\u8FD9\u4E48\u505A\u3002`
|
|
1563
1572
|
);
|
|
1564
1573
|
}
|
|
1565
1574
|
return {
|
|
1575
|
+
port,
|
|
1566
1576
|
async close() {
|
|
1567
1577
|
closeAll();
|
|
1568
1578
|
proxyLog.close();
|
|
@@ -1637,6 +1647,53 @@ function downPage(target) {
|
|
|
1637
1647
|
function escapeHtml(s) {
|
|
1638
1648
|
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
1639
1649
|
}
|
|
1650
|
+
async function occupiedBySameProject(cfg, port) {
|
|
1651
|
+
try {
|
|
1652
|
+
const ctl = AbortSignal.timeout(800);
|
|
1653
|
+
const r = await fetch(`http://127.0.0.1:${port}/__cs/api/state`, { signal: ctl });
|
|
1654
|
+
if (!r.ok) return false;
|
|
1655
|
+
const data = await r.json();
|
|
1656
|
+
return data?.projectRoot === cfg.projectRoot;
|
|
1657
|
+
} catch {
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
async function listenWithFallback(server, cfg, host) {
|
|
1662
|
+
const tryListen = (port) => new Promise((resolve2, reject) => {
|
|
1663
|
+
const onErr = (err) => {
|
|
1664
|
+
if (err.code === "EADDRINUSE") resolve2(false);
|
|
1665
|
+
else reject(err);
|
|
1666
|
+
};
|
|
1667
|
+
server.once("error", onErr);
|
|
1668
|
+
server.listen(port, host, () => {
|
|
1669
|
+
server.off("error", onErr);
|
|
1670
|
+
resolve2(true);
|
|
1671
|
+
});
|
|
1672
|
+
});
|
|
1673
|
+
if (await tryListen(cfg.port)) return cfg.port;
|
|
1674
|
+
if (await occupiedBySameProject(cfg, cfg.port)) {
|
|
1675
|
+
console.log(
|
|
1676
|
+
`[contactsheet] \u672C\u9879\u76EE\u5DF2\u7ECF\u6709\u4E00\u4E2A contactsheet \u5728\u8DD1\u4E86,\u76F4\u63A5\u7528\u5B83:http://localhost:${cfg.port}/__cs`
|
|
1677
|
+
);
|
|
1678
|
+
process.exit(0);
|
|
1679
|
+
}
|
|
1680
|
+
if (cfg.portExplicit) {
|
|
1681
|
+
throw new Error(
|
|
1682
|
+
`\u7AEF\u53E3 ${cfg.port} \u88AB\u5176\u4ED6\u8FDB\u7A0B\u5360\u7528\u3002\u6362\u4E00\u4E2A --port,\u6216\u627E\u51FA\u5360\u7528\u8005:lsof -nP -iTCP:${cfg.port} -sTCP:LISTEN`
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
for (let p = cfg.port + 1; p <= cfg.port + 20; p++) {
|
|
1686
|
+
if (await tryListen(p)) {
|
|
1687
|
+
console.warn(
|
|
1688
|
+
`[contactsheet] \u26A0\uFE0F \u7AEF\u53E3 ${cfg.port} \u88AB\u5360,\u5DF2\u987A\u5EF6\u5230 ${p} \u2192 http://localhost:${p}/__cs
|
|
1689
|
+
\u6CE8\u610F:\u6362\u7AEF\u53E3 = \u6362\u6D4F\u89C8\u5668\u6E90\u3002\u753B\u677F\u4F4D\u7F6E/\u6298\u53E0/\u5E95\u8272\u8FD9\u4E9B\u672C\u673A\u8BB0\u5FC6\u6309\u6E90\u9694\u79BB,\u8FD9\u4E2A\u7AEF\u53E3\u4E0B\u662F\u5168\u65B0\u7684;
|
|
1690
|
+
.mcp.json \u4E0E hook \u4ECD\u6307\u5411 ${cfg.port}\u3002\u60F3\u8981\u7A33\u5B9A,\u8BF7\u91CA\u653E ${cfg.port},\u6216\u6539 config \u7684 port \u540E\u91CD\u8DD1 npx contactsheet init\u3002`
|
|
1691
|
+
);
|
|
1692
|
+
return p;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
throw new Error(`\u4ECE ${cfg.port} \u5F80\u4E0A\u8FDE\u8BD5 20 \u4E2A\u7AEF\u53E3\u90FD\u88AB\u5360,\u7528 --port \u6307\u5B9A\u4E00\u4E2A\u7A7A\u95F2\u7AEF\u53E3`);
|
|
1696
|
+
}
|
|
1640
1697
|
|
|
1641
1698
|
// src/watch/index.ts
|
|
1642
1699
|
import path7 from "node:path";
|
|
@@ -1743,7 +1800,7 @@ async function up(flags) {
|
|
|
1743
1800
|
() => startWatcher(cfg, (entries) => broadcast({ type: "registry", entries }))
|
|
1744
1801
|
);
|
|
1745
1802
|
const server = await startServer(cfg);
|
|
1746
|
-
banner(cfg);
|
|
1803
|
+
banner(cfg, server.port);
|
|
1747
1804
|
let closing = false;
|
|
1748
1805
|
const shutdown = async (sig) => {
|
|
1749
1806
|
if (closing) return;
|
|
@@ -1772,9 +1829,9 @@ async function quiet(fn) {
|
|
|
1772
1829
|
} catch {
|
|
1773
1830
|
}
|
|
1774
1831
|
}
|
|
1775
|
-
function banner(cfg) {
|
|
1832
|
+
function banner(cfg, port) {
|
|
1776
1833
|
console.log(`
|
|
1777
|
-
contactsheet http://localhost:${
|
|
1834
|
+
contactsheet http://localhost:${port}/__cs
|
|
1778
1835
|
\u4EE3\u7406\u76EE\u6807 ${cfg.target}
|
|
1779
1836
|
\u753B\u677F\u76EE\u5F55 ${cfg.designDir}/ \xB7 app \u76EE\u5F55 ${cfg.appDir}/
|
|
1780
1837
|
Ctrl-C \u9000\u51FA
|