contactsheet 0.1.2 → 0.1.4
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 +39 -4
- package/dist/canvas/app.js +437 -381
- package/dist/canvas/app.js.map +4 -4
- package/dist/cli.js +84 -40
- package/dist/cli.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -496,6 +496,22 @@ async function regenerateRegistry(cfg) {
|
|
|
496
496
|
// src/init/index.ts
|
|
497
497
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
498
498
|
import { dirname, join, relative, resolve } from "node:path";
|
|
499
|
+
|
|
500
|
+
// src/term.ts
|
|
501
|
+
var on = process.stdout.isTTY === true && !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
502
|
+
var wrap = (open, close) => (s) => on ? `\x1B[${open}m${s}\x1B[${close}m` : s;
|
|
503
|
+
var bold = wrap(1, 22);
|
|
504
|
+
var dim = wrap(2, 22);
|
|
505
|
+
var red = wrap(31, 39);
|
|
506
|
+
var green = wrap(32, 39);
|
|
507
|
+
var yellow = wrap(33, 39);
|
|
508
|
+
var cyan = wrap(36, 39);
|
|
509
|
+
var magenta = wrap(35, 39);
|
|
510
|
+
var link = (s) => on ? `\x1B[36;4m${s}\x1B[39;24m` : s;
|
|
511
|
+
var ok = (s) => `${green("\u2713")} ${s}`;
|
|
512
|
+
var warn = (s) => `${yellow("\u26A0")} ${yellow(s)}`;
|
|
513
|
+
|
|
514
|
+
// src/init/index.ts
|
|
499
515
|
var DEFAULT_TARGET2 = "http://localhost:3000";
|
|
500
516
|
var DEFAULT_PORT2 = 5199;
|
|
501
517
|
var DEFAULT_DESIGN_DIR2 = "design";
|
|
@@ -505,21 +521,21 @@ async function runInit(cwd, flags) {
|
|
|
505
521
|
assertNextProject(root);
|
|
506
522
|
const appDir = detectAppDir2(root);
|
|
507
523
|
const cfg = writeConfigFile(root, appDir, flags);
|
|
508
|
-
console.log(
|
|
509
|
-
console.log(`
|
|
510
|
-
console.log(
|
|
524
|
+
console.log(`${bold(cyan("\u25C6"))} ${bold("contactsheet init")} ${dim("\u2014\u2014")} ${root}`);
|
|
525
|
+
console.log(ok(`app \u76EE\u5F55:${cfg.appDir}`));
|
|
526
|
+
console.log(ok(`\u914D\u7F6E:contactsheet.config.json(target ${cfg.target},port ${cfg.port},\u753B\u677F\u76EE\u5F55 ${cfg.designDir})`));
|
|
511
527
|
seedArtboards(root, cfg.designDir);
|
|
512
528
|
writeMcpJson(root, cfg.port);
|
|
513
529
|
writeClaudeHook(root, cfg.port);
|
|
514
530
|
console.log("");
|
|
515
|
-
console.log("\u4E0B\u4E00\u6B65:");
|
|
516
|
-
console.log(
|
|
517
|
-
console.log(
|
|
518
|
-
console.log(` 3. \u6253\u5F00 http://localhost:${cfg.port}/__cs`);
|
|
531
|
+
console.log(bold("\u4E0B\u4E00\u6B65:"));
|
|
532
|
+
console.log(` 1. \u7167\u5E38\u8D77\u4F60\u81EA\u5DF1\u7684 dev server(next dev),\u786E\u8BA4\u5B83\u5728 ${cyan(cfg.target)}`);
|
|
533
|
+
console.log(` 2. \u53E6\u5F00\u4E00\u4E2A\u7EC8\u7AEF:${cyan("npx contactsheet")}`);
|
|
534
|
+
console.log(` 3. \u6253\u5F00 ${link(`http://localhost:${cfg.port}/__cs`)}`);
|
|
519
535
|
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`);
|
|
536
|
+
console.log(dim("\u7AEF\u53E3\u90FD\u53EF\u4EE5\u6362:dev server \u4E0D\u5728 ") + cfg.target + dim(" \u5C31 --target <url>,"));
|
|
537
|
+
console.log(dim(` ${cfg.port} \u88AB\u5360\u5C31 --port <n>(\u6216\u6539 contactsheet.config.json \u540E\u91CD\u8DD1 init,MCP/hook \u4F1A\u8DDF\u7740\u6362)\u3002`));
|
|
538
|
+
console.log(dim(` ${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`));
|
|
523
539
|
}
|
|
524
540
|
function assertNextProject(root) {
|
|
525
541
|
const pkgPath = join(root, "package.json");
|
|
@@ -597,7 +613,7 @@ function seedArtboards(root, designDir) {
|
|
|
597
613
|
writeFileSync(artboard, artboardTemplate(name, importPathFor(root, designDir, componentFile)), "utf8");
|
|
598
614
|
created++;
|
|
599
615
|
}
|
|
600
|
-
console.log(
|
|
616
|
+
console.log(ok(`\u753B\u677F:\u94FA\u4E86 ${green(String(created))} \u5757,\u8DF3\u8FC7 ${skipped} \u4E2A\u5DF2\u5B58\u5728`) + (unreadable ? `,${unreadable} \u4E2A\u6587\u4EF6\u6CA1\u8BA4\u51FA\u7EC4\u4EF6\u5BFC\u51FA` : ""));
|
|
601
617
|
}
|
|
602
618
|
function firstComponentExport(source) {
|
|
603
619
|
const hits = [];
|
|
@@ -1044,9 +1060,9 @@ import path5 from "node:path";
|
|
|
1044
1060
|
function isLive(sock) {
|
|
1045
1061
|
return new Promise((resolve2) => {
|
|
1046
1062
|
const s = new net.Socket();
|
|
1047
|
-
const done = (
|
|
1063
|
+
const done = (ok2) => {
|
|
1048
1064
|
s.destroy();
|
|
1049
|
-
resolve2(
|
|
1065
|
+
resolve2(ok2);
|
|
1050
1066
|
};
|
|
1051
1067
|
s.on("connect", () => done(true));
|
|
1052
1068
|
s.on("error", () => done(false));
|
|
@@ -1317,12 +1333,12 @@ function pushToken() {
|
|
|
1317
1333
|
function originAllowed(cfg, req) {
|
|
1318
1334
|
const origin = req.headers.origin;
|
|
1319
1335
|
if (!origin) return true;
|
|
1320
|
-
const
|
|
1336
|
+
const ok2 = /* @__PURE__ */ new Set([
|
|
1321
1337
|
`http://localhost:${cfg.port}`,
|
|
1322
1338
|
`http://127.0.0.1:${cfg.port}`,
|
|
1323
1339
|
`http://[::1]:${cfg.port}`
|
|
1324
1340
|
]);
|
|
1325
|
-
return
|
|
1341
|
+
return ok2.has(origin);
|
|
1326
1342
|
}
|
|
1327
1343
|
async function handleApi(cfg, req, res, pathname) {
|
|
1328
1344
|
const method = req.method ?? "GET";
|
|
@@ -1489,7 +1505,7 @@ function createProxyLog(target) {
|
|
|
1489
1505
|
}
|
|
1490
1506
|
down = true;
|
|
1491
1507
|
console.error(
|
|
1492
|
-
|
|
1508
|
+
`${yellow("\u26A0")} ${yellow(`\u76EE\u6807 ${target} \u8FDE\u4E0D\u4E0A\u4E86`)} \u2014\u2014 \u8D77 next dev \u540E\u4F1A\u81EA\u52A8\u6062\u590D(\u753B\u5E03\u4F1A\u81EA\u5DF1\u91CD\u8BD5)\u3002` + dim("\u671F\u95F4\u7684\u4EE3\u7406\u5931\u8D25\u4E0D\u518D\u9010\u6761\u6253\u5370\u3002")
|
|
1493
1509
|
);
|
|
1494
1510
|
return;
|
|
1495
1511
|
}
|
|
@@ -1499,12 +1515,12 @@ function createProxyLog(target) {
|
|
|
1499
1515
|
win.extra++;
|
|
1500
1516
|
return;
|
|
1501
1517
|
}
|
|
1502
|
-
console.error(
|
|
1518
|
+
console.error(`${red("\u2716")} \u4EE3\u7406\u5931\u8D25 ${pathOf(url)} ${red(String(code))}`);
|
|
1503
1519
|
const timer = setTimeout(() => {
|
|
1504
1520
|
const extra = windows.get(key)?.extra ?? 0;
|
|
1505
1521
|
windows.delete(key);
|
|
1506
1522
|
if (extra > 0) {
|
|
1507
|
-
console.error(`
|
|
1523
|
+
console.error(dim(` (\u8FC7\u53BB ${WINDOW_MS / 1e3} \u79D2\u8FD8\u6709 ${extra} \u6B21\u540C\u7C7B\u5931\u8D25:${key})`));
|
|
1508
1524
|
}
|
|
1509
1525
|
}, WINDOW_MS);
|
|
1510
1526
|
timer.unref();
|
|
@@ -1515,7 +1531,7 @@ function createProxyLog(target) {
|
|
|
1515
1531
|
down = false;
|
|
1516
1532
|
const n = silenced;
|
|
1517
1533
|
silenced = 0;
|
|
1518
|
-
console.log(
|
|
1534
|
+
console.log(`${green("\u2713")} ${green(`\u76EE\u6807 ${target} \u5DF2\u6062\u590D`)}${n > 0 ? dim(`(\u4E0D\u53EF\u8FBE\u671F\u95F4\u538B\u6389 ${n} \u6761\u4EE3\u7406\u5931\u8D25)`) : ""}`);
|
|
1519
1535
|
},
|
|
1520
1536
|
close() {
|
|
1521
1537
|
for (const win of windows.values()) clearTimeout(win.timer);
|
|
@@ -1565,10 +1581,17 @@ async function startServer(cfg) {
|
|
|
1565
1581
|
s.on("close", () => sockets.delete(s));
|
|
1566
1582
|
});
|
|
1567
1583
|
const host = cfg.host ?? "127.0.0.1";
|
|
1568
|
-
|
|
1584
|
+
let twin = null;
|
|
1585
|
+
const port = await listenWithFallback(server, cfg, host, (t) => {
|
|
1586
|
+
twin = t;
|
|
1587
|
+
t.on("connection", (sock) => {
|
|
1588
|
+
sockets.add(sock);
|
|
1589
|
+
sock.on("close", () => sockets.delete(sock));
|
|
1590
|
+
});
|
|
1591
|
+
});
|
|
1569
1592
|
if (host !== "127.0.0.1" && host !== "localhost") {
|
|
1570
1593
|
console.warn(
|
|
1571
|
-
|
|
1594
|
+
warn(`\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`)
|
|
1572
1595
|
);
|
|
1573
1596
|
}
|
|
1574
1597
|
return {
|
|
@@ -1577,6 +1600,9 @@ async function startServer(cfg) {
|
|
|
1577
1600
|
closeAll();
|
|
1578
1601
|
proxyLog.close();
|
|
1579
1602
|
proxy.close();
|
|
1603
|
+
if (twin) {
|
|
1604
|
+
await new Promise((r) => twin.close(() => r()));
|
|
1605
|
+
}
|
|
1580
1606
|
await new Promise((resolve2) => {
|
|
1581
1607
|
const fallback = setTimeout(resolve2, 2e3);
|
|
1582
1608
|
for (const s of sockets) s.destroy();
|
|
@@ -1658,22 +1684,38 @@ async function occupiedBySameProject(cfg, port) {
|
|
|
1658
1684
|
return false;
|
|
1659
1685
|
}
|
|
1660
1686
|
}
|
|
1661
|
-
async function listenWithFallback(server, cfg, host) {
|
|
1662
|
-
const
|
|
1687
|
+
async function listenWithFallback(server, cfg, host, onTwin) {
|
|
1688
|
+
const listenOnce = (srv, port, h) => new Promise((resolve2, reject) => {
|
|
1663
1689
|
const onErr = (err) => {
|
|
1664
|
-
if (err.code === "EADDRINUSE") resolve2(
|
|
1690
|
+
if (err.code === "EADDRINUSE") resolve2("busy");
|
|
1691
|
+
else if (err.code === "EADDRNOTAVAIL" || err.code === "EAFNOSUPPORT") resolve2("nofam");
|
|
1665
1692
|
else reject(err);
|
|
1666
1693
|
};
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
resolve2(
|
|
1694
|
+
srv.once("error", onErr);
|
|
1695
|
+
srv.listen(port, h, () => {
|
|
1696
|
+
srv.off("error", onErr);
|
|
1697
|
+
resolve2("ok");
|
|
1671
1698
|
});
|
|
1672
1699
|
});
|
|
1700
|
+
const tryListen = async (port) => {
|
|
1701
|
+
const main2 = await listenOnce(server, port, host);
|
|
1702
|
+
if (main2 !== "ok") return false;
|
|
1703
|
+
if (host !== "127.0.0.1") return true;
|
|
1704
|
+
const t = http.createServer(server.listeners("request")[0]);
|
|
1705
|
+
for (const l of server.listeners("upgrade")) t.on("upgrade", l);
|
|
1706
|
+
const r = await listenOnce(t, port, "::1");
|
|
1707
|
+
if (r === "ok") {
|
|
1708
|
+
onTwin(t);
|
|
1709
|
+
return true;
|
|
1710
|
+
}
|
|
1711
|
+
if (r === "nofam") return true;
|
|
1712
|
+
await new Promise((res) => server.close(() => res()));
|
|
1713
|
+
return false;
|
|
1714
|
+
};
|
|
1673
1715
|
if (await tryListen(cfg.port)) return cfg.port;
|
|
1674
1716
|
if (await occupiedBySameProject(cfg, cfg.port)) {
|
|
1675
1717
|
console.log(
|
|
1676
|
-
|
|
1718
|
+
`${cyan("\u25CF")} \u672C\u9879\u76EE\u5DF2\u7ECF\u6709\u4E00\u4E2A contactsheet \u5728\u8DD1\u4E86,\u76F4\u63A5\u7528\u5B83:${link(`http://localhost:${cfg.port}/__cs`)}`
|
|
1677
1719
|
);
|
|
1678
1720
|
process.exit(0);
|
|
1679
1721
|
}
|
|
@@ -1685,9 +1727,8 @@ async function listenWithFallback(server, cfg, host) {
|
|
|
1685
1727
|
for (let p = cfg.port + 1; p <= cfg.port + 20; p++) {
|
|
1686
1728
|
if (await tryListen(p)) {
|
|
1687
1729
|
console.warn(
|
|
1688
|
-
|
|
1689
|
-
\
|
|
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`
|
|
1730
|
+
warn(`\u7AEF\u53E3 ${cfg.port} \u88AB\u5360,\u5DF2\u987A\u5EF6\u5230 ${p} \u2192 `) + link(`http://localhost:${p}/__cs`) + "\n" + dim(` \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;
|
|
1731
|
+
`) + dim(` .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
1732
|
);
|
|
1692
1733
|
return p;
|
|
1693
1734
|
}
|
|
@@ -1746,6 +1787,7 @@ async function startWatcher(cfg, onChange) {
|
|
|
1746
1787
|
}
|
|
1747
1788
|
|
|
1748
1789
|
// src/cli.ts
|
|
1790
|
+
process.noDeprecation = true;
|
|
1749
1791
|
var HELP = `contactsheet \u2014\u2014 \u628A UI \u7684\u5404\u79CD\u72B6\u6001\u644A\u5728\u4E00\u9762\u53EF\u7F29\u653E\u7684\u5899\u4E0A
|
|
1750
1792
|
|
|
1751
1793
|
contactsheet [up] \u9644\u7740\u5230\u5F53\u524D Next.js repo:\u6CE8\u5165\u753B\u677F\u8DEF\u7531 + \u8D77\u5916\u58F3(\u9ED8\u8BA4\u547D\u4EE4)
|
|
@@ -1794,19 +1836,21 @@ ${HELP}`);
|
|
|
1794
1836
|
}
|
|
1795
1837
|
async function up(flags) {
|
|
1796
1838
|
const cfg = loadConfig(process.cwd(), flags);
|
|
1797
|
-
await tryStep("\u6CE8\u5165\u753B\u677F\u8DEF\u7531", () => ensureInjected(cfg));
|
|
1839
|
+
const injected = await tryStep("\u6CE8\u5165\u753B\u677F\u8DEF\u7531", () => ensureInjected(cfg));
|
|
1840
|
+
if (injected !== null) console.log(ok(dim("\u753B\u677F\u8DEF\u7531\u5DF2\u6CE8\u5165")));
|
|
1798
1841
|
const watcher = await tryStep(
|
|
1799
1842
|
"\u542F\u52A8\u6587\u4EF6\u76D1\u542C",
|
|
1800
1843
|
() => startWatcher(cfg, (entries) => broadcast({ type: "registry", entries }))
|
|
1801
1844
|
);
|
|
1845
|
+
if (watcher) console.log(ok(dim(`\u76D1\u542C ${cfg.designDir}/**/*.artboard.{tsx,ts}`)));
|
|
1802
1846
|
const server = await startServer(cfg);
|
|
1803
1847
|
banner(cfg, server.port);
|
|
1804
1848
|
let closing = false;
|
|
1805
1849
|
const shutdown = async (sig) => {
|
|
1806
1850
|
if (closing) return;
|
|
1807
1851
|
closing = true;
|
|
1808
|
-
console.log(`
|
|
1809
|
-
[contactsheet] \u6536\u5230 ${sig},\u6B63\u5728\u9000\u51FA\u2026`);
|
|
1852
|
+
console.log(dim(`
|
|
1853
|
+
[contactsheet] \u6536\u5230 ${sig},\u6B63\u5728\u9000\u51FA\u2026`));
|
|
1810
1854
|
if (watcher) await quiet(() => watcher.close());
|
|
1811
1855
|
await quiet(() => server.close());
|
|
1812
1856
|
await quiet(() => closeBrowser());
|
|
@@ -1819,7 +1863,7 @@ async function tryStep(label, fn) {
|
|
|
1819
1863
|
try {
|
|
1820
1864
|
return await fn();
|
|
1821
1865
|
} catch (err) {
|
|
1822
|
-
console.warn(
|
|
1866
|
+
console.warn(warn(`${label}\u5931\u8D25,\u5DF2\u8DF3\u8FC7:${err instanceof Error ? err.message : String(err)}`));
|
|
1823
1867
|
return null;
|
|
1824
1868
|
}
|
|
1825
1869
|
}
|
|
@@ -1831,10 +1875,10 @@ async function quiet(fn) {
|
|
|
1831
1875
|
}
|
|
1832
1876
|
function banner(cfg, port) {
|
|
1833
1877
|
console.log(`
|
|
1834
|
-
contactsheet http://localhost:${port}/__cs
|
|
1835
|
-
\u4EE3\u7406\u76EE\u6807 ${cfg.target}
|
|
1836
|
-
\u753B\u677F\u76EE\u5F55 ${cfg.designDir}/
|
|
1837
|
-
Ctrl-C \u9000\u51FA
|
|
1878
|
+
${bold(cyan("\u25C6"))} ${bold("contactsheet")} ${link(`http://localhost:${port}/__cs`)}
|
|
1879
|
+
${dim("\u4EE3\u7406\u76EE\u6807")} ${cfg.target}
|
|
1880
|
+
${dim("\u753B\u677F\u76EE\u5F55")} ${cfg.designDir}/ ${dim("\xB7")} app \u76EE\u5F55 ${cfg.appDir}/
|
|
1881
|
+
${dim("Ctrl-C \u9000\u51FA")}
|
|
1838
1882
|
`);
|
|
1839
1883
|
}
|
|
1840
1884
|
//# sourceMappingURL=cli.js.map
|