@youtyan/code-viewer 0.8.3 → 0.8.5
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/code-viewer.js +491 -483
- package/package.json +1 -1
- package/web/app.js +246 -87
package/dist/code-viewer.js
CHANGED
|
@@ -94,6 +94,157 @@ var init_sqlite_driver = __esm(() => {
|
|
|
94
94
|
NPX_CACHE_GUIDE = 'Stale npx cache likely contains a binary compiled for a different Node.js version. Fix: `rm -rf ~/.npm/_npx` (macOS / Linux) or `Remove-Item -Recurse -Force "$(npm config get cache)\\_npx"` (Windows), ' + "then re-run `npx -y @youtyan/code-viewer@latest …`.";
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
// web-src/core/id.ts
|
|
98
|
+
function bytesToHex(bytes) {
|
|
99
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
100
|
+
}
|
|
101
|
+
function bytesToBase36(bytes) {
|
|
102
|
+
return Array.from(bytes, (b) => BASE36_ALPHABET[b % BASE36_ALPHABET.length]).join("");
|
|
103
|
+
}
|
|
104
|
+
function randomBase36(length) {
|
|
105
|
+
const cryptoApi = globalThis.crypto;
|
|
106
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
107
|
+
const bytes = new Uint8Array(length);
|
|
108
|
+
cryptoApi.getRandomValues(bytes);
|
|
109
|
+
return bytesToBase36(bytes);
|
|
110
|
+
}
|
|
111
|
+
return Math.random().toString(36).slice(2, 2 + length).padEnd(length, "0");
|
|
112
|
+
}
|
|
113
|
+
function makeId(prefix) {
|
|
114
|
+
const cryptoApi = globalThis.crypto;
|
|
115
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
116
|
+
return `${prefix}-${cryptoApi.randomUUID().replace(/-/g, "").slice(0, 16)}`;
|
|
117
|
+
}
|
|
118
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
119
|
+
const bytes = new Uint8Array(8);
|
|
120
|
+
cryptoApi.getRandomValues(bytes);
|
|
121
|
+
return `${prefix}-${bytesToHex(bytes)}`;
|
|
122
|
+
}
|
|
123
|
+
return `${prefix}-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
124
|
+
}
|
|
125
|
+
function makeTimedId(prefix) {
|
|
126
|
+
const time = Date.now().toString(36);
|
|
127
|
+
const random = randomBase36(6);
|
|
128
|
+
return `${prefix}-${time}${random}`;
|
|
129
|
+
}
|
|
130
|
+
var BASE36_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
131
|
+
|
|
132
|
+
// web-src/core/routes.ts
|
|
133
|
+
function assertNever(value) {
|
|
134
|
+
throw new Error(`unhandled route: ${JSON.stringify(value)}`);
|
|
135
|
+
}
|
|
136
|
+
function parseLineTarget(value) {
|
|
137
|
+
const raw = value || "";
|
|
138
|
+
const range = /^(\d+)-(\d+)$/.exec(raw);
|
|
139
|
+
if (range) {
|
|
140
|
+
const a = Number(range[1]);
|
|
141
|
+
const b = Number(range[2]);
|
|
142
|
+
const start = Math.min(a, b);
|
|
143
|
+
const end = Math.max(a, b);
|
|
144
|
+
if (start > 0)
|
|
145
|
+
return { start, end };
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const line = Number(raw);
|
|
149
|
+
return Number.isInteger(line) && line > 0 ? line : undefined;
|
|
150
|
+
}
|
|
151
|
+
function formatLineTarget(line) {
|
|
152
|
+
return typeof line === "number" ? String(line) : `${line.start}-${line.end}`;
|
|
153
|
+
}
|
|
154
|
+
function buildRoute(route) {
|
|
155
|
+
switch (route.screen) {
|
|
156
|
+
case "repo": {
|
|
157
|
+
const params = new URLSearchParams;
|
|
158
|
+
if (route.ref && route.ref !== "worktree")
|
|
159
|
+
params.set("ref", route.ref);
|
|
160
|
+
if (route.path)
|
|
161
|
+
params.set("path", route.path);
|
|
162
|
+
const qs = params.toString();
|
|
163
|
+
return `/${qs ? `?${qs}` : ""}`;
|
|
164
|
+
}
|
|
165
|
+
case "file":
|
|
166
|
+
if (route.view === "blob") {
|
|
167
|
+
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + "&view=blob" + (route.preview ? "&preview=1" : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "") + (route.virtual === "off" ? "&virtual=off" : "");
|
|
168
|
+
}
|
|
169
|
+
if (route.view === "blame") {
|
|
170
|
+
const ref = route.ref || "worktree";
|
|
171
|
+
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(ref) + "&view=blame" + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
172
|
+
}
|
|
173
|
+
if (route.view === "history") {
|
|
174
|
+
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + "&view=history" + (route.commit ? `&commit=${encodeURIComponent(route.commit)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
175
|
+
}
|
|
176
|
+
return "/file?path=" + encodeURIComponent(route.path) + "&ref=" + encodeURIComponent(route.ref || "worktree") + "&from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "") + (route.virtual === "off" ? "&virtual=off" : "");
|
|
177
|
+
case "diff":
|
|
178
|
+
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ? `&path=${encodeURIComponent(route.path)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
179
|
+
case "help": {
|
|
180
|
+
const params = new URLSearchParams;
|
|
181
|
+
if (route.lang && route.lang !== "en")
|
|
182
|
+
params.set("lang", route.lang);
|
|
183
|
+
if (route.section && route.section !== "overview")
|
|
184
|
+
params.set("section", route.section);
|
|
185
|
+
const qs = params.toString();
|
|
186
|
+
return `/help${qs ? `?${qs}` : ""}`;
|
|
187
|
+
}
|
|
188
|
+
case "history": {
|
|
189
|
+
const params = new URLSearchParams;
|
|
190
|
+
if (route.ref && route.ref !== "HEAD")
|
|
191
|
+
params.set("ref", route.ref);
|
|
192
|
+
if (route.commit)
|
|
193
|
+
params.set("commit", route.commit);
|
|
194
|
+
const qs = params.toString();
|
|
195
|
+
return `/history${qs ? `?${qs}` : ""}`;
|
|
196
|
+
}
|
|
197
|
+
case "journal": {
|
|
198
|
+
const params = new URLSearchParams;
|
|
199
|
+
if (route.tab && route.tab !== "journal")
|
|
200
|
+
params.set("tab", route.tab);
|
|
201
|
+
if (route.date)
|
|
202
|
+
params.set("date", route.date);
|
|
203
|
+
if (route.label)
|
|
204
|
+
params.set("label", route.label);
|
|
205
|
+
if (route.task)
|
|
206
|
+
params.set("task", route.task);
|
|
207
|
+
const qs = params.toString();
|
|
208
|
+
return `/journal${qs ? `?${qs}` : ""}`;
|
|
209
|
+
}
|
|
210
|
+
case "database": {
|
|
211
|
+
const params = new URLSearchParams;
|
|
212
|
+
if (route.db)
|
|
213
|
+
params.set("db", route.db);
|
|
214
|
+
if (route.schema)
|
|
215
|
+
params.set("schema", route.schema);
|
|
216
|
+
if (route.table)
|
|
217
|
+
params.set("table", route.table);
|
|
218
|
+
if (route.tab)
|
|
219
|
+
params.set("tab", route.tab);
|
|
220
|
+
if (route.diffBefore)
|
|
221
|
+
params.set("diffBefore", route.diffBefore);
|
|
222
|
+
if (route.diffAfter)
|
|
223
|
+
params.set("diffAfter", route.diffAfter);
|
|
224
|
+
const qs = params.toString();
|
|
225
|
+
return `/database${qs ? `?${qs}` : ""}`;
|
|
226
|
+
}
|
|
227
|
+
case "unknown":
|
|
228
|
+
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree");
|
|
229
|
+
default:
|
|
230
|
+
return assertNever(route);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
var SPA_PATHS, APP_ENTRY_PATHS;
|
|
234
|
+
var init_routes = __esm(() => {
|
|
235
|
+
SPA_PATHS = [
|
|
236
|
+
"/todif",
|
|
237
|
+
"/todiff",
|
|
238
|
+
"/file",
|
|
239
|
+
"/help",
|
|
240
|
+
"/history",
|
|
241
|
+
"/journal",
|
|
242
|
+
"/database",
|
|
243
|
+
"/doctor"
|
|
244
|
+
];
|
|
245
|
+
APP_ENTRY_PATHS = ["/", "/index.html"];
|
|
246
|
+
});
|
|
247
|
+
|
|
97
248
|
// web-src/server/json-store.ts
|
|
98
249
|
import { randomBytes } from "node:crypto";
|
|
99
250
|
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
@@ -205,6 +356,11 @@ function createJsonFileStore(options) {
|
|
|
205
356
|
}
|
|
206
357
|
var init_json_store = () => {};
|
|
207
358
|
|
|
359
|
+
// web-src/server/ordered-insert.ts
|
|
360
|
+
function orderedInsertOptionCount(input) {
|
|
361
|
+
return (input.before_id ? 1 : 0) + (input.after_id ? 1 : 0) + (input.position !== undefined ? 1 : 0);
|
|
362
|
+
}
|
|
363
|
+
|
|
208
364
|
// web-src/server/annotations.ts
|
|
209
365
|
import { join } from "node:path";
|
|
210
366
|
function annotationsFilePath(root) {
|
|
@@ -214,9 +370,7 @@ function emptyAnnotationsState() {
|
|
|
214
370
|
return { version: 1, sessions: [] };
|
|
215
371
|
}
|
|
216
372
|
function makeAnnotationId(prefix) {
|
|
217
|
-
|
|
218
|
-
const time = Date.now().toString(36);
|
|
219
|
-
return `${prefix}-${time}${random}`;
|
|
373
|
+
return makeTimedId(prefix);
|
|
220
374
|
}
|
|
221
375
|
function normalizeLineRange(raw) {
|
|
222
376
|
if (!raw || typeof raw !== "object")
|
|
@@ -229,16 +383,10 @@ function normalizeLineRange(raw) {
|
|
|
229
383
|
return { start, end: endValue };
|
|
230
384
|
}
|
|
231
385
|
function parseAnnotationLine(raw) {
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const start = Math.min(a, b);
|
|
237
|
-
const end = Math.max(a, b);
|
|
238
|
-
return start > 0 ? { start, end } : undefined;
|
|
239
|
-
}
|
|
240
|
-
const line = Number(raw);
|
|
241
|
-
return Number.isInteger(line) && line > 0 ? { start: line, end: line } : undefined;
|
|
386
|
+
const target = parseLineTarget(raw);
|
|
387
|
+
if (target === undefined)
|
|
388
|
+
return;
|
|
389
|
+
return typeof target === "number" ? { start: target, end: target } : target;
|
|
242
390
|
}
|
|
243
391
|
function normalizeRange(raw) {
|
|
244
392
|
const from = raw && typeof raw === "object" && typeof raw.from === "string" ? raw.from || "HEAD" : "HEAD";
|
|
@@ -441,11 +589,8 @@ function startAnnotationSession(state, title, now, id = makeAnnotationId("s")) {
|
|
|
441
589
|
session
|
|
442
590
|
};
|
|
443
591
|
}
|
|
444
|
-
function insertOptionCount(input) {
|
|
445
|
-
return (input.before_id ? 1 : 0) + (input.after_id ? 1 : 0) + (input.position !== undefined ? 1 : 0);
|
|
446
|
-
}
|
|
447
592
|
function entryInsertIndex(entries, input) {
|
|
448
|
-
if (
|
|
593
|
+
if (orderedInsertOptionCount(input) > 1)
|
|
449
594
|
return { ok: false, error: "use only one of before, after, or position" };
|
|
450
595
|
if (input.before_id) {
|
|
451
596
|
const index = entries.findIndex((entry) => entry.id === input.before_id);
|
|
@@ -471,7 +616,7 @@ function entryInsertIndex(entries, input) {
|
|
|
471
616
|
function findSessionByEntryId(sessions, entryId) {
|
|
472
617
|
return sessions.find((session) => session.entries.some((entry) => entry.id === entryId));
|
|
473
618
|
}
|
|
474
|
-
function addAnnotationEntry(state, input, now,
|
|
619
|
+
function addAnnotationEntry(state, input, now, makeId2 = makeAnnotationId) {
|
|
475
620
|
const target = normalizeAnnotationTarget(input.target);
|
|
476
621
|
if (target?.kind === "database" && !target.db)
|
|
477
622
|
return { ok: false, error: "database annotation requires db" };
|
|
@@ -514,13 +659,13 @@ function addAnnotationEntry(state, input, now, makeId = makeAnnotationId) {
|
|
|
514
659
|
session = sessions[sessions.length - 1];
|
|
515
660
|
}
|
|
516
661
|
if (!session) {
|
|
517
|
-
const started = startAnnotationSession(state, input.session_title || "", now,
|
|
662
|
+
const started = startAnnotationSession(state, input.session_title || "", now, makeId2("s"));
|
|
518
663
|
sessions = started.state.sessions;
|
|
519
664
|
session = started.session;
|
|
520
665
|
createdSession = true;
|
|
521
666
|
}
|
|
522
667
|
const entry = {
|
|
523
|
-
id:
|
|
668
|
+
id: makeId2("a"),
|
|
524
669
|
created_at: now,
|
|
525
670
|
path,
|
|
526
671
|
range: normalizeRange(input.range),
|
|
@@ -554,7 +699,7 @@ function addAnnotationEntry(state, input, now, makeId = makeAnnotationId) {
|
|
|
554
699
|
};
|
|
555
700
|
}
|
|
556
701
|
function moveAnnotationEntry(state, id, input) {
|
|
557
|
-
if (
|
|
702
|
+
if (orderedInsertOptionCount(input) !== 1)
|
|
558
703
|
return { ok: false, error: "move requires before, after, or position" };
|
|
559
704
|
const sourceSession = findSessionByEntryId(state.sessions, id);
|
|
560
705
|
const entry = sourceSession?.entries.find((e) => e.id === id);
|
|
@@ -654,6 +799,7 @@ function deleteAnnotationById(state, id) {
|
|
|
654
799
|
}
|
|
655
800
|
var CODE_VIEWER_DIR = ".code-viewer", ANNOTATIONS_FILE_NAME = "annotations.json", ANNOTATION_BODY_MAX_BYTES, ANNOTATION_TITLE_MAX_CHARS = 300, MAX_ANNOTATIONS_JSON_BYTES = 5000000, annotationsStore;
|
|
656
801
|
var init_annotations = __esm(() => {
|
|
802
|
+
init_routes();
|
|
657
803
|
init_json_store();
|
|
658
804
|
ANNOTATION_BODY_MAX_BYTES = 64 * 1024;
|
|
659
805
|
annotationsStore = createJsonFileStore({
|
|
@@ -666,47 +812,9 @@ var init_annotations = __esm(() => {
|
|
|
666
812
|
});
|
|
667
813
|
});
|
|
668
814
|
|
|
669
|
-
// web-src/server/cache.ts
|
|
670
|
-
import { lstatSync } from "node:fs";
|
|
671
|
-
import { join as join2 } from "node:path";
|
|
672
|
-
function cacheFresh(cached, now = Date.now(), ttlMs = CACHE_TTL_MS) {
|
|
673
|
-
return !!cached && now - cached.storedAt <= ttlMs;
|
|
674
|
-
}
|
|
675
|
-
function setTimedCacheEntry(cache, key, value, now = Date.now(), maxEntries = MAX_TIMED_CACHE_ENTRIES) {
|
|
676
|
-
cache.set(key, { ...value, storedAt: now });
|
|
677
|
-
while (cache.size > maxEntries) {
|
|
678
|
-
const oldest = cache.keys().next().value;
|
|
679
|
-
if (oldest === undefined)
|
|
680
|
-
break;
|
|
681
|
-
cache.delete(oldest);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
function worktreeFileSignature(path, cwd) {
|
|
685
|
-
try {
|
|
686
|
-
const stats = lstatSync(join2(cwd, path));
|
|
687
|
-
const inode = "ino" in stats ? stats.ino : 0;
|
|
688
|
-
return `state:file|size:${stats.size}|mtime:${stats.mtimeMs}|ctime:${stats.ctimeMs}|ino:${inode}`;
|
|
689
|
-
} catch {
|
|
690
|
-
return "state:missing";
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
function fileDiffCacheKey(options) {
|
|
694
|
-
const worktreeTarget = options.range.from === "worktree" || !options.range.to || options.range.to === "worktree";
|
|
695
|
-
if (options.isUntracked && !worktreeTarget) {
|
|
696
|
-
throw new Error("untracked file diffs require a worktree range");
|
|
697
|
-
}
|
|
698
|
-
const signature = worktreeTarget ? `\x00${worktreeFileSignature(options.path, options.cwd)}` : "";
|
|
699
|
-
if (options.isUntracked) {
|
|
700
|
-
return `u\x00${options.path}${signature}\x00${options.extras.join("\x00")}`;
|
|
701
|
-
}
|
|
702
|
-
return `t\x00${options.path}\x00${options.oldPath || ""}${signature}\x00${[...options.extras, ...options.args].join("\x00")}`;
|
|
703
|
-
}
|
|
704
|
-
var CACHE_TTL_MS = 1500, MAX_TIMED_CACHE_ENTRIES = 200;
|
|
705
|
-
var init_cache = () => {};
|
|
706
|
-
|
|
707
815
|
// web-src/server/command-resolver.ts
|
|
708
816
|
import { accessSync, constants, realpathSync, statSync } from "node:fs";
|
|
709
|
-
import { dirname as dirname2, isAbsolute, join as
|
|
817
|
+
import { dirname as dirname2, isAbsolute, join as join2, relative } from "node:path";
|
|
710
818
|
function isExternalCommandName(value) {
|
|
711
819
|
return commandNameSet.has(value);
|
|
712
820
|
}
|
|
@@ -841,7 +949,7 @@ function findGitRootByWalking(start) {
|
|
|
841
949
|
let current = start;
|
|
842
950
|
for (;; ) {
|
|
843
951
|
try {
|
|
844
|
-
statSync(
|
|
952
|
+
statSync(join2(current, ".git"));
|
|
845
953
|
return realpathSync(current);
|
|
846
954
|
} catch {}
|
|
847
955
|
const parent = dirname2(current);
|
|
@@ -873,6 +981,44 @@ var init_command_resolver = __esm(() => {
|
|
|
873
981
|
activeOverrides = new Map;
|
|
874
982
|
});
|
|
875
983
|
|
|
984
|
+
// web-src/server/cache.ts
|
|
985
|
+
import { lstatSync } from "node:fs";
|
|
986
|
+
import { join as join3 } from "node:path";
|
|
987
|
+
function cacheFresh(cached, now = Date.now(), ttlMs = CACHE_TTL_MS) {
|
|
988
|
+
return !!cached && now - cached.storedAt <= ttlMs;
|
|
989
|
+
}
|
|
990
|
+
function setTimedCacheEntry(cache, key, value, now = Date.now(), maxEntries = MAX_TIMED_CACHE_ENTRIES) {
|
|
991
|
+
cache.set(key, { ...value, storedAt: now });
|
|
992
|
+
while (cache.size > maxEntries) {
|
|
993
|
+
const oldest = cache.keys().next().value;
|
|
994
|
+
if (oldest === undefined)
|
|
995
|
+
break;
|
|
996
|
+
cache.delete(oldest);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
function worktreeFileSignature(path, cwd) {
|
|
1000
|
+
try {
|
|
1001
|
+
const stats = lstatSync(join3(cwd, path));
|
|
1002
|
+
const inode = "ino" in stats ? stats.ino : 0;
|
|
1003
|
+
return `state:file|size:${stats.size}|mtime:${stats.mtimeMs}|ctime:${stats.ctimeMs}|ino:${inode}`;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return "state:missing";
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function fileDiffCacheKey(options) {
|
|
1009
|
+
const worktreeTarget = options.range.from === "worktree" || !options.range.to || options.range.to === "worktree";
|
|
1010
|
+
if (options.isUntracked && !worktreeTarget) {
|
|
1011
|
+
throw new Error("untracked file diffs require a worktree range");
|
|
1012
|
+
}
|
|
1013
|
+
const signature = worktreeTarget ? `\x00${worktreeFileSignature(options.path, options.cwd)}` : "";
|
|
1014
|
+
if (options.isUntracked) {
|
|
1015
|
+
return `u\x00${options.path}${signature}\x00${options.extras.join("\x00")}`;
|
|
1016
|
+
}
|
|
1017
|
+
return `t\x00${options.path}\x00${options.oldPath || ""}${signature}\x00${[...options.extras, ...options.args].join("\x00")}`;
|
|
1018
|
+
}
|
|
1019
|
+
var CACHE_TTL_MS = 1500, MAX_TIMED_CACHE_ENTRIES = 200;
|
|
1020
|
+
var init_cache = () => {};
|
|
1021
|
+
|
|
876
1022
|
// web-src/server/name-pattern.ts
|
|
877
1023
|
function parseGlobSegment(pattern) {
|
|
878
1024
|
const matchers = [];
|
|
@@ -985,6 +1131,21 @@ import {
|
|
|
985
1131
|
} from "node:http";
|
|
986
1132
|
import { Readable } from "node:stream";
|
|
987
1133
|
function runSync(args, cwd, options = {}) {
|
|
1134
|
+
const proc = runBytesSync(args, cwd, options);
|
|
1135
|
+
return {
|
|
1136
|
+
code: proc.code,
|
|
1137
|
+
stdout: new TextDecoder().decode(proc.stdout),
|
|
1138
|
+
stderr: proc.stderr
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function runAsync(args, cwd, options = {}) {
|
|
1142
|
+
return runBytesAsync(args, cwd, options).then((proc) => ({
|
|
1143
|
+
code: proc.code,
|
|
1144
|
+
stdout: new TextDecoder().decode(proc.stdout),
|
|
1145
|
+
stderr: proc.stderr
|
|
1146
|
+
}));
|
|
1147
|
+
}
|
|
1148
|
+
function runBytesSync(args, cwd, options = {}) {
|
|
988
1149
|
const proc = spawnSync(args[0], args.slice(1), {
|
|
989
1150
|
cwd,
|
|
990
1151
|
encoding: "buffer",
|
|
@@ -995,17 +1156,10 @@ function runSync(args, cwd, options = {}) {
|
|
|
995
1156
|
});
|
|
996
1157
|
return {
|
|
997
1158
|
code: proc.status ?? (proc.error ? 1 : 0),
|
|
998
|
-
stdout: new
|
|
1159
|
+
stdout: new Uint8Array(proc.stdout || new Uint8Array),
|
|
999
1160
|
stderr: appendProcessError(new TextDecoder().decode(proc.stderr || new Uint8Array), proc.error)
|
|
1000
1161
|
};
|
|
1001
1162
|
}
|
|
1002
|
-
function runAsync(args, cwd, options = {}) {
|
|
1003
|
-
return runBytesAsync(args, cwd, options).then((proc) => ({
|
|
1004
|
-
code: proc.code,
|
|
1005
|
-
stdout: new TextDecoder().decode(proc.stdout),
|
|
1006
|
-
stderr: proc.stderr
|
|
1007
|
-
}));
|
|
1008
|
-
}
|
|
1009
1163
|
function runBytesAsync(args, cwd, options = {}) {
|
|
1010
1164
|
const maxBuffer = options.maxBuffer ?? 64 * 1024 * 1024;
|
|
1011
1165
|
return new Promise((resolve) => {
|
|
@@ -3089,6 +3243,33 @@ function takeValue(argv, index, flag) {
|
|
|
3089
3243
|
return { error: `${flag} requires a value` };
|
|
3090
3244
|
return { value, next: index + 1 };
|
|
3091
3245
|
}
|
|
3246
|
+
function takeGlobalCliOption(argv, index, options) {
|
|
3247
|
+
const flag = argv[index];
|
|
3248
|
+
if (flag === "--cwd" || flag === "--server" && options.allowServer) {
|
|
3249
|
+
const taken = takeValue(argv, index, flag);
|
|
3250
|
+
if ("error" in taken)
|
|
3251
|
+
return { kind: "error", error: taken.error };
|
|
3252
|
+
return {
|
|
3253
|
+
kind: flag === "--cwd" ? "cwd" : "server",
|
|
3254
|
+
value: taken.value,
|
|
3255
|
+
next: taken.next
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3258
|
+
if (flag === "--bin" && options.allowedCommands) {
|
|
3259
|
+
const taken = takeValue(argv, index, flag);
|
|
3260
|
+
if ("error" in taken)
|
|
3261
|
+
return { kind: "error", error: taken.error };
|
|
3262
|
+
const parsed = parseExternalCommandOverride(taken.value, "--bin", options.allowedCommands);
|
|
3263
|
+
if (parsed.ok === false)
|
|
3264
|
+
return { kind: "error", error: parsed.error };
|
|
3265
|
+
return {
|
|
3266
|
+
kind: "command-override",
|
|
3267
|
+
override: parsed.override,
|
|
3268
|
+
next: taken.next
|
|
3269
|
+
};
|
|
3270
|
+
}
|
|
3271
|
+
return { kind: "unhandled" };
|
|
3272
|
+
}
|
|
3092
3273
|
function shellSingleQuote(value) {
|
|
3093
3274
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
3094
3275
|
}
|
|
@@ -3108,7 +3289,7 @@ function isUnsafeText(value) {
|
|
|
3108
3289
|
return true;
|
|
3109
3290
|
return false;
|
|
3110
3291
|
}
|
|
3111
|
-
function
|
|
3292
|
+
function validateSafeCliValue(value, flag) {
|
|
3112
3293
|
if (!value)
|
|
3113
3294
|
return `${flag} requires a non-empty value`;
|
|
3114
3295
|
if (isUnsafeText(value))
|
|
@@ -3117,13 +3298,16 @@ function validateRefValue(value, flag) {
|
|
|
3117
3298
|
return `${flag} must not start with '-'`;
|
|
3118
3299
|
return;
|
|
3119
3300
|
}
|
|
3301
|
+
function validateRefValue(value, flag) {
|
|
3302
|
+
const error = validateSafeCliValue(value, flag);
|
|
3303
|
+
if (error)
|
|
3304
|
+
return error;
|
|
3305
|
+
return;
|
|
3306
|
+
}
|
|
3120
3307
|
function validateRepoRelativePathValue(value, flag) {
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
return `${flag} must be single-line and must not contain NUL`;
|
|
3125
|
-
if (value.startsWith("-"))
|
|
3126
|
-
return `${flag} must not start with '-'`;
|
|
3308
|
+
const error = validateSafeCliValue(value, flag);
|
|
3309
|
+
if (error)
|
|
3310
|
+
return error;
|
|
3127
3311
|
if (value.startsWith("/") || value.startsWith("\\"))
|
|
3128
3312
|
return `${flag} must be repo-relative`;
|
|
3129
3313
|
const parts = value.split(/[\\/]+/);
|
|
@@ -3237,6 +3421,7 @@ function extractErrorDetail(rawBody, isJson, status) {
|
|
|
3237
3421
|
return trimmed;
|
|
3238
3422
|
}
|
|
3239
3423
|
var init_cli_helpers = __esm(() => {
|
|
3424
|
+
init_command_resolver();
|
|
3240
3425
|
init_git();
|
|
3241
3426
|
init_server_registry();
|
|
3242
3427
|
});
|
|
@@ -3256,6 +3441,28 @@ function parsePosition(value) {
|
|
|
3256
3441
|
const n = Number(value);
|
|
3257
3442
|
return Number.isInteger(n) && n > 0 ? n : Number.NaN;
|
|
3258
3443
|
}
|
|
3444
|
+
function parseAnnotationAddOptions(options) {
|
|
3445
|
+
const body = options.get("--body");
|
|
3446
|
+
const bodyFile = options.get("--body-file");
|
|
3447
|
+
if (body !== undefined && bodyFile !== undefined)
|
|
3448
|
+
return { ok: false, error: "use either --body or --body-file" };
|
|
3449
|
+
const position = parsePosition(options.get("--position"));
|
|
3450
|
+
if (Number.isNaN(position))
|
|
3451
|
+
return { ok: false, error: "--position must be a positive integer" };
|
|
3452
|
+
return {
|
|
3453
|
+
ok: true,
|
|
3454
|
+
options: {
|
|
3455
|
+
title: options.get("--title"),
|
|
3456
|
+
session: options.get("--session"),
|
|
3457
|
+
sessionTitle: options.get("--session-title"),
|
|
3458
|
+
body,
|
|
3459
|
+
bodyFile,
|
|
3460
|
+
before: options.get("--before"),
|
|
3461
|
+
after: options.get("--after"),
|
|
3462
|
+
position
|
|
3463
|
+
}
|
|
3464
|
+
};
|
|
3465
|
+
}
|
|
3259
3466
|
function parseFilter(value) {
|
|
3260
3467
|
const idx = value.indexOf("=");
|
|
3261
3468
|
if (idx <= 0)
|
|
@@ -3310,15 +3517,15 @@ function parseAnnotateArgs(argv) {
|
|
|
3310
3517
|
const arg = argv[i];
|
|
3311
3518
|
if (arg === "--help" || arg === "-h")
|
|
3312
3519
|
return { ok: true, args: { command: { kind: "help" } } };
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
i =
|
|
3520
|
+
const global = takeGlobalCliOption(argv, i, { allowServer: true });
|
|
3521
|
+
if (global.kind === "error")
|
|
3522
|
+
return { ok: false, error: global.error };
|
|
3523
|
+
if (global.kind === "cwd") {
|
|
3524
|
+
cwd = global.value;
|
|
3525
|
+
i = global.next;
|
|
3526
|
+
} else if (global.kind === "server") {
|
|
3527
|
+
server = global.value;
|
|
3528
|
+
i = global.next;
|
|
3322
3529
|
} else if (valueFlags.has(arg)) {
|
|
3323
3530
|
const taken = takeValue(argv, i, arg);
|
|
3324
3531
|
if ("error" in taken)
|
|
@@ -3363,13 +3570,9 @@ function parseAnnotateArgs(argv) {
|
|
|
3363
3570
|
if (!line)
|
|
3364
3571
|
return { ok: false, error: "--line must be <n> or <n>-<m>" };
|
|
3365
3572
|
}
|
|
3366
|
-
const
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
return { ok: false, error: "use either --body or --body-file" };
|
|
3370
|
-
const position = parsePosition(options.get("--position"));
|
|
3371
|
-
if (Number.isNaN(position))
|
|
3372
|
-
return { ok: false, error: "--position must be a positive integer" };
|
|
3573
|
+
const commonOptions = parseAnnotationAddOptions(options);
|
|
3574
|
+
if (commonOptions.ok === false)
|
|
3575
|
+
return { ok: false, error: commonOptions.error };
|
|
3373
3576
|
return {
|
|
3374
3577
|
ok: true,
|
|
3375
3578
|
args: {
|
|
@@ -3379,14 +3582,7 @@ function parseAnnotateArgs(argv) {
|
|
|
3379
3582
|
line,
|
|
3380
3583
|
from: options.get("--from"),
|
|
3381
3584
|
to: options.get("--to"),
|
|
3382
|
-
|
|
3383
|
-
session: options.get("--session"),
|
|
3384
|
-
sessionTitle: options.get("--session-title"),
|
|
3385
|
-
body,
|
|
3386
|
-
bodyFile,
|
|
3387
|
-
before: options.get("--before"),
|
|
3388
|
-
after: options.get("--after"),
|
|
3389
|
-
position
|
|
3585
|
+
...commonOptions.options
|
|
3390
3586
|
},
|
|
3391
3587
|
cwd,
|
|
3392
3588
|
server
|
|
@@ -3396,13 +3592,9 @@ function parseAnnotateArgs(argv) {
|
|
|
3396
3592
|
if (subcommand === "add-db") {
|
|
3397
3593
|
if (!options.get("--db"))
|
|
3398
3594
|
return { ok: false, error: "add-db requires --db <id>" };
|
|
3399
|
-
const
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
return { ok: false, error: "use either --body or --body-file" };
|
|
3403
|
-
const position = parsePosition(options.get("--position"));
|
|
3404
|
-
if (Number.isNaN(position))
|
|
3405
|
-
return { ok: false, error: "--position must be a positive integer" };
|
|
3595
|
+
const commonOptions = parseAnnotationAddOptions(options);
|
|
3596
|
+
if (commonOptions.ok === false)
|
|
3597
|
+
return { ok: false, error: commonOptions.error };
|
|
3406
3598
|
const rawTab = options.get("--tab");
|
|
3407
3599
|
const tab = normalizeDatabaseTab(rawTab);
|
|
3408
3600
|
if (rawTab !== undefined && tab === undefined)
|
|
@@ -3477,14 +3669,7 @@ function parseAnnotateArgs(argv) {
|
|
|
3477
3669
|
searchTerm: options.get("--search-term"),
|
|
3478
3670
|
includeNonText: flags.has("--include-non-text") || undefined,
|
|
3479
3671
|
searchAutoRun: flags.has("--run-search"),
|
|
3480
|
-
|
|
3481
|
-
session: options.get("--session"),
|
|
3482
|
-
sessionTitle: options.get("--session-title"),
|
|
3483
|
-
body,
|
|
3484
|
-
bodyFile,
|
|
3485
|
-
before: options.get("--before"),
|
|
3486
|
-
after: options.get("--after"),
|
|
3487
|
-
position
|
|
3672
|
+
...commonOptions.options
|
|
3488
3673
|
},
|
|
3489
3674
|
cwd,
|
|
3490
3675
|
server
|
|
@@ -3597,6 +3782,14 @@ function printList(state) {
|
|
|
3597
3782
|
});
|
|
3598
3783
|
}
|
|
3599
3784
|
}
|
|
3785
|
+
function printAddedAnnotation(result, location, serverUrl) {
|
|
3786
|
+
const sessionTitle = result.session_title || "Untitled session";
|
|
3787
|
+
if (result.created_session) {
|
|
3788
|
+
console.error(`created new annotation session ${result.session_id} (${sessionTitle})`);
|
|
3789
|
+
}
|
|
3790
|
+
console.log(`annotated ${location} ` + `[${result.entry.id}] in session ${result.session_id} (${sessionTitle})`);
|
|
3791
|
+
console.error(`view annotations at ${serverUrl}/ with the code annotations panel`);
|
|
3792
|
+
}
|
|
3600
3793
|
async function annotationBodyFromCommand(command) {
|
|
3601
3794
|
let body = command.body;
|
|
3602
3795
|
if (body === undefined && command.bodyFile !== undefined) {
|
|
@@ -3657,11 +3850,7 @@ async function runAnnotateCli(argv) {
|
|
|
3657
3850
|
after_id: command.after,
|
|
3658
3851
|
position: command.position
|
|
3659
3852
|
});
|
|
3660
|
-
|
|
3661
|
-
console.error(`created new annotation session ${result.session_id} (${result.session_title || "Untitled session"})`);
|
|
3662
|
-
}
|
|
3663
|
-
console.log(`annotated ${result.entry.path}${formatLine(result.entry.line)} ` + `[${result.entry.id}] in session ${result.session_id} (${result.session_title || "Untitled session"})`);
|
|
3664
|
-
console.error(`view annotations at ${serverUrl}/ with the code annotations panel`);
|
|
3853
|
+
printAddedAnnotation(result, `${result.entry.path}${formatLine(result.entry.line)}`, serverUrl);
|
|
3665
3854
|
return;
|
|
3666
3855
|
}
|
|
3667
3856
|
if (command.kind === "add-db") {
|
|
@@ -3711,11 +3900,7 @@ async function runAnnotateCli(argv) {
|
|
|
3711
3900
|
after_id: command.after,
|
|
3712
3901
|
position: command.position
|
|
3713
3902
|
});
|
|
3714
|
-
|
|
3715
|
-
console.error(`created new annotation session ${result.session_id} (${result.session_title || "Untitled session"})`);
|
|
3716
|
-
}
|
|
3717
|
-
console.log(`annotated ${result.entry.path} ` + `[${result.entry.id}] in session ${result.session_id} (${result.session_title || "Untitled session"})`);
|
|
3718
|
-
console.error(`view annotations at ${serverUrl}/ with the code annotations panel`);
|
|
3903
|
+
printAddedAnnotation(result, result.entry.path, serverUrl);
|
|
3719
3904
|
return;
|
|
3720
3905
|
}
|
|
3721
3906
|
if (command.kind === "list") {
|
|
@@ -4276,23 +4461,17 @@ function parseFileArgs(argv) {
|
|
|
4276
4461
|
if (arg === "--help" || arg === "-h") {
|
|
4277
4462
|
return { ok: true, args: { command: { kind: "help" } } };
|
|
4278
4463
|
}
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
"git"
|
|
4291
|
-
]);
|
|
4292
|
-
if (parsed.ok === false)
|
|
4293
|
-
return { ok: false, error: parsed.error };
|
|
4294
|
-
commandOverrides.push(parsed.override);
|
|
4295
|
-
i = taken.next;
|
|
4464
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
4465
|
+
allowedCommands: ["git"]
|
|
4466
|
+
});
|
|
4467
|
+
if (global.kind === "error")
|
|
4468
|
+
return { ok: false, error: global.error };
|
|
4469
|
+
if (global.kind === "cwd") {
|
|
4470
|
+
cwd = global.value;
|
|
4471
|
+
i = global.next;
|
|
4472
|
+
} else if (global.kind === "command-override") {
|
|
4473
|
+
commandOverrides.push(global.override);
|
|
4474
|
+
i = global.next;
|
|
4296
4475
|
} else if (VALUE_FLAGS.has(arg)) {
|
|
4297
4476
|
const taken = takeValue(argv, i, arg);
|
|
4298
4477
|
if ("error" in taken)
|
|
@@ -5525,35 +5704,30 @@ function parseJournalArgs(argv) {
|
|
|
5525
5704
|
"--wip-limit",
|
|
5526
5705
|
"--limit",
|
|
5527
5706
|
"--repo",
|
|
5528
|
-
"--gh-label",
|
|
5529
|
-
"--search",
|
|
5530
|
-
"--state"
|
|
5531
|
-
]);
|
|
5532
|
-
try {
|
|
5533
|
-
for (let i = 0;i < argv.length; i++) {
|
|
5534
|
-
const arg = argv[i];
|
|
5535
|
-
if (arg === "--help" || arg === "-h")
|
|
5536
|
-
return { ok: true, args: { command: { kind: "help" }, dryRun: false } };
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
i =
|
|
5546
|
-
} else if (
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
]);
|
|
5553
|
-
if (parsed.ok === false)
|
|
5554
|
-
return { ok: false, error: parsed.error };
|
|
5555
|
-
commandOverrides.push(parsed.override);
|
|
5556
|
-
i = taken.next;
|
|
5707
|
+
"--gh-label",
|
|
5708
|
+
"--search",
|
|
5709
|
+
"--state"
|
|
5710
|
+
]);
|
|
5711
|
+
try {
|
|
5712
|
+
for (let i = 0;i < argv.length; i++) {
|
|
5713
|
+
const arg = argv[i];
|
|
5714
|
+
if (arg === "--help" || arg === "-h")
|
|
5715
|
+
return { ok: true, args: { command: { kind: "help" }, dryRun: false } };
|
|
5716
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
5717
|
+
allowServer: true,
|
|
5718
|
+
allowedCommands: ["gh"]
|
|
5719
|
+
});
|
|
5720
|
+
if (global.kind === "error")
|
|
5721
|
+
return { ok: false, error: global.error };
|
|
5722
|
+
if (global.kind === "cwd") {
|
|
5723
|
+
cwd = global.value;
|
|
5724
|
+
i = global.next;
|
|
5725
|
+
} else if (global.kind === "server") {
|
|
5726
|
+
server = global.value;
|
|
5727
|
+
i = global.next;
|
|
5728
|
+
} else if (global.kind === "command-override") {
|
|
5729
|
+
commandOverrides.push(global.override);
|
|
5730
|
+
i = global.next;
|
|
5557
5731
|
} else if (valueFlags.has(arg)) {
|
|
5558
5732
|
const taken = takeValue(argv, i, arg);
|
|
5559
5733
|
if ("error" in taken)
|
|
@@ -6338,107 +6512,6 @@ var init_journal_cli = __esm(() => {
|
|
|
6338
6512
|
init_github_issues();
|
|
6339
6513
|
});
|
|
6340
6514
|
|
|
6341
|
-
// web-src/core/routes.ts
|
|
6342
|
-
function assertNever(value) {
|
|
6343
|
-
throw new Error(`unhandled route: ${JSON.stringify(value)}`);
|
|
6344
|
-
}
|
|
6345
|
-
function formatLineTarget(line) {
|
|
6346
|
-
return typeof line === "number" ? String(line) : `${line.start}-${line.end}`;
|
|
6347
|
-
}
|
|
6348
|
-
function buildRoute(route) {
|
|
6349
|
-
switch (route.screen) {
|
|
6350
|
-
case "repo": {
|
|
6351
|
-
const params = new URLSearchParams;
|
|
6352
|
-
if (route.ref && route.ref !== "worktree")
|
|
6353
|
-
params.set("ref", route.ref);
|
|
6354
|
-
if (route.path)
|
|
6355
|
-
params.set("path", route.path);
|
|
6356
|
-
const qs = params.toString();
|
|
6357
|
-
return `/${qs ? `?${qs}` : ""}`;
|
|
6358
|
-
}
|
|
6359
|
-
case "file":
|
|
6360
|
-
if (route.view === "blob") {
|
|
6361
|
-
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + "&view=blob" + (route.preview ? "&preview=1" : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "") + (route.virtual === "off" ? "&virtual=off" : "");
|
|
6362
|
-
}
|
|
6363
|
-
if (route.view === "blame") {
|
|
6364
|
-
const ref = route.ref || "worktree";
|
|
6365
|
-
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(ref) + "&view=blame" + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
6366
|
-
}
|
|
6367
|
-
if (route.view === "history") {
|
|
6368
|
-
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + "&view=history" + (route.commit ? `&commit=${encodeURIComponent(route.commit)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
6369
|
-
}
|
|
6370
|
-
return "/file?path=" + encodeURIComponent(route.path) + "&ref=" + encodeURIComponent(route.ref || "worktree") + "&from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "") + (route.virtual === "off" ? "&virtual=off" : "");
|
|
6371
|
-
case "diff":
|
|
6372
|
-
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ? `&path=${encodeURIComponent(route.path)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
6373
|
-
case "help": {
|
|
6374
|
-
const params = new URLSearchParams;
|
|
6375
|
-
if (route.lang && route.lang !== "en")
|
|
6376
|
-
params.set("lang", route.lang);
|
|
6377
|
-
if (route.section && route.section !== "overview")
|
|
6378
|
-
params.set("section", route.section);
|
|
6379
|
-
const qs = params.toString();
|
|
6380
|
-
return `/help${qs ? `?${qs}` : ""}`;
|
|
6381
|
-
}
|
|
6382
|
-
case "history": {
|
|
6383
|
-
const params = new URLSearchParams;
|
|
6384
|
-
if (route.ref && route.ref !== "HEAD")
|
|
6385
|
-
params.set("ref", route.ref);
|
|
6386
|
-
if (route.commit)
|
|
6387
|
-
params.set("commit", route.commit);
|
|
6388
|
-
const qs = params.toString();
|
|
6389
|
-
return `/history${qs ? `?${qs}` : ""}`;
|
|
6390
|
-
}
|
|
6391
|
-
case "journal": {
|
|
6392
|
-
const params = new URLSearchParams;
|
|
6393
|
-
if (route.tab && route.tab !== "journal")
|
|
6394
|
-
params.set("tab", route.tab);
|
|
6395
|
-
if (route.date)
|
|
6396
|
-
params.set("date", route.date);
|
|
6397
|
-
if (route.label)
|
|
6398
|
-
params.set("label", route.label);
|
|
6399
|
-
if (route.task)
|
|
6400
|
-
params.set("task", route.task);
|
|
6401
|
-
const qs = params.toString();
|
|
6402
|
-
return `/journal${qs ? `?${qs}` : ""}`;
|
|
6403
|
-
}
|
|
6404
|
-
case "database": {
|
|
6405
|
-
const params = new URLSearchParams;
|
|
6406
|
-
if (route.db)
|
|
6407
|
-
params.set("db", route.db);
|
|
6408
|
-
if (route.schema)
|
|
6409
|
-
params.set("schema", route.schema);
|
|
6410
|
-
if (route.table)
|
|
6411
|
-
params.set("table", route.table);
|
|
6412
|
-
if (route.tab)
|
|
6413
|
-
params.set("tab", route.tab);
|
|
6414
|
-
if (route.diffBefore)
|
|
6415
|
-
params.set("diffBefore", route.diffBefore);
|
|
6416
|
-
if (route.diffAfter)
|
|
6417
|
-
params.set("diffAfter", route.diffAfter);
|
|
6418
|
-
const qs = params.toString();
|
|
6419
|
-
return `/database${qs ? `?${qs}` : ""}`;
|
|
6420
|
-
}
|
|
6421
|
-
case "unknown":
|
|
6422
|
-
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree");
|
|
6423
|
-
default:
|
|
6424
|
-
return assertNever(route);
|
|
6425
|
-
}
|
|
6426
|
-
}
|
|
6427
|
-
var SPA_PATHS, APP_ENTRY_PATHS;
|
|
6428
|
-
var init_routes = __esm(() => {
|
|
6429
|
-
SPA_PATHS = [
|
|
6430
|
-
"/todif",
|
|
6431
|
-
"/todiff",
|
|
6432
|
-
"/file",
|
|
6433
|
-
"/help",
|
|
6434
|
-
"/history",
|
|
6435
|
-
"/journal",
|
|
6436
|
-
"/database",
|
|
6437
|
-
"/doctor"
|
|
6438
|
-
];
|
|
6439
|
-
APP_ENTRY_PATHS = ["/", "/index.html"];
|
|
6440
|
-
});
|
|
6441
|
-
|
|
6442
6515
|
// web-src/server/query-cli.ts
|
|
6443
6516
|
var exports_query_cli = {};
|
|
6444
6517
|
__export(exports_query_cli, {
|
|
@@ -6481,26 +6554,21 @@ function parseQueryArgs(argv) {
|
|
|
6481
6554
|
const arg = argv[i];
|
|
6482
6555
|
if (arg === "--help" || arg === "-h")
|
|
6483
6556
|
return { ok: true, args: { command: { kind: "help" } } };
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
i =
|
|
6493
|
-
} else if (
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
]);
|
|
6500
|
-
if (parsed.ok === false)
|
|
6501
|
-
return { ok: false, error: parsed.error };
|
|
6502
|
-
commandOverrides.push(parsed.override);
|
|
6503
|
-
i = taken.next;
|
|
6557
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
6558
|
+
allowServer: true,
|
|
6559
|
+
allowedCommands: ["git"]
|
|
6560
|
+
});
|
|
6561
|
+
if (global.kind === "error")
|
|
6562
|
+
return { ok: false, error: global.error };
|
|
6563
|
+
if (global.kind === "cwd") {
|
|
6564
|
+
cwd = global.value;
|
|
6565
|
+
i = global.next;
|
|
6566
|
+
} else if (global.kind === "server") {
|
|
6567
|
+
server = global.value;
|
|
6568
|
+
i = global.next;
|
|
6569
|
+
} else if (global.kind === "command-override") {
|
|
6570
|
+
commandOverrides.push(global.override);
|
|
6571
|
+
i = global.next;
|
|
6504
6572
|
} else if (VALUE_FLAGS2.has(arg)) {
|
|
6505
6573
|
const taken = takeValue(argv, i, arg);
|
|
6506
6574
|
if ("error" in taken)
|
|
@@ -9139,6 +9207,18 @@ __export(exports_search_cli, {
|
|
|
9139
9207
|
SEARCH_AGENT_HELP: () => SEARCH_AGENT_HELP,
|
|
9140
9208
|
FILE_NAME_SEARCH_DEFAULT_MAX: () => FILE_NAME_SEARCH_DEFAULT_MAX
|
|
9141
9209
|
});
|
|
9210
|
+
function parseSearchMax(raw, hardCap) {
|
|
9211
|
+
if (raw === undefined)
|
|
9212
|
+
return { value: undefined };
|
|
9213
|
+
const value = Number(raw);
|
|
9214
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
9215
|
+
return { error: `--max must be a positive integer (got ${raw})` };
|
|
9216
|
+
}
|
|
9217
|
+
if (value > hardCap) {
|
|
9218
|
+
return { error: `--max must be <= ${hardCap} (got ${value})` };
|
|
9219
|
+
}
|
|
9220
|
+
return { value };
|
|
9221
|
+
}
|
|
9142
9222
|
function parseSearchArgs(argv) {
|
|
9143
9223
|
const rest = [];
|
|
9144
9224
|
let cwd;
|
|
@@ -9152,26 +9232,21 @@ function parseSearchArgs(argv) {
|
|
|
9152
9232
|
if (arg === "--help" || arg === "-h") {
|
|
9153
9233
|
return { ok: true, args: { command: { kind: "help" } } };
|
|
9154
9234
|
}
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
i =
|
|
9164
|
-
} else if (
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
]);
|
|
9171
|
-
if (parsed.ok === false)
|
|
9172
|
-
return { ok: false, error: parsed.error };
|
|
9173
|
-
commandOverrides.push(parsed.override);
|
|
9174
|
-
i = taken.next;
|
|
9235
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
9236
|
+
allowServer: true,
|
|
9237
|
+
allowedCommands: ["git"]
|
|
9238
|
+
});
|
|
9239
|
+
if (global.kind === "error")
|
|
9240
|
+
return { ok: false, error: global.error };
|
|
9241
|
+
if (global.kind === "cwd") {
|
|
9242
|
+
cwd = global.value;
|
|
9243
|
+
i = global.next;
|
|
9244
|
+
} else if (global.kind === "server") {
|
|
9245
|
+
server = global.value;
|
|
9246
|
+
i = global.next;
|
|
9247
|
+
} else if (global.kind === "command-override") {
|
|
9248
|
+
commandOverrides.push(global.override);
|
|
9249
|
+
i = global.next;
|
|
9175
9250
|
} else if (REPEATABLE_VALUE_FLAGS.has(arg)) {
|
|
9176
9251
|
const taken = takeValue(argv, i, arg);
|
|
9177
9252
|
if ("error" in taken)
|
|
@@ -9230,24 +9305,10 @@ function parseSearchArgs(argv) {
|
|
|
9230
9305
|
error: "search files does not accept --path"
|
|
9231
9306
|
};
|
|
9232
9307
|
}
|
|
9233
|
-
const
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
if (!Number.isInteger(n) || n <= 0) {
|
|
9238
|
-
return {
|
|
9239
|
-
ok: false,
|
|
9240
|
-
error: `--max must be a positive integer (got ${maxRaw2})`
|
|
9241
|
-
};
|
|
9242
|
-
}
|
|
9243
|
-
if (n > FILE_SEARCH_ABSOLUTE_MAX) {
|
|
9244
|
-
return {
|
|
9245
|
-
ok: false,
|
|
9246
|
-
error: `--max must be <= ${FILE_SEARCH_ABSOLUTE_MAX} (got ${n})`
|
|
9247
|
-
};
|
|
9248
|
-
}
|
|
9249
|
-
max2 = n;
|
|
9250
|
-
}
|
|
9308
|
+
const parsedMax2 = parseSearchMax(options.get("--max"), FILE_SEARCH_ABSOLUTE_MAX);
|
|
9309
|
+
if ("error" in parsedMax2)
|
|
9310
|
+
return { ok: false, error: parsedMax2.error };
|
|
9311
|
+
const max = parsedMax2.value ?? FILE_NAME_SEARCH_DEFAULT_MAX;
|
|
9251
9312
|
return {
|
|
9252
9313
|
ok: true,
|
|
9253
9314
|
args: {
|
|
@@ -9255,7 +9316,7 @@ function parseSearchArgs(argv) {
|
|
|
9255
9316
|
kind: "files",
|
|
9256
9317
|
term,
|
|
9257
9318
|
ref: options.get("--ref"),
|
|
9258
|
-
max
|
|
9319
|
+
max,
|
|
9259
9320
|
json: flags.has("--json")
|
|
9260
9321
|
},
|
|
9261
9322
|
cwd,
|
|
@@ -9264,24 +9325,9 @@ function parseSearchArgs(argv) {
|
|
|
9264
9325
|
}
|
|
9265
9326
|
};
|
|
9266
9327
|
}
|
|
9267
|
-
const
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
const n = Number(maxRaw);
|
|
9271
|
-
if (!Number.isInteger(n) || n <= 0) {
|
|
9272
|
-
return {
|
|
9273
|
-
ok: false,
|
|
9274
|
-
error: `--max must be a positive integer (got ${maxRaw})`
|
|
9275
|
-
};
|
|
9276
|
-
}
|
|
9277
|
-
if (n > GREP_ABSOLUTE_MAX) {
|
|
9278
|
-
return {
|
|
9279
|
-
ok: false,
|
|
9280
|
-
error: `--max must be <= ${GREP_ABSOLUTE_MAX} (got ${n})`
|
|
9281
|
-
};
|
|
9282
|
-
}
|
|
9283
|
-
max = n;
|
|
9284
|
-
}
|
|
9328
|
+
const parsedMax = parseSearchMax(options.get("--max"), GREP_ABSOLUTE_MAX);
|
|
9329
|
+
if ("error" in parsedMax)
|
|
9330
|
+
return { ok: false, error: parsedMax.error };
|
|
9285
9331
|
return {
|
|
9286
9332
|
ok: true,
|
|
9287
9333
|
args: {
|
|
@@ -9291,7 +9337,7 @@ function parseSearchArgs(argv) {
|
|
|
9291
9337
|
ref: options.get("--ref"),
|
|
9292
9338
|
paths,
|
|
9293
9339
|
regex: flags.has("--regex"),
|
|
9294
|
-
max,
|
|
9340
|
+
max: parsedMax.value,
|
|
9295
9341
|
json: flags.has("--json")
|
|
9296
9342
|
},
|
|
9297
9343
|
cwd,
|
|
@@ -9843,23 +9889,17 @@ function parseStatusArgs(argv) {
|
|
|
9843
9889
|
if (arg === "--help" || arg === "-h") {
|
|
9844
9890
|
return { ok: true, args: { command: { kind: "help" } } };
|
|
9845
9891
|
}
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
"git"
|
|
9858
|
-
]);
|
|
9859
|
-
if (parsed.ok === false)
|
|
9860
|
-
return { ok: false, error: parsed.error };
|
|
9861
|
-
commandOverrides.push(parsed.override);
|
|
9862
|
-
i = taken.next;
|
|
9892
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
9893
|
+
allowedCommands: ["git"]
|
|
9894
|
+
});
|
|
9895
|
+
if (global.kind === "error")
|
|
9896
|
+
return { ok: false, error: global.error };
|
|
9897
|
+
if (global.kind === "cwd") {
|
|
9898
|
+
cwd = global.value;
|
|
9899
|
+
i = global.next;
|
|
9900
|
+
} else if (global.kind === "command-override") {
|
|
9901
|
+
commandOverrides.push(global.override);
|
|
9902
|
+
i = global.next;
|
|
9863
9903
|
} else if (VALUE_FLAGS4.has(arg)) {
|
|
9864
9904
|
const taken = takeValue(argv, i, arg);
|
|
9865
9905
|
if ("error" in taken)
|
|
@@ -10421,6 +10461,9 @@ function placeValue(coerced, kind, useParams, params) {
|
|
|
10421
10461
|
function coerceCell(cell, columnType) {
|
|
10422
10462
|
return coerceDbValue(cell.value, columnType);
|
|
10423
10463
|
}
|
|
10464
|
+
function formatWriteComparisons(cells, columnTypes, kind, useParams, params, separator) {
|
|
10465
|
+
return cells.map((cell) => `${sanitizeIdentifier(cell.column, kind)} = ${placeValue(coerceCell(cell, columnTypes.get(cell.column) ?? "TEXT"), kind, useParams, params)}`).join(separator);
|
|
10466
|
+
}
|
|
10424
10467
|
function buildInsertSql(table, cells, columnTypes, kind) {
|
|
10425
10468
|
if (cells.length === 0) {
|
|
10426
10469
|
throw new Error("insert requires at least one column value");
|
|
@@ -10441,8 +10484,8 @@ function buildUpdateSql(table, set, pk, columnTypes, kind) {
|
|
|
10441
10484
|
}
|
|
10442
10485
|
const useParams = useParamsFor(kind);
|
|
10443
10486
|
const params = [];
|
|
10444
|
-
const setSql = set
|
|
10445
|
-
const whereSql = pk
|
|
10487
|
+
const setSql = formatWriteComparisons(set, columnTypes, kind, useParams, params, ", ");
|
|
10488
|
+
const whereSql = formatWriteComparisons(pk, columnTypes, kind, useParams, params, " AND ");
|
|
10446
10489
|
const sql = `UPDATE ${sanitizeIdentifier(table, kind)} SET ${setSql} WHERE ${whereSql}`;
|
|
10447
10490
|
return { sql, params };
|
|
10448
10491
|
}
|
|
@@ -10452,7 +10495,7 @@ function buildDeleteSql(table, pk, columnTypes, kind) {
|
|
|
10452
10495
|
}
|
|
10453
10496
|
const useParams = useParamsFor(kind);
|
|
10454
10497
|
const params = [];
|
|
10455
|
-
const whereSql = pk
|
|
10498
|
+
const whereSql = formatWriteComparisons(pk, columnTypes, kind, useParams, params, " AND ");
|
|
10456
10499
|
const sql = `DELETE FROM ${sanitizeIdentifier(table, kind)} WHERE ${whereSql}`;
|
|
10457
10500
|
return { sql, params };
|
|
10458
10501
|
}
|
|
@@ -15563,23 +15606,6 @@ var init_discovery = __esm(() => {
|
|
|
15563
15606
|
supabaseDiscoveryCache = new Map;
|
|
15564
15607
|
});
|
|
15565
15608
|
|
|
15566
|
-
// web-src/core/id.ts
|
|
15567
|
-
function bytesToHex(bytes) {
|
|
15568
|
-
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
15569
|
-
}
|
|
15570
|
-
function makeId(prefix) {
|
|
15571
|
-
const cryptoApi = globalThis.crypto;
|
|
15572
|
-
if (typeof cryptoApi?.randomUUID === "function") {
|
|
15573
|
-
return `${prefix}-${cryptoApi.randomUUID().replace(/-/g, "").slice(0, 16)}`;
|
|
15574
|
-
}
|
|
15575
|
-
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
15576
|
-
const bytes = new Uint8Array(8);
|
|
15577
|
-
cryptoApi.getRandomValues(bytes);
|
|
15578
|
-
return `${prefix}-${bytesToHex(bytes)}`;
|
|
15579
|
-
}
|
|
15580
|
-
return `${prefix}-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
15581
|
-
}
|
|
15582
|
-
|
|
15583
15609
|
// web-src/server/worktree-watcher.ts
|
|
15584
15610
|
import {
|
|
15585
15611
|
lstatSync as lstatSync3,
|
|
@@ -15850,15 +15876,17 @@ function optionalString(value, maxLen) {
|
|
|
15850
15876
|
function optionalBoolean(value) {
|
|
15851
15877
|
return typeof value === "boolean" ? value : undefined;
|
|
15852
15878
|
}
|
|
15853
|
-
function
|
|
15879
|
+
function optionalFiniteNumber(value, min, max, round) {
|
|
15854
15880
|
if (typeof value !== "number" || !Number.isFinite(value))
|
|
15855
15881
|
return;
|
|
15856
|
-
|
|
15882
|
+
const normalized = round ? Math.round(value) : value;
|
|
15883
|
+
return Math.max(min, Math.min(max, normalized));
|
|
15884
|
+
}
|
|
15885
|
+
function optionalNumber(value, min, max) {
|
|
15886
|
+
return optionalFiniteNumber(value, min, max, true);
|
|
15857
15887
|
}
|
|
15858
15888
|
function optionalFloat(value, min, max) {
|
|
15859
|
-
|
|
15860
|
-
return;
|
|
15861
|
-
return Math.max(min, Math.min(max, value));
|
|
15889
|
+
return optionalFiniteNumber(value, min, max, false);
|
|
15862
15890
|
}
|
|
15863
15891
|
function optionalFontSize(value) {
|
|
15864
15892
|
return value === "compact" || value === "regular" || value === "large" || value === "xlarge" ? value : undefined;
|
|
@@ -16690,6 +16718,25 @@ function asStringArray(value) {
|
|
|
16690
16718
|
function asNumber(value) {
|
|
16691
16719
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
16692
16720
|
}
|
|
16721
|
+
function asDynamoDbItemsResult(raw) {
|
|
16722
|
+
return {
|
|
16723
|
+
items: Array.isArray(raw.Items) ? raw.Items : [],
|
|
16724
|
+
count: asNumber(raw.Count),
|
|
16725
|
+
scannedCount: asNumber(raw.ScannedCount),
|
|
16726
|
+
...raw.LastEvaluatedKey ? { lastEvaluatedKey: asObject(raw.LastEvaluatedKey) } : {}
|
|
16727
|
+
};
|
|
16728
|
+
}
|
|
16729
|
+
function dynamoDbItemsRequestFields(opts) {
|
|
16730
|
+
return {
|
|
16731
|
+
...opts.limit ? { Limit: Math.min(1000, Math.max(1, opts.limit)) } : {},
|
|
16732
|
+
...opts.exclusiveStartKey ? { ExclusiveStartKey: opts.exclusiveStartKey } : {},
|
|
16733
|
+
...opts.indexName ? { IndexName: opts.indexName } : {},
|
|
16734
|
+
...opts.projectionExpression ? { ProjectionExpression: opts.projectionExpression } : {},
|
|
16735
|
+
...opts.filterExpression ? { FilterExpression: opts.filterExpression } : {},
|
|
16736
|
+
...opts.expressionAttributeNames ? { ExpressionAttributeNames: opts.expressionAttributeNames } : {},
|
|
16737
|
+
...opts.expressionAttributeValues ? { ExpressionAttributeValues: opts.expressionAttributeValues } : {}
|
|
16738
|
+
};
|
|
16739
|
+
}
|
|
16693
16740
|
function createDynamoDbAdapter(config) {
|
|
16694
16741
|
async function signedJsonRequest(action, body, signal, deadline = createDynamoDbTransportDeadline(config)) {
|
|
16695
16742
|
const requestBody = JSON.stringify(body);
|
|
@@ -16772,41 +16819,19 @@ function createDynamoDbAdapter(config) {
|
|
|
16772
16819
|
assertTableName(opts.tableName);
|
|
16773
16820
|
const raw = await signedJsonRequest("Scan", {
|
|
16774
16821
|
TableName: opts.tableName,
|
|
16775
|
-
...
|
|
16776
|
-
...opts.exclusiveStartKey ? { ExclusiveStartKey: opts.exclusiveStartKey } : {},
|
|
16777
|
-
...opts.indexName ? { IndexName: opts.indexName } : {},
|
|
16778
|
-
...opts.projectionExpression ? { ProjectionExpression: opts.projectionExpression } : {},
|
|
16779
|
-
...opts.filterExpression ? { FilterExpression: opts.filterExpression } : {},
|
|
16780
|
-
...opts.expressionAttributeNames ? { ExpressionAttributeNames: opts.expressionAttributeNames } : {},
|
|
16781
|
-
...opts.expressionAttributeValues ? { ExpressionAttributeValues: opts.expressionAttributeValues } : {}
|
|
16822
|
+
...dynamoDbItemsRequestFields(opts)
|
|
16782
16823
|
}, opts.signal);
|
|
16783
|
-
return
|
|
16784
|
-
items: Array.isArray(raw.Items) ? raw.Items : [],
|
|
16785
|
-
count: asNumber(raw.Count),
|
|
16786
|
-
scannedCount: asNumber(raw.ScannedCount),
|
|
16787
|
-
...raw.LastEvaluatedKey ? { lastEvaluatedKey: asObject(raw.LastEvaluatedKey) } : {}
|
|
16788
|
-
};
|
|
16824
|
+
return asDynamoDbItemsResult(raw);
|
|
16789
16825
|
}
|
|
16790
16826
|
async function queryAsync(opts) {
|
|
16791
16827
|
assertTableName(opts.tableName);
|
|
16792
16828
|
const raw = await signedJsonRequest("Query", {
|
|
16793
16829
|
TableName: opts.tableName,
|
|
16794
16830
|
KeyConditionExpression: opts.keyConditionExpression,
|
|
16795
|
-
...
|
|
16796
|
-
...opts.exclusiveStartKey ? { ExclusiveStartKey: opts.exclusiveStartKey } : {},
|
|
16797
|
-
...opts.indexName ? { IndexName: opts.indexName } : {},
|
|
16798
|
-
...opts.projectionExpression ? { ProjectionExpression: opts.projectionExpression } : {},
|
|
16799
|
-
...opts.filterExpression ? { FilterExpression: opts.filterExpression } : {},
|
|
16800
|
-
...opts.expressionAttributeNames ? { ExpressionAttributeNames: opts.expressionAttributeNames } : {},
|
|
16801
|
-
...opts.expressionAttributeValues ? { ExpressionAttributeValues: opts.expressionAttributeValues } : {},
|
|
16831
|
+
...dynamoDbItemsRequestFields(opts),
|
|
16802
16832
|
...opts.scanIndexForward !== undefined ? { ScanIndexForward: opts.scanIndexForward } : {}
|
|
16803
16833
|
}, opts.signal);
|
|
16804
|
-
return
|
|
16805
|
-
items: Array.isArray(raw.Items) ? raw.Items : [],
|
|
16806
|
-
count: asNumber(raw.Count),
|
|
16807
|
-
scannedCount: asNumber(raw.ScannedCount),
|
|
16808
|
-
...raw.LastEvaluatedKey ? { lastEvaluatedKey: asObject(raw.LastEvaluatedKey) } : {}
|
|
16809
|
-
};
|
|
16834
|
+
return asDynamoDbItemsResult(raw);
|
|
16810
16835
|
}
|
|
16811
16836
|
async function getItemAsync(opts) {
|
|
16812
16837
|
assertTableName(opts.tableName);
|
|
@@ -22497,29 +22522,20 @@ function parseDoctorCliArgs(argv) {
|
|
|
22497
22522
|
json2 = true;
|
|
22498
22523
|
continue;
|
|
22499
22524
|
}
|
|
22500
|
-
|
|
22501
|
-
|
|
22502
|
-
|
|
22503
|
-
|
|
22504
|
-
|
|
22525
|
+
const global = takeGlobalCliOption(argv, i, {
|
|
22526
|
+
allowedCommands: ["git", "docker", "gh"]
|
|
22527
|
+
});
|
|
22528
|
+
if (global.kind === "error") {
|
|
22529
|
+
return { kind: "error", message: global.error };
|
|
22530
|
+
}
|
|
22531
|
+
if (global.kind === "cwd") {
|
|
22532
|
+
cwd = global.value;
|
|
22533
|
+
i = global.next;
|
|
22505
22534
|
continue;
|
|
22506
22535
|
}
|
|
22507
|
-
if (
|
|
22508
|
-
|
|
22509
|
-
|
|
22510
|
-
return {
|
|
22511
|
-
kind: "error",
|
|
22512
|
-
message: "--bin requires <name>=<absolute-path>"
|
|
22513
|
-
};
|
|
22514
|
-
}
|
|
22515
|
-
const parsed = parseExternalCommandOverride(next, "--bin", [
|
|
22516
|
-
"git",
|
|
22517
|
-
"docker",
|
|
22518
|
-
"gh"
|
|
22519
|
-
]);
|
|
22520
|
-
if (parsed.ok === false)
|
|
22521
|
-
return { kind: "error", message: parsed.error };
|
|
22522
|
-
commandOverrides.push(parsed.override);
|
|
22536
|
+
if (global.kind === "command-override") {
|
|
22537
|
+
commandOverrides.push(global.override);
|
|
22538
|
+
i = global.next;
|
|
22523
22539
|
continue;
|
|
22524
22540
|
}
|
|
22525
22541
|
if (arg === "--port") {
|
|
@@ -22646,6 +22662,7 @@ Exit codes:
|
|
|
22646
22662
|
`, STATUS_SYMBOL;
|
|
22647
22663
|
var init_doctor_cli = __esm(() => {
|
|
22648
22664
|
init_command_resolver();
|
|
22665
|
+
init_cli_helpers();
|
|
22649
22666
|
init_doctor();
|
|
22650
22667
|
init_git();
|
|
22651
22668
|
STATUS_SYMBOL = {
|
|
@@ -22711,9 +22728,7 @@ function emptyJournalTaskState() {
|
|
|
22711
22728
|
return { version: 1, tasks: [] };
|
|
22712
22729
|
}
|
|
22713
22730
|
function makeJournalId(prefix) {
|
|
22714
|
-
|
|
22715
|
-
const time = Date.now().toString(36);
|
|
22716
|
-
return `${prefix}-${time}${random}`;
|
|
22731
|
+
return makeTimedId(prefix);
|
|
22717
22732
|
}
|
|
22718
22733
|
function optionalString4(value, maxLen) {
|
|
22719
22734
|
if (typeof value !== "string")
|
|
@@ -22867,11 +22882,8 @@ async function updateDailyJournalState(root, updater) {
|
|
|
22867
22882
|
async function updateJournalTaskState(root, updater) {
|
|
22868
22883
|
return journalTaskStore.update(root, updater);
|
|
22869
22884
|
}
|
|
22870
|
-
function insertOptionCount2(input) {
|
|
22871
|
-
return (input.before_id ? 1 : 0) + (input.after_id ? 1 : 0) + (input.position !== undefined ? 1 : 0);
|
|
22872
|
-
}
|
|
22873
22885
|
function taskInsertIndex(tasks, status, input) {
|
|
22874
|
-
if (
|
|
22886
|
+
if (orderedInsertOptionCount(input) > 1)
|
|
22875
22887
|
return { ok: false, error: "use only one of before, after, or position" };
|
|
22876
22888
|
if (input.before_id || input.after_id) {
|
|
22877
22889
|
const anchorId = input.before_id || input.after_id || "";
|
|
@@ -23039,6 +23051,16 @@ function addJournalTask(state, input, now, makeId3 = makeJournalId) {
|
|
|
23039
23051
|
tasks.splice(insertAt.index, 0, task);
|
|
23040
23052
|
return { ok: true, state: { version: 1, tasks }, task };
|
|
23041
23053
|
}
|
|
23054
|
+
function journalTaskResult(state, task) {
|
|
23055
|
+
return {
|
|
23056
|
+
ok: true,
|
|
23057
|
+
state: {
|
|
23058
|
+
version: 1,
|
|
23059
|
+
tasks: state.tasks.map((item) => item.id === task.id ? task : item)
|
|
23060
|
+
},
|
|
23061
|
+
task
|
|
23062
|
+
};
|
|
23063
|
+
}
|
|
23042
23064
|
function updateJournalTask(state, id, patch, now) {
|
|
23043
23065
|
const task = state.tasks.find((item) => item.id === id);
|
|
23044
23066
|
if (!task)
|
|
@@ -23093,14 +23115,7 @@ function updateJournalTask(state, id, patch, now) {
|
|
|
23093
23115
|
else
|
|
23094
23116
|
delete next.journal_entry_id;
|
|
23095
23117
|
}
|
|
23096
|
-
return
|
|
23097
|
-
ok: true,
|
|
23098
|
-
state: {
|
|
23099
|
-
version: 1,
|
|
23100
|
-
tasks: state.tasks.map((item) => item.id === id ? next : item)
|
|
23101
|
-
},
|
|
23102
|
-
task: next
|
|
23103
|
-
};
|
|
23118
|
+
return journalTaskResult(state, next);
|
|
23104
23119
|
}
|
|
23105
23120
|
function moveJournalTask(state, id, input, now) {
|
|
23106
23121
|
const source = state.tasks.find((task) => task.id === id);
|
|
@@ -23210,8 +23225,7 @@ function claimJournalTask(state, id, input, now) {
|
|
|
23210
23225
|
if (!task)
|
|
23211
23226
|
return { ok: false, error: "task not found" };
|
|
23212
23227
|
const nowMs = Date.parse(now);
|
|
23213
|
-
|
|
23214
|
-
if (activeClaim)
|
|
23228
|
+
if (taskClaimActive(task, nowMs))
|
|
23215
23229
|
return { ok: false, error: "task is already claimed" };
|
|
23216
23230
|
if (task.status !== "todo" && task.status !== "doing")
|
|
23217
23231
|
return {
|
|
@@ -23222,12 +23236,9 @@ function claimJournalTask(state, id, input, now) {
|
|
|
23222
23236
|
const wipLimit = input.wip_limit;
|
|
23223
23237
|
if (wipLimit !== undefined && wipLimit > 0) {
|
|
23224
23238
|
const activeDoing = state.tasks.filter((item) => {
|
|
23225
|
-
if (item.status !== "doing" ||
|
|
23226
|
-
return false;
|
|
23227
|
-
if (item.claim.by !== by)
|
|
23239
|
+
if (item.status !== "doing" || item.claim?.by !== by)
|
|
23228
23240
|
return false;
|
|
23229
|
-
|
|
23230
|
-
return Number.isFinite(expires) && expires > nowMs;
|
|
23241
|
+
return taskClaimActive(item, nowMs);
|
|
23231
23242
|
}).length;
|
|
23232
23243
|
if (activeDoing >= wipLimit)
|
|
23233
23244
|
return { ok: false, error: "WIP limit reached" };
|
|
@@ -23244,14 +23255,7 @@ function claimJournalTask(state, id, input, now) {
|
|
|
23244
23255
|
lease_expires_at: leaseExpiresAt
|
|
23245
23256
|
}
|
|
23246
23257
|
};
|
|
23247
|
-
return
|
|
23248
|
-
ok: true,
|
|
23249
|
-
state: {
|
|
23250
|
-
version: 1,
|
|
23251
|
-
tasks: state.tasks.map((item) => item.id === id ? next : item)
|
|
23252
|
-
},
|
|
23253
|
-
task: next
|
|
23254
|
-
};
|
|
23258
|
+
return journalTaskResult(state, next);
|
|
23255
23259
|
}
|
|
23256
23260
|
function completeJournalTask(state, id, input, now, makeId3 = makeJournalId) {
|
|
23257
23261
|
const task = state.tasks.find((item) => item.id === id);
|
|
@@ -23260,8 +23264,7 @@ function completeJournalTask(state, id, input, now, makeId3 = makeJournalId) {
|
|
|
23260
23264
|
if (task.status !== "doing")
|
|
23261
23265
|
return { ok: false, error: "only doing tasks can be completed" };
|
|
23262
23266
|
const nowMs = Date.parse(now);
|
|
23263
|
-
|
|
23264
|
-
if (!activeClaim)
|
|
23267
|
+
if (!taskClaimActive(task, nowMs))
|
|
23265
23268
|
return { ok: false, error: "task must be claimed before completion" };
|
|
23266
23269
|
const by = optionalString4(input.by, 128);
|
|
23267
23270
|
if (!by)
|
|
@@ -23291,14 +23294,7 @@ function completeJournalTask(state, id, input, now, makeId3 = makeJournalId) {
|
|
|
23291
23294
|
...notes.length ? { notes } : {}
|
|
23292
23295
|
};
|
|
23293
23296
|
delete next.claim;
|
|
23294
|
-
return
|
|
23295
|
-
ok: true,
|
|
23296
|
-
state: {
|
|
23297
|
-
version: 1,
|
|
23298
|
-
tasks: state.tasks.map((item) => item.id === id ? next : item)
|
|
23299
|
-
},
|
|
23300
|
-
task: next
|
|
23301
|
-
};
|
|
23297
|
+
return journalTaskResult(state, next);
|
|
23302
23298
|
}
|
|
23303
23299
|
function deleteJournalTask(state, id) {
|
|
23304
23300
|
const tasks = state.tasks.filter((task) => task.id !== id);
|
|
@@ -26498,7 +26494,7 @@ async function handleUploadFiles(req) {
|
|
|
26498
26494
|
return text("file exists", 409);
|
|
26499
26495
|
return text("upload failed", 500);
|
|
26500
26496
|
}
|
|
26501
|
-
triggerUpdate();
|
|
26497
|
+
triggerUpdate(uploads.map((upload) => dir ? `${dir}/${upload.name}` : upload.name));
|
|
26502
26498
|
return json2({
|
|
26503
26499
|
ok: true,
|
|
26504
26500
|
files: uploads.map((upload) => upload.name),
|
|
@@ -26731,6 +26727,12 @@ async function handleTrashPath(req) {
|
|
|
26731
26727
|
const originalFullPath = safeWorktreePath2(path);
|
|
26732
26728
|
if (!originalFullPath)
|
|
26733
26729
|
return text("not found", 404);
|
|
26730
|
+
let changedPaths;
|
|
26731
|
+
try {
|
|
26732
|
+
const stats = statSync6(originalFullPath);
|
|
26733
|
+
if (!stats.isDirectory())
|
|
26734
|
+
changedPaths = [path];
|
|
26735
|
+
} catch {}
|
|
26734
26736
|
const moved = await movePathToTrash(worktreePath(path));
|
|
26735
26737
|
if (!moved.ok)
|
|
26736
26738
|
return text(moved.error || "trash failed", 500);
|
|
@@ -26743,7 +26745,7 @@ async function handleTrashPath(req) {
|
|
|
26743
26745
|
trashPath: moved.trashPath
|
|
26744
26746
|
}
|
|
26745
26747
|
};
|
|
26746
|
-
triggerUpdate();
|
|
26748
|
+
triggerUpdate(changedPaths);
|
|
26747
26749
|
return json2({ ok: true, generation, undo });
|
|
26748
26750
|
}
|
|
26749
26751
|
async function handleCreateDirectory(req) {
|
|
@@ -26796,7 +26798,7 @@ async function handleCreateDirectory(req) {
|
|
|
26796
26798
|
return text("already exists", 409);
|
|
26797
26799
|
return text("create failed", 500);
|
|
26798
26800
|
}
|
|
26799
|
-
triggerUpdate();
|
|
26801
|
+
triggerUpdate([targetPath]);
|
|
26800
26802
|
return json2({ ok: true, path: targetPath, generation });
|
|
26801
26803
|
}
|
|
26802
26804
|
async function handleRestoreTrash(req) {
|
|
@@ -26828,7 +26830,13 @@ async function handleRestoreTrash(req) {
|
|
|
26828
26830
|
const restored = await restoreTrashPath(originalPath, trashPath || undefined);
|
|
26829
26831
|
if (!restored.ok)
|
|
26830
26832
|
return text(restored.error || "undo failed", 409);
|
|
26831
|
-
|
|
26833
|
+
let changedPaths;
|
|
26834
|
+
try {
|
|
26835
|
+
const stats = statSync6(worktreePath(originalPath));
|
|
26836
|
+
if (!stats.isDirectory())
|
|
26837
|
+
changedPaths = [originalPath];
|
|
26838
|
+
} catch {}
|
|
26839
|
+
triggerUpdate(changedPaths);
|
|
26832
26840
|
return json2({ ok: true, generation });
|
|
26833
26841
|
}
|
|
26834
26842
|
function annotationSse(kind, sessionId, entryId) {
|