summaryrefslogtreecommitdiff
path: root/frontend/src/lib/draftGuard.ts
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-17 14:32:37 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-17 14:32:37 +0800
commit5c0ba37eda80d39e6ceca59bb1d5f4942f858995 (patch)
tree948723f9cedf7ccb0707fa6ee516bd30fe20fd10 /frontend/src/lib/draftGuard.ts
downloadstrategy-lab-5c0ba37eda80d39e6ceca59bb1d5f4942f858995.tar.gz
chore: establish Strategy Lab source baseline (development, not release)
Diffstat (limited to 'frontend/src/lib/draftGuard.ts')
-rw-r--r--frontend/src/lib/draftGuard.ts46
1 files changed, 46 insertions, 0 deletions
diff --git a/frontend/src/lib/draftGuard.ts b/frontend/src/lib/draftGuard.ts
new file mode 100644
index 0000000..d6a5222
--- /dev/null
+++ b/frontend/src/lib/draftGuard.ts
@@ -0,0 +1,46 @@
+import { diffLines, diffWordsWithSpace } from 'diff';
+
+export interface DiffStats {
+ added: number;
+ removed: number;
+}
+
+export function unifiedDiffStats(before: string, after: string): DiffStats {
+ const parts = diffLines(before, after);
+ let added = 0;
+ let removed = 0;
+ for (const p of parts) {
+ if (p.added) added += p.value.replace(/\n$/, '').split('\n').length;
+ else if (p.removed) removed += p.value.replace(/\n$/, '').split('\n').length;
+ }
+ return { added, removed };
+}
+
+export interface ServerDraft {
+ generation: number;
+ code: string;
+}
+
+export interface ConflictVerdict {
+ stale: boolean;
+ serverEqualsLocal: boolean;
+ localDirty: boolean;
+}
+
+export class ConflictResolver {
+ constructor(private local: { generation: number; code: string }) {}
+
+ onServerState(server: ServerDraft, lastKnownGeneration: number): ConflictVerdict {
+ const stale = server.generation !== lastKnownGeneration && lastKnownGeneration !== null;
+ const serverEqualsLocal = server.generation === this.local.generation && server.code === this.local.code;
+ return { stale, serverEqualsLocal, localDirty: true };
+ }
+
+ retryPlan(server: ServerDraft): { generation: number; code: string } {
+ return { generation: server.generation, code: this.local.code };
+ }
+}
+
+export function wordDiff(before: string, after: string) {
+ return diffWordsWithSpace(before, after);
+}