local-diff-reviewer 3.0.11 → 4.0.1
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/start.js +225 -10
- package/dist/web/assets/{arc-DXHF8Xjh.js → arc-BR56UJ2q.js} +1 -1
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-ULJhFTbi.js → architectureDiagram-3BPJPVTR-QSNoOmcD.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-DIADQ_Db.js → blockDiagram-GPEHLZMM-DIZH0QR3.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-BFpuzqsc.js → c4Diagram-AAUBKEIU-CPDSbt6E.js} +1 -1
- package/dist/web/assets/channel-B1I9H9NN.js +1 -0
- package/dist/web/assets/{chunk-2J33WTMH-9OzFjec-.js → chunk-2J33WTMH-DfV1Wxzg.js} +1 -1
- package/dist/web/assets/{chunk-3OPIFGDE-EFvQ3NBs.js → chunk-3OPIFGDE-B7UZbk4f.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-ONJ_mt24.js → chunk-4BX2VUAB-urkKkocB.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-QqFfqssu.js → chunk-55IACEB6-C8ylU6mt.js} +1 -1
- package/dist/web/assets/{chunk-5ZQYHXKU-D6msllU9.js → chunk-5ZQYHXKU-Cy7POa4x.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-CFg4EWdY.js → chunk-727SXJPM-C8E8Y71j.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-BeXyF8IX.js → chunk-AQP2D5EJ-D9rMJpjr.js} +1 -1
- package/dist/web/assets/{chunk-BSJP7CBP-NyyDjQ87.js → chunk-BSJP7CBP-DPOxgIuA.js} +1 -1
- package/dist/web/assets/{chunk-CSCIHK7Q-BF0nJmAe.js → chunk-CSCIHK7Q-NalEqjEe.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-CV7dwoCt.js → chunk-FMBD7UC4-CqHu0Ddy.js} +1 -1
- package/dist/web/assets/{chunk-KSCS5N6A-7RBrnQLn.js → chunk-KSCS5N6A-4DOHUm1X.js} +1 -1
- package/dist/web/assets/{chunk-L5ZTLDWV-BZglmESS.js → chunk-L5ZTLDWV-C2ELgJzw.js} +1 -1
- package/dist/web/assets/{chunk-LZXEDZCA-DxIwWmhs.js → chunk-LZXEDZCA-BB0BR9oJ.js} +2 -2
- package/dist/web/assets/{chunk-ND2GUHAM-A2GWzy8a.js → chunk-ND2GUHAM-Xhn_2Cqz.js} +1 -1
- package/dist/web/assets/{chunk-NZK2D7GU-BYPCWtIt.js → chunk-NZK2D7GU-zYi1cs9Z.js} +1 -1
- package/dist/web/assets/{chunk-O5CBEL6O-BuXZ1xgZ.js → chunk-O5CBEL6O-BODJA_dy.js} +1 -1
- package/dist/web/assets/chunk-QZHKN3VN-ByJ-AwbE.js +1 -0
- package/dist/web/assets/chunk-WU5MYG2G-D1aTMOQw.js +1 -0
- package/dist/web/assets/{chunk-XPW4576I-CrjhlLuT.js → chunk-XPW4576I-D8_9GoWv.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-DqiTlcHU.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-BCTUlGPz.js +1 -0
- package/dist/web/assets/{cose-bilkent-S5V4N54A-DFjrK-O7.js → cose-bilkent-S5V4N54A-BsloOG1M.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-AlQN943T.js → dagre-BM42HDAG-C2KIEcH-.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-B-yTojQn.js → diagram-2AECGRRQ-BUwRJ9KM.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-DM06sjaj.js → diagram-5GNKFQAL-BZPhOzmo.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-288OtixI.js → diagram-KO2AKTUF-CAUK4gKm.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-DFMXU6YQ.js → diagram-LMA3HP47-C_r9DVs_.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-B9fW2BsX.js → diagram-OG6HWLK6-31p4uFXJ.js} +1 -1
- package/dist/web/assets/{dist-BvZI7zIw.js → dist-Ck1Zve1a.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-GFhwFMWA.js → erDiagram-TEJ5UH35-C8EeJM7j.js} +1 -1
- package/dist/web/assets/{flowDiagram-I6XJVG4X-X0GzsqXd.js → flowDiagram-I6XJVG4X-BQqB8kKF.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-D9krnzcL.js → ganttDiagram-6RSMTGT7-4NPFmdaW.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-CHFX9mpW.js → gitGraphDiagram-PVQCEYII-CDmvFqiZ.js} +1 -1
- package/dist/web/assets/{index-VrNoEeV7.js → index-B_58iLIC.js} +20 -20
- package/dist/web/assets/index-Bp6Az-HB.css +1 -0
- package/dist/web/assets/{infoDiagram-5YYISTIA-Cjr_2IwG.js → infoDiagram-5YYISTIA-B7bI0yw0.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-_pI9bUMX.js → ishikawaDiagram-YF4QCWOH-D5xBBsAU.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-Wm-uvXkm.js → journeyDiagram-JHISSGLW-Bx7sCi9m.js} +1 -1
- package/dist/web/assets/{kanban-definition-UN3LZRKU-im0ALNi3.js → kanban-definition-UN3LZRKU-BZMYOpbE.js} +1 -1
- package/dist/web/assets/{line-Ca3yhFyP.js → line-D_c4pLL_.js} +1 -1
- package/dist/web/assets/{linear-BrB6R3UM.js → linear-jch8k3gY.js} +1 -1
- package/dist/web/assets/{mermaid-parser.core-Q_p_x88P.js → mermaid-parser.core-meE2GJWa.js} +1 -1
- package/dist/web/assets/{mermaid.core-CcZkq1Ys.js → mermaid.core-CED8hy6R.js} +3 -3
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-BYQ_7shU.js → mindmap-definition-RKZ34NQL-Dq5CdJkT.js} +1 -1
- package/dist/web/assets/{pieDiagram-4H26LBE5-CSrEqk1e.js → pieDiagram-4H26LBE5-tlCDWqfO.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-DvAYvPCK.js → quadrantDiagram-W4KKPZXB-DxqMe-7l.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-xsUUetfN.js → requirementDiagram-4Y6WPE33-Cit2aJnc.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-FpP4Fral.js → sankeyDiagram-5OEKKPKP-DxOco6qW.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DIhE7jBb.js → sequenceDiagram-3UESZ5HK-FxR-x1T2.js} +1 -1
- package/dist/web/assets/{src-BjU1Qb5i.js → src-R6QfzeRb.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-DzHUB4mR.js → stateDiagram-AJRCARHV-D_w-AmGN.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-CEnMp_RU.js +1 -0
- package/dist/web/assets/{timeline-definition-PNZ67QCA-CuNxP27U.js → timeline-definition-PNZ67QCA--m6p5F06.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-DrMSOIzz.js → vennDiagram-CIIHVFJN-BvTLOSov.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-D9LY-mKZ.js → wardleyDiagram-YWT4CUSO-suMirVgL.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-CQAaO6Ia.js → xychartDiagram-2RQKCTM6-BDTgsmAY.js} +1 -1
- package/dist/web/index.html +2 -2
- package/docs/images/diff-review-ui.jpg +0 -0
- package/package.json +1 -1
- package/dist/web/assets/channel-B4GK5WC3.js +0 -1
- package/dist/web/assets/chunk-QZHKN3VN-C4R4Iq0n.js +0 -1
- package/dist/web/assets/chunk-WU5MYG2G-uDn33PFD.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-B-ab5Qcl.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-mOcBwqwQ.js +0 -1
- package/dist/web/assets/index-Ci6CsMGU.css +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-FTSfnTDs.js +0 -1
package/dist/cli/start.js
CHANGED
|
@@ -8,7 +8,7 @@ import { basename as basename3, dirname as dirname3, join as join5, resolve as r
|
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
|
|
10
10
|
// src/server/storage.ts
|
|
11
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
11
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
13
|
import { homedir, platform } from "node:os";
|
|
14
14
|
import { basename, dirname, join } from "node:path";
|
|
@@ -68,16 +68,27 @@ async function attachLegacyComments(repoRoot, diffHash2, diffFiles) {
|
|
|
68
68
|
async function readCommentStore(repoRoot) {
|
|
69
69
|
const path = commentsPath(repoRoot);
|
|
70
70
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
const text = await readFile(path, "utf8");
|
|
72
|
+
return normalizeStore(parseCommentStore(text));
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (!isMissingFileError(error)) {
|
|
75
|
+
const recovered = await recoverCommentStore(repoRoot, path, error);
|
|
76
|
+
if (recovered) return recovered;
|
|
77
|
+
}
|
|
73
78
|
return readLegacyComments(repoRoot);
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
async function writeComments(repoRoot, store) {
|
|
77
82
|
const path = commentsPath(repoRoot);
|
|
83
|
+
const tempPath = `${path}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
78
84
|
await mkdir(dirname(path), { recursive: true });
|
|
79
|
-
|
|
85
|
+
try {
|
|
86
|
+
await writeFile(tempPath, `${JSON.stringify(store, null, 2)}
|
|
80
87
|
`, "utf8");
|
|
88
|
+
await rename(tempPath, path);
|
|
89
|
+
} finally {
|
|
90
|
+
await rm(tempPath, { force: true }).catch(() => void 0);
|
|
91
|
+
}
|
|
81
92
|
}
|
|
82
93
|
function commentsPath(repoRoot) {
|
|
83
94
|
const repoName = basename(repoRoot) || "repo";
|
|
@@ -92,11 +103,71 @@ function commentLogsDir() {
|
|
|
92
103
|
}
|
|
93
104
|
async function readLegacyComments(repoRoot) {
|
|
94
105
|
try {
|
|
95
|
-
return normalizeStore(
|
|
106
|
+
return normalizeStore(parseCommentStore(await readFile(join(repoRoot, ".diff-review", "comments.json"), "utf8")));
|
|
96
107
|
} catch {
|
|
97
108
|
return { threads: [] };
|
|
98
109
|
}
|
|
99
110
|
}
|
|
111
|
+
async function recoverCommentStore(repoRoot, path, cause) {
|
|
112
|
+
try {
|
|
113
|
+
const recovered = normalizeStore(parseRecoverableCommentStore(await readFile(path, "utf8")));
|
|
114
|
+
await writeComments(repoRoot, recovered);
|
|
115
|
+
return recovered;
|
|
116
|
+
} catch {
|
|
117
|
+
console.warn(`Failed to read comment store ${path}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function parseCommentStore(text) {
|
|
122
|
+
const parsed = JSON.parse(text);
|
|
123
|
+
if (!Array.isArray(parsed.threads)) return { threads: [] };
|
|
124
|
+
return parsed;
|
|
125
|
+
}
|
|
126
|
+
function parseRecoverableCommentStore(text) {
|
|
127
|
+
const end = findRootJsonObjectEnd(text);
|
|
128
|
+
if (end === -1) throw new Error("Comment store does not contain a complete JSON object");
|
|
129
|
+
return parseCommentStore(text.slice(0, end));
|
|
130
|
+
}
|
|
131
|
+
function findRootJsonObjectEnd(text) {
|
|
132
|
+
let depth = 0;
|
|
133
|
+
let inString = false;
|
|
134
|
+
let escaped = false;
|
|
135
|
+
let started = false;
|
|
136
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
137
|
+
const char = text[index];
|
|
138
|
+
if (!started) {
|
|
139
|
+
if (/\s/.test(char)) continue;
|
|
140
|
+
if (char !== "{") return -1;
|
|
141
|
+
started = true;
|
|
142
|
+
}
|
|
143
|
+
if (inString) {
|
|
144
|
+
if (escaped) {
|
|
145
|
+
escaped = false;
|
|
146
|
+
} else if (char === "\\") {
|
|
147
|
+
escaped = true;
|
|
148
|
+
} else if (char === '"') {
|
|
149
|
+
inString = false;
|
|
150
|
+
}
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (char === '"') {
|
|
154
|
+
inString = true;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (char === "{") {
|
|
158
|
+
depth += 1;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (char === "}") {
|
|
162
|
+
depth -= 1;
|
|
163
|
+
if (depth === 0) return index + 1;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
function isMissingFileError(error) {
|
|
169
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
170
|
+
}
|
|
100
171
|
function normalizeStore(store) {
|
|
101
172
|
const groups = /* @__PURE__ */ new Map();
|
|
102
173
|
for (const thread of store.threads) {
|
|
@@ -850,9 +921,108 @@ function getThreadLocation(thread) {
|
|
|
850
921
|
return `${thread.filePath}:${thread.anchor.lineNumber}`;
|
|
851
922
|
}
|
|
852
923
|
|
|
924
|
+
// src/server/file-watcher-service.ts
|
|
925
|
+
import { watch } from "node:fs";
|
|
926
|
+
var FileWatcherService = class {
|
|
927
|
+
constructor(repoRoot) {
|
|
928
|
+
this.repoRoot = repoRoot;
|
|
929
|
+
this.startWatching();
|
|
930
|
+
}
|
|
931
|
+
repoRoot;
|
|
932
|
+
clients = /* @__PURE__ */ new Set();
|
|
933
|
+
watchers = [];
|
|
934
|
+
pendingChanges = false;
|
|
935
|
+
debounceTimer = null;
|
|
936
|
+
closed = false;
|
|
937
|
+
/**
|
|
938
|
+
* 注册一个 SSE 客户端,并立即同步当前是否存在待刷新的文件变化。
|
|
939
|
+
*/
|
|
940
|
+
subscribe(res) {
|
|
941
|
+
this.clients.add(res);
|
|
942
|
+
this.send(res, {
|
|
943
|
+
type: "connected",
|
|
944
|
+
hasPendingChanges: this.pendingChanges
|
|
945
|
+
});
|
|
946
|
+
res.on("close", () => {
|
|
947
|
+
this.clients.delete(res);
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* 在 review 快照已经重算后清空待刷新状态,并通知前端恢复为最新快照。
|
|
952
|
+
*/
|
|
953
|
+
clearPendingChanges() {
|
|
954
|
+
if (!this.pendingChanges) return;
|
|
955
|
+
this.pendingChanges = false;
|
|
956
|
+
this.broadcast({ type: "synced", hasPendingChanges: false });
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* 释放底层文件监听资源,避免 runtime 退出后留下悬挂 watcher。
|
|
960
|
+
*/
|
|
961
|
+
dispose() {
|
|
962
|
+
this.closed = true;
|
|
963
|
+
if (this.debounceTimer) {
|
|
964
|
+
clearTimeout(this.debounceTimer);
|
|
965
|
+
this.debounceTimer = null;
|
|
966
|
+
}
|
|
967
|
+
this.watchers.splice(0).forEach((watcher) => watcher.close());
|
|
968
|
+
this.clients.forEach((client) => client.end());
|
|
969
|
+
this.clients.clear();
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* 优先使用递归监听整个仓库;若运行环境不支持,则退化为监听仓库根和 `.git`。
|
|
973
|
+
*/
|
|
974
|
+
startWatching() {
|
|
975
|
+
if (this.tryWatch(this.repoRoot, { recursive: true })) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
this.tryWatch(this.repoRoot);
|
|
979
|
+
this.tryWatch(`${this.repoRoot}/.git`);
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* 把短时间内的多次磁盘事件合并成一次“可刷新”通知,避免前端按钮频繁闪动。
|
|
983
|
+
*/
|
|
984
|
+
handleChange() {
|
|
985
|
+
if (this.closed) return;
|
|
986
|
+
this.pendingChanges = true;
|
|
987
|
+
if (this.debounceTimer) {
|
|
988
|
+
clearTimeout(this.debounceTimer);
|
|
989
|
+
}
|
|
990
|
+
this.debounceTimer = setTimeout(() => {
|
|
991
|
+
this.debounceTimer = null;
|
|
992
|
+
this.broadcast({
|
|
993
|
+
type: "change",
|
|
994
|
+
hasPendingChanges: true,
|
|
995
|
+
changedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
996
|
+
});
|
|
997
|
+
}, 180);
|
|
998
|
+
}
|
|
999
|
+
tryWatch(path, options) {
|
|
1000
|
+
try {
|
|
1001
|
+
const watcher = watch(path, options ?? {}, () => {
|
|
1002
|
+
this.handleChange();
|
|
1003
|
+
});
|
|
1004
|
+
this.watchers.push(watcher);
|
|
1005
|
+
return true;
|
|
1006
|
+
} catch {
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
broadcast(event) {
|
|
1011
|
+
this.clients.forEach((client) => {
|
|
1012
|
+
this.send(client, event);
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
send(res, event) {
|
|
1016
|
+
res.write(`data: ${JSON.stringify(event)}
|
|
1017
|
+
|
|
1018
|
+
`);
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
|
|
853
1022
|
// src/server/index.ts
|
|
854
1023
|
async function startServer(state, port = 4966) {
|
|
855
1024
|
let markdownPreviews = await buildMarkdownPreviewCache(state);
|
|
1025
|
+
const fileWatcher = new FileWatcherService(state.session.repoRoot);
|
|
856
1026
|
const app = express();
|
|
857
1027
|
app.use(express.json({ limit: "2mb" }));
|
|
858
1028
|
app.get("/api/session", (_req, res) => {
|
|
@@ -885,13 +1055,34 @@ async function startServer(state, port = 4966) {
|
|
|
885
1055
|
webDist: state.webDist
|
|
886
1056
|
};
|
|
887
1057
|
markdownPreviews = await buildMarkdownPreviewCache(nextReviewState);
|
|
888
|
-
state
|
|
889
|
-
|
|
1058
|
+
applyReviewState(state, nextReviewState);
|
|
1059
|
+
fileWatcher.clearPendingChanges();
|
|
890
1060
|
res.json({ session: state.session, files: state.diffFiles });
|
|
891
1061
|
} catch (error) {
|
|
892
1062
|
next(error);
|
|
893
1063
|
}
|
|
894
1064
|
});
|
|
1065
|
+
app.get("/api/watch", (_req, res) => {
|
|
1066
|
+
res.writeHead(200, {
|
|
1067
|
+
"Content-Type": "text/event-stream",
|
|
1068
|
+
"Cache-Control": "no-cache, no-transform",
|
|
1069
|
+
Connection: "keep-alive"
|
|
1070
|
+
});
|
|
1071
|
+
res.write(": connected\n\n");
|
|
1072
|
+
fileWatcher.subscribe(res);
|
|
1073
|
+
});
|
|
1074
|
+
app.post("/api/refresh", async (_req, res, next) => {
|
|
1075
|
+
try {
|
|
1076
|
+
const nextReviewState = await rebuildReviewState(state);
|
|
1077
|
+
markdownPreviews = await buildMarkdownPreviewCache(nextReviewState);
|
|
1078
|
+
applyReviewState(state, nextReviewState);
|
|
1079
|
+
fileWatcher.clearPendingChanges();
|
|
1080
|
+
const comments = await readComments(state.session.repoRoot);
|
|
1081
|
+
res.json({ session: state.session, files: state.diffFiles, threads: comments.threads });
|
|
1082
|
+
} catch (error) {
|
|
1083
|
+
next(error);
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
895
1086
|
app.get("/api/markdown-preview", async (req, res, next) => {
|
|
896
1087
|
try {
|
|
897
1088
|
const filePath = String(req.query.path ?? "");
|
|
@@ -1168,7 +1359,7 @@ async function startServer(state, port = 4966) {
|
|
|
1168
1359
|
app.use((error, _req, res, _next) => {
|
|
1169
1360
|
res.status(500).json({ error: error.message });
|
|
1170
1361
|
});
|
|
1171
|
-
return listen(app, port);
|
|
1362
|
+
return listen(app, port, fileWatcher);
|
|
1172
1363
|
}
|
|
1173
1364
|
async function buildMarkdownPreviewCache(state) {
|
|
1174
1365
|
const previews = /* @__PURE__ */ new Map();
|
|
@@ -1187,12 +1378,36 @@ async function buildMarkdownPreviewCache(state) {
|
|
|
1187
1378
|
);
|
|
1188
1379
|
return previews;
|
|
1189
1380
|
}
|
|
1190
|
-
function
|
|
1381
|
+
function applyReviewState(currentState, nextState) {
|
|
1382
|
+
currentState.session = nextState.session;
|
|
1383
|
+
currentState.diffFiles = nextState.diffFiles;
|
|
1384
|
+
}
|
|
1385
|
+
async function rebuildReviewState(state) {
|
|
1386
|
+
const diff = await getDiff(state.session.mode, state.session.repoRoot);
|
|
1387
|
+
const diffFiles = parseUnifiedDiff(diff);
|
|
1388
|
+
const session = {
|
|
1389
|
+
id: crypto.randomUUID(),
|
|
1390
|
+
repoName: state.session.repoName,
|
|
1391
|
+
repoRoot: state.session.repoRoot,
|
|
1392
|
+
mode: state.session.mode,
|
|
1393
|
+
diffHash: diffHash(diff),
|
|
1394
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1395
|
+
};
|
|
1396
|
+
return {
|
|
1397
|
+
session,
|
|
1398
|
+
diffFiles,
|
|
1399
|
+
webDist: state.webDist
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
function listen(app, port, fileWatcher) {
|
|
1191
1403
|
return new Promise((resolve3, reject) => {
|
|
1192
1404
|
const server = createServer(app);
|
|
1405
|
+
server.once("close", () => {
|
|
1406
|
+
fileWatcher.dispose();
|
|
1407
|
+
});
|
|
1193
1408
|
server.once("error", (error) => {
|
|
1194
1409
|
if (error.code === "EADDRINUSE" && port !== 0) {
|
|
1195
|
-
listen(app, 0).then(resolve3, reject);
|
|
1410
|
+
listen(app, 0, fileWatcher).then(resolve3, reject);
|
|
1196
1411
|
return;
|
|
1197
1412
|
}
|
|
1198
1413
|
reject(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-BJQEcSo7.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-
|
|
1
|
+
import{n as e,t}from"./path-BJQEcSo7.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-Ck1Zve1a.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|