zdashboard 2.5.1 → 2.6.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/dist/cli.js +160 -23
- package/dist/cli.js.map +1 -1
- package/dist/web/assets/FileIcon-Bc03q6Gz.js +279 -0
- package/dist/web/assets/FilterPills-CSZQenbh.js +1 -0
- package/dist/web/assets/ProgressBar-ycyJBwG-.js +1 -0
- package/dist/web/assets/Workspace-jCfxaTOM.js +1 -0
- package/dist/web/assets/badge-DUO7nDks.js +1 -0
- package/dist/web/assets/index-4aiRmNbP.css +1 -0
- package/dist/web/assets/{index-DKB8z9I8.js → index-BrvOKJRF.js} +1 -1
- package/dist/web/assets/index-Co_rMXPa.js +7816 -0
- package/dist/web/assets/web-BKh2HY35.js +2 -0
- package/dist/web/assets/web-BNjs9lCy.js +139 -0
- package/dist/web/assets/web-BrsVNrGk.js +1 -0
- package/dist/web/assets/web-Bt0s1qFE.js +5 -0
- package/dist/web/assets/web-CCoznDNk.js +2 -0
- package/dist/web/assets/web-DxK2pSVl.js +1 -0
- package/dist/web/assets/web-ShIDOvFD.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +2 -1
- package/dist/web/assets/FileIcon-CWL_Aew0.js +0 -110
- package/dist/web/assets/FilterPills-DfrtQ2BX.js +0 -1
- package/dist/web/assets/MdViewer-DoCxNu7A.js +0 -270
- package/dist/web/assets/ProgressBar-CIDdp-03.js +0 -1
- package/dist/web/assets/Workspace-CsW6-X9a.js +0 -16
- package/dist/web/assets/badge-izTmQYbF.js +0 -1
- package/dist/web/assets/book-open-CCPWUzhH.js +0 -6
- package/dist/web/assets/file-text-DHJKu2eF.js +0 -6
- package/dist/web/assets/index-C39_SyD0.css +0 -1
- package/dist/web/assets/index-Cu37wtgU.js +0 -161
- package/dist/web/assets/vt323-latin-400-normal-Dqn9ZSPj.woff +0 -0
- package/dist/web/assets/web-9Iy8fpbv.js +0 -7
- package/dist/web/assets/web-C4KehBpT.js +0 -26
- package/dist/web/assets/web-CSsoKnCH.js +0 -2
- package/dist/web/assets/web-CnZCJ59N.js +0 -25
- package/dist/web/assets/web-DjRxK_Na.js +0 -16
- package/dist/web/assets/web-DuuJgOy2.js +0 -21
- package/dist/web/assets/web-DxAXHOpi.js +0 -16
- /package/dist/web/assets/{MdViewer-BTcE7LSd.css → FileIcon-BTcE7LSd.css} +0 -0
package/dist/cli.js
CHANGED
|
@@ -167,7 +167,7 @@ import { fileURLToPath } from "url";
|
|
|
167
167
|
// package.json
|
|
168
168
|
var package_default = {
|
|
169
169
|
name: "zdashboard",
|
|
170
|
-
version: "2.
|
|
170
|
+
version: "2.6.2",
|
|
171
171
|
description: "ZCode skill dashboard platform \u2014 pluggable viewers for zdesign/zview/zreview/zgoal",
|
|
172
172
|
type: "module",
|
|
173
173
|
bin: {
|
|
@@ -189,6 +189,7 @@ var package_default = {
|
|
|
189
189
|
},
|
|
190
190
|
dependencies: {
|
|
191
191
|
"@fontsource/vt323": "^5.3.0",
|
|
192
|
+
"@phosphor-icons/react": "^2.1.10",
|
|
192
193
|
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
|
193
194
|
"@radix-ui/react-scroll-area": "^1.2.0",
|
|
194
195
|
"@radix-ui/react-separator": "^1.1.0",
|
|
@@ -686,7 +687,8 @@ var ReloadService = class extends Service2 {
|
|
|
686
687
|
return () => this.clients.delete(res);
|
|
687
688
|
});
|
|
688
689
|
try {
|
|
689
|
-
this.watcher = fs5.watch(config.root, { recursive: true }, () => {
|
|
690
|
+
this.watcher = fs5.watch(config.root, { recursive: true }, (eventType, filename) => {
|
|
691
|
+
if (filename && /^(?:\.git|node_modules|dist|\.pnpm)(?:[/\\]|$)/.test(filename)) return;
|
|
690
692
|
if (this.timer) clearTimeout(this.timer);
|
|
691
693
|
this.timer = setTimeout(() => {
|
|
692
694
|
this.ctx.server.refreshGitInfo();
|
|
@@ -839,7 +841,7 @@ function scanTree(root, hasOpenspec, hasDocs) {
|
|
|
839
841
|
const docs = buildTree(paths).map((n) => ({ ...n, path: n.path ? `docs/${n.path}` : void 0 }));
|
|
840
842
|
if (docs.length) tree.push({ name: "docs", kind: "dir", children: docs });
|
|
841
843
|
}
|
|
842
|
-
const skip = /* @__PURE__ */ new Set(["openspec", "docs", "node_modules", ".git", "dist", "
|
|
844
|
+
const skip = /* @__PURE__ */ new Set(["openspec", "docs", "node_modules", ".git", "dist", "playground", ".zreview"]);
|
|
843
845
|
const etc = [];
|
|
844
846
|
try {
|
|
845
847
|
for (const ent of fs7.readdirSync(root, { withFileTypes: true })) {
|
|
@@ -1245,62 +1247,148 @@ var apply4 = {
|
|
|
1245
1247
|
import fs8 from "fs";
|
|
1246
1248
|
import path7 from "path";
|
|
1247
1249
|
import YAML2 from "yaml";
|
|
1248
|
-
var
|
|
1250
|
+
var REVIEW_DIR = ".zreview";
|
|
1251
|
+
var REVIEW_FILE = path7.join(REVIEW_DIR, "review.yaml");
|
|
1252
|
+
var DOCS_DIR = path7.join(REVIEW_DIR, "docs");
|
|
1253
|
+
var DIAGRAMS_DIR = path7.join(REVIEW_DIR, "diagrams");
|
|
1249
1254
|
var ReviewStore = class {
|
|
1250
1255
|
root;
|
|
1251
|
-
file;
|
|
1252
1256
|
onChange;
|
|
1253
1257
|
constructor(root, onChange) {
|
|
1254
1258
|
this.root = root;
|
|
1255
1259
|
this.onChange = onChange;
|
|
1256
|
-
const existing = REVIEW_CANDIDATES.find((rel) => fs8.existsSync(path7.join(root, rel)));
|
|
1257
|
-
this.file = path7.join(root, existing ?? REVIEW_CANDIDATES[0]);
|
|
1258
1260
|
}
|
|
1259
1261
|
exists() {
|
|
1260
|
-
return fs8.existsSync(this.
|
|
1262
|
+
return fs8.existsSync(path7.join(this.root, REVIEW_FILE));
|
|
1261
1263
|
}
|
|
1262
1264
|
read() {
|
|
1265
|
+
const fullPath = path7.join(this.root, REVIEW_FILE);
|
|
1266
|
+
if (!fs8.existsSync(fullPath)) {
|
|
1267
|
+
return { status: "draft", summary: "", documents: [], codebases: [], diagrams: [], items: [] };
|
|
1268
|
+
}
|
|
1263
1269
|
try {
|
|
1264
|
-
const parsed = YAML2.parse(fs8.readFileSync(
|
|
1265
|
-
if (!parsed || !Array.isArray(parsed.items))
|
|
1266
|
-
|
|
1270
|
+
const parsed = YAML2.parse(fs8.readFileSync(fullPath, "utf8"));
|
|
1271
|
+
if (!parsed || !Array.isArray(parsed.items)) {
|
|
1272
|
+
return { status: "draft", summary: parsed?.summary ?? "", documents: parsed?.documents ?? [], codebases: parsed?.codebases ?? [], diagrams: parsed?.diagrams ?? [], items: [] };
|
|
1273
|
+
}
|
|
1274
|
+
return {
|
|
1275
|
+
status: parsed.status ?? "draft",
|
|
1276
|
+
summary: parsed.summary ?? "",
|
|
1277
|
+
documents: parsed.documents ?? [],
|
|
1278
|
+
codebases: parsed.codebases ?? [],
|
|
1279
|
+
diagrams: parsed.diagrams ?? [],
|
|
1280
|
+
items: parsed.items
|
|
1281
|
+
};
|
|
1267
1282
|
} catch {
|
|
1268
|
-
return { status: "draft", items: [] };
|
|
1283
|
+
return { status: "draft", summary: "", documents: [], codebases: [], diagrams: [], items: [] };
|
|
1269
1284
|
}
|
|
1270
1285
|
}
|
|
1271
1286
|
write(data) {
|
|
1272
|
-
fs8.mkdirSync(path7.
|
|
1273
|
-
fs8.writeFileSync(this.
|
|
1287
|
+
fs8.mkdirSync(path7.join(this.root, REVIEW_DIR), { recursive: true });
|
|
1288
|
+
fs8.writeFileSync(path7.join(this.root, REVIEW_FILE), YAML2.stringify(data), "utf8");
|
|
1274
1289
|
this.onChange?.();
|
|
1275
1290
|
}
|
|
1276
1291
|
updateItem(id, patch) {
|
|
1277
1292
|
const data = this.read();
|
|
1278
|
-
const item = data.items
|
|
1293
|
+
const item = this.findItem(data.items, id);
|
|
1279
1294
|
if (!item) throw new Error(`item ${id} not found`);
|
|
1280
1295
|
if (patch.answer !== void 0) item.answer = patch.answer;
|
|
1281
1296
|
if (patch.state !== void 0) item.state = patch.state;
|
|
1297
|
+
if (patch.priority !== void 0) item.priority = patch.priority;
|
|
1298
|
+
if (patch.title !== void 0) item.title = patch.title;
|
|
1282
1299
|
if (patch.state === "answered" && !patch.answer && !item.answer) item.answer = "";
|
|
1283
1300
|
this.write(data);
|
|
1284
1301
|
return data;
|
|
1285
1302
|
}
|
|
1303
|
+
addChild(parentId, title, priority = "medium") {
|
|
1304
|
+
const data = this.read();
|
|
1305
|
+
const parent = this.findItem(data.items, parentId);
|
|
1306
|
+
if (!parent) throw new Error(`parent ${parentId} not found`);
|
|
1307
|
+
if (!parent.children) parent.children = [];
|
|
1308
|
+
const newId = `${parentId}-${parent.children.length + 1}`;
|
|
1309
|
+
parent.children.push({
|
|
1310
|
+
id: newId,
|
|
1311
|
+
type: "decomposition",
|
|
1312
|
+
state: "open",
|
|
1313
|
+
title,
|
|
1314
|
+
priority
|
|
1315
|
+
});
|
|
1316
|
+
this.write(data);
|
|
1317
|
+
return data;
|
|
1318
|
+
}
|
|
1319
|
+
removeItem(id) {
|
|
1320
|
+
const data = this.read();
|
|
1321
|
+
const removed = this.removeItemFromList(data.items, id);
|
|
1322
|
+
if (!removed) throw new Error(`item ${id} not found`);
|
|
1323
|
+
this.write(data);
|
|
1324
|
+
return data;
|
|
1325
|
+
}
|
|
1286
1326
|
setStatus(status) {
|
|
1287
1327
|
const data = this.read();
|
|
1288
|
-
if (status === "passed" && data.items
|
|
1328
|
+
if (status === "passed" && this.hasOpenItems(data.items)) {
|
|
1289
1329
|
throw new Error("\u5B58\u5728\u672A\u5904\u7406\u7684\u8BC4\u5BA1\u9879(open),\u4E0D\u80FD\u901A\u8FC7");
|
|
1290
1330
|
}
|
|
1291
1331
|
data.status = status;
|
|
1292
1332
|
this.write(data);
|
|
1293
1333
|
return data;
|
|
1294
1334
|
}
|
|
1295
|
-
|
|
1335
|
+
listDocs() {
|
|
1336
|
+
const docsDir = path7.join(this.root, DOCS_DIR);
|
|
1337
|
+
if (!fs8.existsSync(docsDir)) return [];
|
|
1296
1338
|
try {
|
|
1297
|
-
|
|
1298
|
-
if (!fs8.existsSync(zdevDir) || !fs8.statSync(zdevDir).isDirectory()) return [];
|
|
1299
|
-
return fs8.readdirSync(zdevDir).filter((f) => /\.(md|markdown)$/i.test(f) && fs8.statSync(path7.join(zdevDir, f)).isFile()).sort();
|
|
1339
|
+
return fs8.readdirSync(docsDir).filter((f) => /\.(md|markdown|txt)$/i.test(f)).sort();
|
|
1300
1340
|
} catch {
|
|
1301
1341
|
return [];
|
|
1302
1342
|
}
|
|
1303
1343
|
}
|
|
1344
|
+
readDoc(name) {
|
|
1345
|
+
const fullPath = path7.join(this.root, DOCS_DIR, name);
|
|
1346
|
+
if (!fs8.existsSync(fullPath)) throw new Error(`doc ${name} not found`);
|
|
1347
|
+
return fs8.readFileSync(fullPath, "utf8");
|
|
1348
|
+
}
|
|
1349
|
+
listDiagrams() {
|
|
1350
|
+
const dir = path7.join(this.root, DIAGRAMS_DIR);
|
|
1351
|
+
if (!fs8.existsSync(dir)) return [];
|
|
1352
|
+
try {
|
|
1353
|
+
return fs8.readdirSync(dir).filter((f) => /\.html$/i.test(f)).sort();
|
|
1354
|
+
} catch {
|
|
1355
|
+
return [];
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
readDiagram(name) {
|
|
1359
|
+
const fullPath = path7.join(this.root, DIAGRAMS_DIR, name);
|
|
1360
|
+
if (!fs8.existsSync(fullPath)) throw new Error(`diagram ${name} not found`);
|
|
1361
|
+
return fs8.readFileSync(fullPath, "utf8");
|
|
1362
|
+
}
|
|
1363
|
+
findItem(items, id) {
|
|
1364
|
+
for (const item of items) {
|
|
1365
|
+
if (item.id === id) return item;
|
|
1366
|
+
if (item.children) {
|
|
1367
|
+
const found = this.findItem(item.children, id);
|
|
1368
|
+
if (found) return found;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
removeItemFromList(items, id) {
|
|
1374
|
+
for (let i = 0; i < items.length; i++) {
|
|
1375
|
+
if (items[i].id === id) {
|
|
1376
|
+
items.splice(i, 1);
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
if (items[i].children && this.removeItemFromList(items[i].children, id)) {
|
|
1380
|
+
return true;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return false;
|
|
1384
|
+
}
|
|
1385
|
+
hasOpenItems(items) {
|
|
1386
|
+
for (const item of items) {
|
|
1387
|
+
if (item.state === "open") return true;
|
|
1388
|
+
if (item.children && this.hasOpenItems(item.children)) return true;
|
|
1389
|
+
}
|
|
1390
|
+
return false;
|
|
1391
|
+
}
|
|
1304
1392
|
};
|
|
1305
1393
|
|
|
1306
1394
|
// src/plugins/review/index.ts
|
|
@@ -1310,7 +1398,7 @@ var apply5 = {
|
|
|
1310
1398
|
const root = config.root;
|
|
1311
1399
|
ctx.inject(["server"], () => {
|
|
1312
1400
|
if (!ctx.server?.route) return;
|
|
1313
|
-
ctx.dashboard.register({ mode: "review", label: "\u6587\u6863\u8BC4\u5BA1", icon: "\u2705", description: "
|
|
1401
|
+
ctx.dashboard.register({ mode: "review", label: "\u6587\u6863\u8BC4\u5BA1", icon: "\u2705", description: "\u591A\u6587\u6863\u9700\u6C42\u8BC4\u5BA1\u4E0E\u62C6\u89E3 \xB7 zreview" });
|
|
1314
1402
|
const reviewStore = new ReviewStore(root, () => {
|
|
1315
1403
|
ctx.reload.broadcast("files");
|
|
1316
1404
|
});
|
|
@@ -1326,7 +1414,44 @@ var apply5 = {
|
|
|
1326
1414
|
}
|
|
1327
1415
|
try {
|
|
1328
1416
|
const body = JSON.parse(await readBody(req) || "{}");
|
|
1329
|
-
const data = reviewStore.updateItem(body.id, {
|
|
1417
|
+
const data = reviewStore.updateItem(body.id, {
|
|
1418
|
+
answer: body.answer,
|
|
1419
|
+
state: body.state,
|
|
1420
|
+
priority: body.priority,
|
|
1421
|
+
title: body.title
|
|
1422
|
+
});
|
|
1423
|
+
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1424
|
+
res.end(JSON.stringify(data));
|
|
1425
|
+
} catch (e) {
|
|
1426
|
+
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
|
1427
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "unknown error" }));
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
ctx.server.route("/__review/item/add-child", async (req, res) => {
|
|
1431
|
+
if (req.headers["x-stop-token"] !== ctx.server.stopToken) {
|
|
1432
|
+
res.writeHead(403);
|
|
1433
|
+
res.end("forbidden");
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
const body = JSON.parse(await readBody(req) || "{}");
|
|
1438
|
+
const data = reviewStore.addChild(body.parentId, body.title, body.priority);
|
|
1439
|
+
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1440
|
+
res.end(JSON.stringify(data));
|
|
1441
|
+
} catch (e) {
|
|
1442
|
+
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
|
1443
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "unknown error" }));
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
ctx.server.route("/__review/item/remove", async (req, res) => {
|
|
1447
|
+
if (req.headers["x-stop-token"] !== ctx.server.stopToken) {
|
|
1448
|
+
res.writeHead(403);
|
|
1449
|
+
res.end("forbidden");
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
try {
|
|
1453
|
+
const body = JSON.parse(await readBody(req) || "{}");
|
|
1454
|
+
const data = reviewStore.removeItem(body.id);
|
|
1330
1455
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1331
1456
|
res.end(JSON.stringify(data));
|
|
1332
1457
|
} catch (e) {
|
|
@@ -1352,7 +1477,19 @@ var apply5 = {
|
|
|
1352
1477
|
});
|
|
1353
1478
|
ctx.server.route("/__docs", async (_req, res) => {
|
|
1354
1479
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1355
|
-
res.end(JSON.stringify(reviewStore.
|
|
1480
|
+
res.end(JSON.stringify(reviewStore.listDocs()));
|
|
1481
|
+
});
|
|
1482
|
+
ctx.server.route("/__docs/:name", async (req, res) => {
|
|
1483
|
+
try {
|
|
1484
|
+
const name = req.params?.name;
|
|
1485
|
+
if (!name) throw new Error("missing doc name");
|
|
1486
|
+
const content = reviewStore.readDoc(name);
|
|
1487
|
+
res.writeHead(200, { "Content-Type": "text/markdown; charset=utf-8", "Cache-Control": "no-cache" });
|
|
1488
|
+
res.end(content);
|
|
1489
|
+
} catch (e) {
|
|
1490
|
+
res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
|
|
1491
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : "not found" }));
|
|
1492
|
+
}
|
|
1356
1493
|
});
|
|
1357
1494
|
});
|
|
1358
1495
|
}
|