@youtyan/code-viewer 0.11.1 → 0.11.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/code-viewer.js +567 -283
- package/package.json +1 -1
- package/web/app.js +22 -15
package/dist/code-viewer.js
CHANGED
|
@@ -1173,7 +1173,7 @@ function runBytesSync(args, cwd2, options = {}) {
|
|
|
1173
1173
|
}
|
|
1174
1174
|
function runBytesAsync(args, cwd2, options = {}) {
|
|
1175
1175
|
const maxBuffer = options.maxBuffer ?? 64 * 1024 * 1024;
|
|
1176
|
-
return new Promise((
|
|
1176
|
+
return new Promise((resolve4) => {
|
|
1177
1177
|
const proc = spawn(args[0], args.slice(1), {
|
|
1178
1178
|
cwd: cwd2,
|
|
1179
1179
|
stdio: [options.stdin === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
|
|
@@ -1214,7 +1214,7 @@ function runBytesAsync(args, cwd2, options = {}) {
|
|
|
1214
1214
|
} else {
|
|
1215
1215
|
stderr = appendProcessError(stderr, processError);
|
|
1216
1216
|
}
|
|
1217
|
-
|
|
1217
|
+
resolve4({
|
|
1218
1218
|
code,
|
|
1219
1219
|
stdout: concatBytes(stdoutChunks),
|
|
1220
1220
|
stderr
|
|
@@ -1260,41 +1260,28 @@ function concatBytes(chunks) {
|
|
|
1260
1260
|
}
|
|
1261
1261
|
return out;
|
|
1262
1262
|
}
|
|
1263
|
-
function spawnDetached(args) {
|
|
1264
|
-
const child = spawn(args[0], args.slice(1), {
|
|
1265
|
-
detached: true,
|
|
1266
|
-
stdio: "ignore"
|
|
1267
|
-
});
|
|
1268
|
-
child.on("error", (err) => {
|
|
1269
|
-
console.warn(
|
|
1270
|
-
"[code-viewer] failed to start detached command:",
|
|
1271
|
-
err.message
|
|
1272
|
-
);
|
|
1273
|
-
});
|
|
1274
|
-
child.unref();
|
|
1275
|
-
}
|
|
1276
1263
|
function spawnStream(args, cwd2) {
|
|
1277
1264
|
const proc = spawn(args[0], args.slice(1), {
|
|
1278
1265
|
cwd: cwd2,
|
|
1279
1266
|
stdio: ["ignore", "pipe", "ignore"]
|
|
1280
1267
|
});
|
|
1281
|
-
let
|
|
1268
|
+
let errorCode2 = 0;
|
|
1282
1269
|
proc.on("error", () => {
|
|
1283
|
-
|
|
1270
|
+
errorCode2 = 1;
|
|
1284
1271
|
});
|
|
1285
1272
|
return {
|
|
1286
1273
|
stream: Readable.toWeb(
|
|
1287
1274
|
proc.stdout
|
|
1288
1275
|
),
|
|
1289
|
-
exited: new Promise((
|
|
1276
|
+
exited: new Promise((resolve4) => {
|
|
1290
1277
|
let settled = false;
|
|
1291
1278
|
const done = (code) => {
|
|
1292
1279
|
if (settled) return;
|
|
1293
1280
|
settled = true;
|
|
1294
|
-
|
|
1281
|
+
resolve4(code);
|
|
1295
1282
|
};
|
|
1296
1283
|
proc.on("error", () => done(1));
|
|
1297
|
-
proc.on("close", (code) => done(
|
|
1284
|
+
proc.on("close", (code) => done(errorCode2 || (code ?? 1)));
|
|
1298
1285
|
}),
|
|
1299
1286
|
kill: (signal) => proc.kill(signal)
|
|
1300
1287
|
};
|
|
@@ -1350,7 +1337,7 @@ function startServer(options) {
|
|
|
1350
1337
|
res.end("internal server error");
|
|
1351
1338
|
}
|
|
1352
1339
|
});
|
|
1353
|
-
return new Promise((
|
|
1340
|
+
return new Promise((resolve4, reject) => {
|
|
1354
1341
|
server2.once("error", reject);
|
|
1355
1342
|
server2.listen(options.port, options.hostname, () => {
|
|
1356
1343
|
server2.off("error", reject);
|
|
@@ -1359,7 +1346,7 @@ function startServer(options) {
|
|
|
1359
1346
|
});
|
|
1360
1347
|
const address = server2.address();
|
|
1361
1348
|
const port = typeof address === "object" && address ? address.port : options.port;
|
|
1362
|
-
|
|
1349
|
+
resolve4({
|
|
1363
1350
|
port,
|
|
1364
1351
|
close: () => new Promise((resolveClose, rejectClose) => {
|
|
1365
1352
|
let settled = false;
|
|
@@ -1418,7 +1405,7 @@ async function writeWebResponse(res, response) {
|
|
|
1418
1405
|
res.end();
|
|
1419
1406
|
return;
|
|
1420
1407
|
}
|
|
1421
|
-
await new Promise((
|
|
1408
|
+
await new Promise((resolve4, reject) => {
|
|
1422
1409
|
const body = Readable.fromWeb(
|
|
1423
1410
|
response.body
|
|
1424
1411
|
);
|
|
@@ -1435,12 +1422,12 @@ async function writeWebResponse(res, response) {
|
|
|
1435
1422
|
reject(error);
|
|
1436
1423
|
})
|
|
1437
1424
|
);
|
|
1438
|
-
res.on("finish", () => settle(
|
|
1425
|
+
res.on("finish", () => settle(resolve4));
|
|
1439
1426
|
res.on(
|
|
1440
1427
|
"close",
|
|
1441
1428
|
() => settle(() => {
|
|
1442
1429
|
body.destroy();
|
|
1443
|
-
|
|
1430
|
+
resolve4();
|
|
1444
1431
|
})
|
|
1445
1432
|
);
|
|
1446
1433
|
body.pipe(res);
|
|
@@ -2444,7 +2431,7 @@ async function worktreeFilesystemEntriesAsync(cwd2, path, recursive, omitDirName
|
|
|
2444
2431
|
const yieldIfNeeded = async () => {
|
|
2445
2432
|
visitedDirs++;
|
|
2446
2433
|
if (visitedDirs % 25 === 0) {
|
|
2447
|
-
await new Promise((
|
|
2434
|
+
await new Promise((resolve4) => setTimeout(resolve4, 0));
|
|
2448
2435
|
}
|
|
2449
2436
|
};
|
|
2450
2437
|
const walk = async (dir, prefix, depth) => {
|
|
@@ -7925,7 +7912,7 @@ function searchPollIntervalMs() {
|
|
|
7925
7912
|
}
|
|
7926
7913
|
function sleep(ms) {
|
|
7927
7914
|
if (ms <= 0) return Promise.resolve();
|
|
7928
|
-
return new Promise((
|
|
7915
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
7929
7916
|
}
|
|
7930
7917
|
async function cancelSearchJobBestEffort(serverUrl, jobId) {
|
|
7931
7918
|
try {
|
|
@@ -8707,8 +8694,8 @@ function computeFuzzyMatch(query, path) {
|
|
|
8707
8694
|
const first = indices[0];
|
|
8708
8695
|
score -= Math.min(first, 40);
|
|
8709
8696
|
if (indices[0] >= baseStart) score += 20;
|
|
8710
|
-
const
|
|
8711
|
-
const tier = pathMatchTier(q, lowerPath,
|
|
8697
|
+
const basename6 = lowerPath.slice(baseStart);
|
|
8698
|
+
const tier = pathMatchTier(q, lowerPath, basename6);
|
|
8712
8699
|
const contiguousRange = contiguousPathRange(q, lowerPath, baseStart);
|
|
8713
8700
|
return {
|
|
8714
8701
|
score,
|
|
@@ -8860,8 +8847,8 @@ function createGlobPathMatcher(query) {
|
|
|
8860
8847
|
const suffix = query.replace(/^\*+/, "").toLowerCase();
|
|
8861
8848
|
return (path) => {
|
|
8862
8849
|
const baseStart = basenameStart(path);
|
|
8863
|
-
const
|
|
8864
|
-
if (!regex.test(path) && (query.includes("/") || !regex.test(
|
|
8850
|
+
const basename6 = path.slice(baseStart);
|
|
8851
|
+
if (!regex.test(path) && (query.includes("/") || !regex.test(basename6)))
|
|
8865
8852
|
return null;
|
|
8866
8853
|
const ranges = [];
|
|
8867
8854
|
const lowerPath = path.toLowerCase();
|
|
@@ -10840,7 +10827,7 @@ function send(message) {
|
|
|
10840
10827
|
`);
|
|
10841
10828
|
}
|
|
10842
10829
|
function readConfigLine() {
|
|
10843
|
-
return new Promise((
|
|
10830
|
+
return new Promise((resolve4, reject) => {
|
|
10844
10831
|
let buffer = "";
|
|
10845
10832
|
const stdin = process.stdin;
|
|
10846
10833
|
stdin.setEncoding("utf8");
|
|
@@ -10850,7 +10837,7 @@ function readConfigLine() {
|
|
|
10850
10837
|
if (newline === -1) return;
|
|
10851
10838
|
stdin.off("data", onData);
|
|
10852
10839
|
stdin.off("end", onEnd);
|
|
10853
|
-
|
|
10840
|
+
resolve4(buffer.slice(0, newline));
|
|
10854
10841
|
};
|
|
10855
10842
|
const onEnd = () => {
|
|
10856
10843
|
stdin.off("data", onData);
|
|
@@ -10861,12 +10848,12 @@ function readConfigLine() {
|
|
|
10861
10848
|
});
|
|
10862
10849
|
}
|
|
10863
10850
|
function hashFile(path) {
|
|
10864
|
-
return new Promise((
|
|
10851
|
+
return new Promise((resolve4) => {
|
|
10865
10852
|
const hash = createHash2("sha256");
|
|
10866
10853
|
const stream = createReadStream2(path);
|
|
10867
10854
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
10868
|
-
stream.on("end", () =>
|
|
10869
|
-
stream.on("error", () =>
|
|
10855
|
+
stream.on("end", () => resolve4(hash.digest("hex")));
|
|
10856
|
+
stream.on("error", () => resolve4("unreadable"));
|
|
10870
10857
|
});
|
|
10871
10858
|
}
|
|
10872
10859
|
function parsePorcelainV2(raw) {
|
|
@@ -11391,7 +11378,7 @@ function waitForAbortableResource(promise, signal, dispose, message = "operation
|
|
|
11391
11378
|
void promise.then(disposeSafely, () => void 0);
|
|
11392
11379
|
return Promise.reject(abortError(message));
|
|
11393
11380
|
}
|
|
11394
|
-
return new Promise((
|
|
11381
|
+
return new Promise((resolve4, reject) => {
|
|
11395
11382
|
let aborted = false;
|
|
11396
11383
|
const onAbort = () => {
|
|
11397
11384
|
aborted = true;
|
|
@@ -11406,7 +11393,7 @@ function waitForAbortableResource(promise, signal, dispose, message = "operation
|
|
|
11406
11393
|
disposeSafely(resource);
|
|
11407
11394
|
return;
|
|
11408
11395
|
}
|
|
11409
|
-
|
|
11396
|
+
resolve4(resource);
|
|
11410
11397
|
},
|
|
11411
11398
|
(error) => {
|
|
11412
11399
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -11436,7 +11423,7 @@ function appendMessage(buffer, message) {
|
|
|
11436
11423
|
function spawnCollectAsync(opts) {
|
|
11437
11424
|
throwIfAborted(opts.signal, opts.abortMessage);
|
|
11438
11425
|
const killSignal = opts.killSignal ?? "SIGTERM";
|
|
11439
|
-
return new Promise((
|
|
11426
|
+
return new Promise((resolve4, reject) => {
|
|
11440
11427
|
const child = spawn2(opts.command, opts.args, {
|
|
11441
11428
|
cwd: opts.cwd,
|
|
11442
11429
|
env: opts.env,
|
|
@@ -11453,7 +11440,7 @@ function spawnCollectAsync(opts) {
|
|
|
11453
11440
|
opts.signal?.removeEventListener("abort", abort);
|
|
11454
11441
|
let stderr = Buffer.concat(stderrChunks);
|
|
11455
11442
|
if (fallbackStderr) stderr = appendMessage(stderr, fallbackStderr);
|
|
11456
|
-
|
|
11443
|
+
resolve4({
|
|
11457
11444
|
stdout: Buffer.concat(stdoutChunks),
|
|
11458
11445
|
stderr,
|
|
11459
11446
|
code
|
|
@@ -15062,7 +15049,7 @@ function guardedS3Transport(signal, operation, deadline) {
|
|
|
15062
15049
|
controller.abort(err);
|
|
15063
15050
|
reject(err);
|
|
15064
15051
|
};
|
|
15065
|
-
const guarded = new Promise((
|
|
15052
|
+
const guarded = new Promise((resolve4, reject) => {
|
|
15066
15053
|
const onParentAbort = () => abort(new S3HttpError(503, "S3 HTTP transport aborted"), reject);
|
|
15067
15054
|
if (signal) {
|
|
15068
15055
|
signal.addEventListener("abort", onParentAbort, { once: true });
|
|
@@ -15076,7 +15063,7 @@ function guardedS3Transport(signal, operation, deadline) {
|
|
|
15076
15063
|
(value) => {
|
|
15077
15064
|
if (settled) return;
|
|
15078
15065
|
settled = true;
|
|
15079
|
-
|
|
15066
|
+
resolve4(value);
|
|
15080
15067
|
},
|
|
15081
15068
|
(err) => {
|
|
15082
15069
|
if (settled) return;
|
|
@@ -18180,7 +18167,7 @@ function guardedDynamoDbTransport(signal, operation, deadline) {
|
|
|
18180
18167
|
controller.abort(err);
|
|
18181
18168
|
reject(err);
|
|
18182
18169
|
};
|
|
18183
|
-
const guarded = new Promise((
|
|
18170
|
+
const guarded = new Promise((resolve4, reject) => {
|
|
18184
18171
|
const onParentAbort = () => abort(
|
|
18185
18172
|
new DynamoDbHttpError(503, "DynamoDB HTTP transport aborted"),
|
|
18186
18173
|
reject
|
|
@@ -18197,7 +18184,7 @@ function guardedDynamoDbTransport(signal, operation, deadline) {
|
|
|
18197
18184
|
(value) => {
|
|
18198
18185
|
if (settled) return;
|
|
18199
18186
|
settled = true;
|
|
18200
|
-
|
|
18187
|
+
resolve4(value);
|
|
18201
18188
|
},
|
|
18202
18189
|
(err) => {
|
|
18203
18190
|
if (settled) return;
|
|
@@ -19345,7 +19332,7 @@ async function parseBoundedJsonBody(req, maxBytes, tooLargeMessage) {
|
|
|
19345
19332
|
function waitForCallerAbort(promise, signal, message) {
|
|
19346
19333
|
if (!signal) return promise;
|
|
19347
19334
|
if (signal.aborted) return Promise.reject(abortError(message));
|
|
19348
|
-
return new Promise((
|
|
19335
|
+
return new Promise((resolve4, reject) => {
|
|
19349
19336
|
let settled = false;
|
|
19350
19337
|
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
19351
19338
|
const onAbort = () => {
|
|
@@ -19360,7 +19347,7 @@ function waitForCallerAbort(promise, signal, message) {
|
|
|
19360
19347
|
if (settled) return;
|
|
19361
19348
|
settled = true;
|
|
19362
19349
|
cleanup();
|
|
19363
|
-
|
|
19350
|
+
resolve4(value);
|
|
19364
19351
|
},
|
|
19365
19352
|
(err) => {
|
|
19366
19353
|
if (settled) return;
|
|
@@ -23248,8 +23235,8 @@ async function handleSnapshotCreate(cwd2, req, sendSse2, omitDirNames) {
|
|
|
23248
23235
|
let activeSnapshotId;
|
|
23249
23236
|
let resolveIdAck;
|
|
23250
23237
|
let rejectIdAck;
|
|
23251
|
-
const idAck = new Promise((
|
|
23252
|
-
resolveIdAck =
|
|
23238
|
+
const idAck = new Promise((resolve4, reject) => {
|
|
23239
|
+
resolveIdAck = resolve4;
|
|
23253
23240
|
rejectIdAck = reject;
|
|
23254
23241
|
});
|
|
23255
23242
|
(async () => {
|
|
@@ -24361,8 +24348,8 @@ function writeToShellWhenReady(id, data) {
|
|
|
24361
24348
|
const entry = sessions.get(id);
|
|
24362
24349
|
if (!entry || entry.meta.exited) return Promise.resolve({ status: "gone" });
|
|
24363
24350
|
if (entry.ready) return Promise.resolve(writeToShellEntry(entry, data));
|
|
24364
|
-
return new Promise((
|
|
24365
|
-
entry.queued.push({ data, resolve:
|
|
24351
|
+
return new Promise((resolve4) => {
|
|
24352
|
+
entry.queued.push({ data, resolve: resolve4 });
|
|
24366
24353
|
});
|
|
24367
24354
|
}
|
|
24368
24355
|
function writeToShell(id, data) {
|
|
@@ -24391,14 +24378,14 @@ function resizeShell(id, cols, rows) {
|
|
|
24391
24378
|
}
|
|
24392
24379
|
function waitForShellExit(entry) {
|
|
24393
24380
|
if (entry.meta.exited) return Promise.resolve(true);
|
|
24394
|
-
return new Promise((
|
|
24381
|
+
return new Promise((resolve4) => {
|
|
24395
24382
|
let settled = false;
|
|
24396
24383
|
const finish = (exited) => {
|
|
24397
24384
|
if (settled) return;
|
|
24398
24385
|
settled = true;
|
|
24399
24386
|
clearTimeout(timer2);
|
|
24400
24387
|
entry.exitListeners.delete(onExit);
|
|
24401
|
-
|
|
24388
|
+
resolve4(exited);
|
|
24402
24389
|
};
|
|
24403
24390
|
const onExit = () => finish(true);
|
|
24404
24391
|
entry.exitListeners.add(onExit);
|
|
@@ -25582,10 +25569,10 @@ async function runProbeWithTimeout(probe, file, cwd2, timeoutMs, parentSignal) {
|
|
|
25582
25569
|
timedOut: false
|
|
25583
25570
|
})
|
|
25584
25571
|
);
|
|
25585
|
-
const timeoutPromise = new Promise((
|
|
25572
|
+
const timeoutPromise = new Promise((resolve4) => {
|
|
25586
25573
|
timer2 = setTimeout(() => {
|
|
25587
25574
|
controller.abort();
|
|
25588
|
-
|
|
25575
|
+
resolve4({
|
|
25589
25576
|
kind: "fail",
|
|
25590
25577
|
reason: `timed out after ${timeoutMs}ms`,
|
|
25591
25578
|
timedOut: true
|
|
@@ -26018,6 +26005,102 @@ var init_dev_assets = __esm({
|
|
|
26018
26005
|
}
|
|
26019
26006
|
});
|
|
26020
26007
|
|
|
26008
|
+
// web-src/server/file-upload.ts
|
|
26009
|
+
import {
|
|
26010
|
+
closeSync as closeSync2,
|
|
26011
|
+
constants as constants3,
|
|
26012
|
+
openSync as openSync2,
|
|
26013
|
+
unlinkSync as unlinkSync2,
|
|
26014
|
+
writeFileSync as writeFileSync2
|
|
26015
|
+
} from "node:fs";
|
|
26016
|
+
function errorCode(error) {
|
|
26017
|
+
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
|
|
26018
|
+
return error.code;
|
|
26019
|
+
}
|
|
26020
|
+
return void 0;
|
|
26021
|
+
}
|
|
26022
|
+
function withErrorCode(error, code) {
|
|
26023
|
+
return code === void 0 ? error : Object.assign(error, { code });
|
|
26024
|
+
}
|
|
26025
|
+
function writeAndClose(upload, fd, bytes, fileSystem) {
|
|
26026
|
+
let writeError;
|
|
26027
|
+
try {
|
|
26028
|
+
fileSystem.write(fd, bytes);
|
|
26029
|
+
} catch (error) {
|
|
26030
|
+
writeError = error;
|
|
26031
|
+
}
|
|
26032
|
+
try {
|
|
26033
|
+
fileSystem.close(fd);
|
|
26034
|
+
} catch (closeError) {
|
|
26035
|
+
if (writeError !== void 0) {
|
|
26036
|
+
throw withErrorCode(
|
|
26037
|
+
errorWithCauses(`failed to write and close ${upload.target}`, [
|
|
26038
|
+
writeError,
|
|
26039
|
+
closeError
|
|
26040
|
+
]),
|
|
26041
|
+
errorCode(writeError)
|
|
26042
|
+
);
|
|
26043
|
+
}
|
|
26044
|
+
throw errorWithCause(`failed to close ${upload.target}`, closeError);
|
|
26045
|
+
}
|
|
26046
|
+
if (writeError !== void 0) throw writeError;
|
|
26047
|
+
}
|
|
26048
|
+
async function writeUploadedFiles(uploads, fileSystem = NODE_FILE_SYSTEM) {
|
|
26049
|
+
const created = [];
|
|
26050
|
+
try {
|
|
26051
|
+
for (const upload of uploads) {
|
|
26052
|
+
const bytes = new Uint8Array(await upload.file.arrayBuffer());
|
|
26053
|
+
const fd = fileSystem.open(upload.target);
|
|
26054
|
+
created.push(upload.target);
|
|
26055
|
+
writeAndClose(upload, fd, bytes, fileSystem);
|
|
26056
|
+
}
|
|
26057
|
+
} catch (error) {
|
|
26058
|
+
const cleanupErrors = [];
|
|
26059
|
+
for (const path of created) {
|
|
26060
|
+
try {
|
|
26061
|
+
fileSystem.remove(path);
|
|
26062
|
+
} catch (cleanupError) {
|
|
26063
|
+
cleanupErrors.push(
|
|
26064
|
+
errorWithCause(
|
|
26065
|
+
`failed to remove partial upload ${path}`,
|
|
26066
|
+
cleanupError
|
|
26067
|
+
)
|
|
26068
|
+
);
|
|
26069
|
+
}
|
|
26070
|
+
}
|
|
26071
|
+
const code = errorCode(error);
|
|
26072
|
+
if (cleanupErrors.length > 0) {
|
|
26073
|
+
throw withErrorCode(
|
|
26074
|
+
errorWithCauses(
|
|
26075
|
+
"failed to write uploaded files and clean up partial files",
|
|
26076
|
+
[error, ...cleanupErrors]
|
|
26077
|
+
),
|
|
26078
|
+
code
|
|
26079
|
+
);
|
|
26080
|
+
}
|
|
26081
|
+
throw withErrorCode(
|
|
26082
|
+
errorWithCause("failed to write uploaded files", error),
|
|
26083
|
+
code
|
|
26084
|
+
);
|
|
26085
|
+
}
|
|
26086
|
+
}
|
|
26087
|
+
var NODE_FILE_SYSTEM;
|
|
26088
|
+
var init_file_upload = __esm({
|
|
26089
|
+
"web-src/server/file-upload.ts"() {
|
|
26090
|
+
init_error_detail();
|
|
26091
|
+
NODE_FILE_SYSTEM = {
|
|
26092
|
+
open: (path) => openSync2(
|
|
26093
|
+
path,
|
|
26094
|
+
constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | (constants3.O_NOFOLLOW || 0),
|
|
26095
|
+
420
|
|
26096
|
+
),
|
|
26097
|
+
write: (fd, bytes) => writeFileSync2(fd, bytes),
|
|
26098
|
+
close: (fd) => closeSync2(fd),
|
|
26099
|
+
remove: (path) => unlinkSync2(path)
|
|
26100
|
+
};
|
|
26101
|
+
}
|
|
26102
|
+
});
|
|
26103
|
+
|
|
26021
26104
|
// web-src/server/journal.ts
|
|
26022
26105
|
import { join as join18 } from "node:path";
|
|
26023
26106
|
function dailyJournalFilePath(root) {
|
|
@@ -28960,6 +29043,367 @@ var init_mcp = __esm({
|
|
|
28960
29043
|
}
|
|
28961
29044
|
});
|
|
28962
29045
|
|
|
29046
|
+
// web-src/server/os-platform.ts
|
|
29047
|
+
function isWsl(platform, release) {
|
|
29048
|
+
return platform === "linux" && /wsl/i.test(release);
|
|
29049
|
+
}
|
|
29050
|
+
var init_os_platform = __esm({
|
|
29051
|
+
"web-src/server/os-platform.ts"() {
|
|
29052
|
+
}
|
|
29053
|
+
});
|
|
29054
|
+
|
|
29055
|
+
// web-src/server/os-opener.ts
|
|
29056
|
+
import { release as osRelease } from "node:os";
|
|
29057
|
+
function directoryCommands(path, platform) {
|
|
29058
|
+
if (platform === "darwin") {
|
|
29059
|
+
return [{ args: ["open", "--", path], cwd: path }];
|
|
29060
|
+
}
|
|
29061
|
+
if (platform === "win32") {
|
|
29062
|
+
return [{ args: ["explorer.exe", path], cwd: path }];
|
|
29063
|
+
}
|
|
29064
|
+
return [
|
|
29065
|
+
{ args: ["xdg-open", path], cwd: path },
|
|
29066
|
+
{ args: ["gio", "open", path], cwd: path }
|
|
29067
|
+
];
|
|
29068
|
+
}
|
|
29069
|
+
function urlCommands(url, cwd2, platform) {
|
|
29070
|
+
if (platform === "darwin") {
|
|
29071
|
+
return [{ args: ["open", url], cwd: cwd2 }];
|
|
29072
|
+
}
|
|
29073
|
+
if (platform === "win32") {
|
|
29074
|
+
return [{ args: ["cmd.exe", "/c", "start", "", url], cwd: cwd2 }];
|
|
29075
|
+
}
|
|
29076
|
+
return [
|
|
29077
|
+
{ args: ["xdg-open", url], cwd: cwd2 },
|
|
29078
|
+
{ args: ["gio", "open", url], cwd: cwd2 }
|
|
29079
|
+
];
|
|
29080
|
+
}
|
|
29081
|
+
function commandResultError(command, result) {
|
|
29082
|
+
return Object.assign(
|
|
29083
|
+
new Error(
|
|
29084
|
+
result.code === 0 ? `${command.args[0]} wrote to stderr` : `${command.args[0]} exited with ${result.code}`
|
|
29085
|
+
),
|
|
29086
|
+
{
|
|
29087
|
+
command: command.args,
|
|
29088
|
+
cwd: command.cwd,
|
|
29089
|
+
result
|
|
29090
|
+
}
|
|
29091
|
+
);
|
|
29092
|
+
}
|
|
29093
|
+
async function executeOpenCommand(command) {
|
|
29094
|
+
try {
|
|
29095
|
+
return await runAsync(command.args, command.cwd, {
|
|
29096
|
+
timeout: OPEN_TIMEOUT_MS
|
|
29097
|
+
});
|
|
29098
|
+
} catch (error) {
|
|
29099
|
+
throw commandExecutionError(command, error);
|
|
29100
|
+
}
|
|
29101
|
+
}
|
|
29102
|
+
function commandSucceeded(result) {
|
|
29103
|
+
return result.code === 0 && result.stderr.trim() === "";
|
|
29104
|
+
}
|
|
29105
|
+
function commandExecutionError(command, cause) {
|
|
29106
|
+
return Object.assign(
|
|
29107
|
+
errorWithCause(`failed to execute ${command.args[0]}`, cause),
|
|
29108
|
+
{
|
|
29109
|
+
command: command.args,
|
|
29110
|
+
cwd: command.cwd
|
|
29111
|
+
}
|
|
29112
|
+
);
|
|
29113
|
+
}
|
|
29114
|
+
async function runOpenCommands(commands, operation, errors = []) {
|
|
29115
|
+
for (const command of commands) {
|
|
29116
|
+
try {
|
|
29117
|
+
const result = await executeOpenCommand(command);
|
|
29118
|
+
if (commandSucceeded(result)) return;
|
|
29119
|
+
errors.push(commandResultError(command, result));
|
|
29120
|
+
} catch (error) {
|
|
29121
|
+
errors.push(
|
|
29122
|
+
error instanceof Error ? error : commandExecutionError(command, error)
|
|
29123
|
+
);
|
|
29124
|
+
}
|
|
29125
|
+
}
|
|
29126
|
+
throw errorWithCauses(`failed to ${operation}`, errors);
|
|
29127
|
+
}
|
|
29128
|
+
async function commandOutput(command) {
|
|
29129
|
+
const result = await executeOpenCommand(command);
|
|
29130
|
+
if (!commandSucceeded(result)) throw commandResultError(command, result);
|
|
29131
|
+
const output = result.stdout.trim();
|
|
29132
|
+
if (!output) {
|
|
29133
|
+
throw Object.assign(new Error(`${command.args[0]} returned no path`), {
|
|
29134
|
+
command: command.args,
|
|
29135
|
+
cwd: command.cwd,
|
|
29136
|
+
result
|
|
29137
|
+
});
|
|
29138
|
+
}
|
|
29139
|
+
return output;
|
|
29140
|
+
}
|
|
29141
|
+
async function wslWindowsCommandCwd(cwd2) {
|
|
29142
|
+
return commandOutput({ args: ["wslpath", "-u", "C:\\"], cwd: cwd2 });
|
|
29143
|
+
}
|
|
29144
|
+
async function openWslDirectory(path) {
|
|
29145
|
+
const errors = [];
|
|
29146
|
+
try {
|
|
29147
|
+
const windowsPath = await commandOutput({
|
|
29148
|
+
args: ["wslpath", "-w", path],
|
|
29149
|
+
cwd: path
|
|
29150
|
+
});
|
|
29151
|
+
const windowsCwd = await wslWindowsCommandCwd(path);
|
|
29152
|
+
const command = {
|
|
29153
|
+
args: ["cmd.exe", "/c", "start", "", windowsPath],
|
|
29154
|
+
cwd: windowsCwd
|
|
29155
|
+
};
|
|
29156
|
+
const result = await executeOpenCommand(command);
|
|
29157
|
+
if (commandSucceeded(result)) return;
|
|
29158
|
+
errors.push(commandResultError(command, result));
|
|
29159
|
+
} catch (error) {
|
|
29160
|
+
errors.push(
|
|
29161
|
+
error instanceof Error ? error : errorWithCause("failed to open directory through WSL", error)
|
|
29162
|
+
);
|
|
29163
|
+
}
|
|
29164
|
+
return runOpenCommands(
|
|
29165
|
+
[
|
|
29166
|
+
{ args: ["gio", "open", path], cwd: path },
|
|
29167
|
+
{ args: ["xdg-open", path], cwd: path }
|
|
29168
|
+
],
|
|
29169
|
+
"open directory in OS",
|
|
29170
|
+
errors
|
|
29171
|
+
);
|
|
29172
|
+
}
|
|
29173
|
+
async function openWslUrl(url, cwd2) {
|
|
29174
|
+
const errors = [];
|
|
29175
|
+
try {
|
|
29176
|
+
const windowsCwd = await wslWindowsCommandCwd(cwd2);
|
|
29177
|
+
const command = {
|
|
29178
|
+
args: ["cmd.exe", "/c", "start", "", url],
|
|
29179
|
+
cwd: windowsCwd
|
|
29180
|
+
};
|
|
29181
|
+
const result = await executeOpenCommand(command);
|
|
29182
|
+
if (commandSucceeded(result)) return;
|
|
29183
|
+
errors.push(commandResultError(command, result));
|
|
29184
|
+
} catch (error) {
|
|
29185
|
+
errors.push(
|
|
29186
|
+
error instanceof Error ? error : errorWithCause("failed to open URL through WSL", error)
|
|
29187
|
+
);
|
|
29188
|
+
}
|
|
29189
|
+
return runOpenCommands(
|
|
29190
|
+
[
|
|
29191
|
+
{ args: ["gio", "open", url], cwd: cwd2 },
|
|
29192
|
+
{ args: ["xdg-open", url], cwd: cwd2 }
|
|
29193
|
+
],
|
|
29194
|
+
"open URL in OS",
|
|
29195
|
+
errors
|
|
29196
|
+
);
|
|
29197
|
+
}
|
|
29198
|
+
function openDirectoryInOs(path, platform = process.platform, release = osRelease()) {
|
|
29199
|
+
if (isWsl(platform, release)) return openWslDirectory(path);
|
|
29200
|
+
return runOpenCommands(
|
|
29201
|
+
directoryCommands(path, platform),
|
|
29202
|
+
"open directory in OS"
|
|
29203
|
+
);
|
|
29204
|
+
}
|
|
29205
|
+
function openUrlInOs(url, cwd2, platform = process.platform, release = osRelease()) {
|
|
29206
|
+
if (isWsl(platform, release)) return openWslUrl(url, cwd2);
|
|
29207
|
+
return runOpenCommands(urlCommands(url, cwd2, platform), "open URL in OS");
|
|
29208
|
+
}
|
|
29209
|
+
var OPEN_TIMEOUT_MS;
|
|
29210
|
+
var init_os_opener = __esm({
|
|
29211
|
+
"web-src/server/os-opener.ts"() {
|
|
29212
|
+
init_error_detail();
|
|
29213
|
+
init_os_platform();
|
|
29214
|
+
init_runtime();
|
|
29215
|
+
OPEN_TIMEOUT_MS = 15e3;
|
|
29216
|
+
}
|
|
29217
|
+
});
|
|
29218
|
+
|
|
29219
|
+
// web-src/server/os-trash.ts
|
|
29220
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
29221
|
+
import { existsSync as existsSync8, lstatSync as lstatSync5, mkdirSync as mkdirSync4, renameSync } from "node:fs";
|
|
29222
|
+
import { homedir as homedir3, release as osRelease2 } from "node:os";
|
|
29223
|
+
import { basename as basename3, dirname as dirname6, join as join21, resolve as resolve2 } from "node:path";
|
|
29224
|
+
function windowsTrashScript(path) {
|
|
29225
|
+
const quotedPath = path.replace(/'/g, "''");
|
|
29226
|
+
return [
|
|
29227
|
+
"$ErrorActionPreference = 'Stop';",
|
|
29228
|
+
`$path = '${quotedPath}';`,
|
|
29229
|
+
"Add-Type -TypeDefinition @'",
|
|
29230
|
+
"using System;",
|
|
29231
|
+
"using System.Runtime.InteropServices;",
|
|
29232
|
+
"public static class CodeViewerRecycleBin {",
|
|
29233
|
+
" [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]",
|
|
29234
|
+
" public struct SHFILEOPSTRUCT {",
|
|
29235
|
+
" public IntPtr hwnd;",
|
|
29236
|
+
" public uint wFunc;",
|
|
29237
|
+
" public string pFrom;",
|
|
29238
|
+
" public string pTo;",
|
|
29239
|
+
" public ushort fFlags;",
|
|
29240
|
+
" [MarshalAs(UnmanagedType.Bool)] public bool fAnyOperationsAborted;",
|
|
29241
|
+
" public IntPtr hNameMappings;",
|
|
29242
|
+
" public string lpszProgressTitle;",
|
|
29243
|
+
" }",
|
|
29244
|
+
' [DllImport("shell32.dll", CharSet = CharSet.Unicode)]',
|
|
29245
|
+
" private static extern int SHFileOperationW(ref SHFILEOPSTRUCT lpFileOp);",
|
|
29246
|
+
" public static void MoveToRecycleBin(string path) {",
|
|
29247
|
+
" const uint FO_DELETE = 0x0003;",
|
|
29248
|
+
" const ushort FOF_SILENT = 0x0004;",
|
|
29249
|
+
" const ushort FOF_NOCONFIRMATION = 0x0010;",
|
|
29250
|
+
" const ushort FOF_ALLOWUNDO = 0x0040;",
|
|
29251
|
+
" const ushort FOF_NOERRORUI = 0x0400;",
|
|
29252
|
+
" var op = new SHFILEOPSTRUCT {",
|
|
29253
|
+
" hwnd = IntPtr.Zero,",
|
|
29254
|
+
" wFunc = FO_DELETE,",
|
|
29255
|
+
' pFrom = path + "\\0\\0",',
|
|
29256
|
+
" pTo = null,",
|
|
29257
|
+
" fFlags = (ushort)(FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT),",
|
|
29258
|
+
" fAnyOperationsAborted = false,",
|
|
29259
|
+
" hNameMappings = IntPtr.Zero,",
|
|
29260
|
+
" lpszProgressTitle = null",
|
|
29261
|
+
" };",
|
|
29262
|
+
" int result = SHFileOperationW(ref op);",
|
|
29263
|
+
' if (result != 0) throw new InvalidOperationException("SHFileOperationW failed: " + result);',
|
|
29264
|
+
' if (op.fAnyOperationsAborted) throw new OperationCanceledException("SHFileOperationW aborted");',
|
|
29265
|
+
" }",
|
|
29266
|
+
"}",
|
|
29267
|
+
"'@;",
|
|
29268
|
+
"[CodeViewerRecycleBin]::MoveToRecycleBin($path);"
|
|
29269
|
+
].join(" ");
|
|
29270
|
+
}
|
|
29271
|
+
function windowsRestoreTrashScript(originalPath) {
|
|
29272
|
+
const quotedPath = originalPath.replace(/'/g, "''");
|
|
29273
|
+
return [
|
|
29274
|
+
"$ErrorActionPreference = 'Stop';",
|
|
29275
|
+
`$original = '${quotedPath}';`,
|
|
29276
|
+
"$parent = [System.IO.Path]::GetDirectoryName($original);",
|
|
29277
|
+
"$name = [System.IO.Path]::GetFileName($original);",
|
|
29278
|
+
"$shell = New-Object -ComObject Shell.Application;",
|
|
29279
|
+
"$bin = $shell.Namespace(10);",
|
|
29280
|
+
"$restored = $false;",
|
|
29281
|
+
"foreach ($item in $bin.Items()) {",
|
|
29282
|
+
" $deletedFrom = $item.ExtendedProperty('System.Recycle.DeletedFrom');",
|
|
29283
|
+
" if ($item.Name -eq $name -and $deletedFrom -eq $parent) {",
|
|
29284
|
+
" $item.InvokeVerb('ESTORE');",
|
|
29285
|
+
" $restored = $true;",
|
|
29286
|
+
" break;",
|
|
29287
|
+
" }",
|
|
29288
|
+
"}",
|
|
29289
|
+
"if (-not $restored) { throw 'recycle bin item not found'; }"
|
|
29290
|
+
].join(" ");
|
|
29291
|
+
}
|
|
29292
|
+
function commandResultError2(operation, command, cwd2, result) {
|
|
29293
|
+
return Object.assign(new Error(`${operation} failed`), {
|
|
29294
|
+
command,
|
|
29295
|
+
cwd: cwd2,
|
|
29296
|
+
result
|
|
29297
|
+
});
|
|
29298
|
+
}
|
|
29299
|
+
async function runRequiredCommand(operation, command, cwd2) {
|
|
29300
|
+
let result;
|
|
29301
|
+
try {
|
|
29302
|
+
result = await runAsync(command, cwd2, { timeout: TRASH_TIMEOUT_MS });
|
|
29303
|
+
} catch (cause) {
|
|
29304
|
+
throw Object.assign(errorWithCause(`${operation} failed`, cause), {
|
|
29305
|
+
command,
|
|
29306
|
+
cwd: cwd2
|
|
29307
|
+
});
|
|
29308
|
+
}
|
|
29309
|
+
if (result.code !== 0) {
|
|
29310
|
+
throw commandResultError2(operation, command, cwd2, result);
|
|
29311
|
+
}
|
|
29312
|
+
}
|
|
29313
|
+
function managedTrashRoot(cwd2) {
|
|
29314
|
+
return join21(cwd2, ".code-viewer", "trash");
|
|
29315
|
+
}
|
|
29316
|
+
function movePathIntoTrashDirectory(path, trashRoot) {
|
|
29317
|
+
mkdirSync4(trashRoot, { recursive: true });
|
|
29318
|
+
const name = basename3(path) || "trash-item";
|
|
29319
|
+
const trashPath = join21(trashRoot, `${name}-${randomUUID2()}`);
|
|
29320
|
+
if (existsSync8(trashPath)) {
|
|
29321
|
+
throw Object.assign(new Error("trash destination already exists"), {
|
|
29322
|
+
trashPath
|
|
29323
|
+
});
|
|
29324
|
+
}
|
|
29325
|
+
renameSync(path, trashPath);
|
|
29326
|
+
return { trashPath };
|
|
29327
|
+
}
|
|
29328
|
+
function trashRootForHandle(cwd2, platform, release) {
|
|
29329
|
+
if (platform === "darwin") return join21(homedir3(), ".Trash");
|
|
29330
|
+
if (isWsl(platform, release)) return managedTrashRoot(cwd2);
|
|
29331
|
+
return null;
|
|
29332
|
+
}
|
|
29333
|
+
function unsupportedTrashError(operation, platform, release) {
|
|
29334
|
+
return Object.assign(new Error(`${operation} unsupported`), {
|
|
29335
|
+
platform,
|
|
29336
|
+
release
|
|
29337
|
+
});
|
|
29338
|
+
}
|
|
29339
|
+
async function movePathToTrash(path, cwd2, platform = process.platform, release = osRelease2()) {
|
|
29340
|
+
lstatSync5(path);
|
|
29341
|
+
if (platform === "darwin") {
|
|
29342
|
+
return movePathIntoTrashDirectory(path, join21(homedir3(), ".Trash"));
|
|
29343
|
+
}
|
|
29344
|
+
if (isWsl(platform, release)) {
|
|
29345
|
+
return movePathIntoTrashDirectory(path, managedTrashRoot(cwd2));
|
|
29346
|
+
}
|
|
29347
|
+
if (platform === "win32") {
|
|
29348
|
+
await runRequiredCommand(
|
|
29349
|
+
"move path to Recycle Bin",
|
|
29350
|
+
[
|
|
29351
|
+
"powershell.exe",
|
|
29352
|
+
"-NoProfile",
|
|
29353
|
+
"-NonInteractive",
|
|
29354
|
+
"-ExecutionPolicy",
|
|
29355
|
+
"Bypass",
|
|
29356
|
+
"-Command",
|
|
29357
|
+
windowsTrashScript(path)
|
|
29358
|
+
],
|
|
29359
|
+
cwd2
|
|
29360
|
+
);
|
|
29361
|
+
return {};
|
|
29362
|
+
}
|
|
29363
|
+
throw unsupportedTrashError("trash", platform, release);
|
|
29364
|
+
}
|
|
29365
|
+
async function restorePathFromTrash(originalPath, trashPath, cwd2, platform = process.platform, release = osRelease2()) {
|
|
29366
|
+
if (existsSync8(originalPath)) {
|
|
29367
|
+
throw new Error("restore target exists");
|
|
29368
|
+
}
|
|
29369
|
+
if (trashPath) {
|
|
29370
|
+
const trashRoot = trashRootForHandle(cwd2, platform, release);
|
|
29371
|
+
if (!trashRoot || dirname6(resolve2(trashPath)) !== resolve2(trashRoot)) {
|
|
29372
|
+
throw new Error("invalid trash handle");
|
|
29373
|
+
}
|
|
29374
|
+
if (!existsSync8(trashPath)) throw new Error("trash item not found");
|
|
29375
|
+
mkdirSync4(dirname6(originalPath), { recursive: true });
|
|
29376
|
+
renameSync(trashPath, originalPath);
|
|
29377
|
+
return;
|
|
29378
|
+
}
|
|
29379
|
+
if (platform === "win32") {
|
|
29380
|
+
await runRequiredCommand(
|
|
29381
|
+
"restore path from Recycle Bin",
|
|
29382
|
+
[
|
|
29383
|
+
"powershell.exe",
|
|
29384
|
+
"-NoProfile",
|
|
29385
|
+
"-NonInteractive",
|
|
29386
|
+
"-ExecutionPolicy",
|
|
29387
|
+
"Bypass",
|
|
29388
|
+
"-Command",
|
|
29389
|
+
windowsRestoreTrashScript(originalPath)
|
|
29390
|
+
],
|
|
29391
|
+
cwd2
|
|
29392
|
+
);
|
|
29393
|
+
return;
|
|
29394
|
+
}
|
|
29395
|
+
throw unsupportedTrashError("restore from trash", platform, release);
|
|
29396
|
+
}
|
|
29397
|
+
var TRASH_TIMEOUT_MS;
|
|
29398
|
+
var init_os_trash = __esm({
|
|
29399
|
+
"web-src/server/os-trash.ts"() {
|
|
29400
|
+
init_error_detail();
|
|
29401
|
+
init_os_platform();
|
|
29402
|
+
init_runtime();
|
|
29403
|
+
TRASH_TIMEOUT_MS = 6e4;
|
|
29404
|
+
}
|
|
29405
|
+
});
|
|
29406
|
+
|
|
28963
29407
|
// web-src/server/request-origin.ts
|
|
28964
29408
|
function requestAllowed(req) {
|
|
28965
29409
|
const host = req.headers.get("host") || "";
|
|
@@ -28984,12 +29428,12 @@ var init_request_origin = __esm({
|
|
|
28984
29428
|
|
|
28985
29429
|
// web-src/server/watch-supervisor.ts
|
|
28986
29430
|
import { spawn as spawn3 } from "node:child_process";
|
|
28987
|
-
import { join as
|
|
29431
|
+
import { join as join22 } from "node:path";
|
|
28988
29432
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
28989
29433
|
function watchChildCommand() {
|
|
28990
29434
|
const entry = process.argv[1] ?? "";
|
|
28991
29435
|
const isTypeScriptEntry = entry.endsWith(".ts");
|
|
28992
|
-
const script = isTypeScriptEntry ?
|
|
29436
|
+
const script = isTypeScriptEntry ? join22(fileURLToPath3(new URL(".", import.meta.url)), "cli.ts") : entry;
|
|
28993
29437
|
const loaderArgs = isTypeScriptEntry ? process.execArgv : [];
|
|
28994
29438
|
return [process.argv[0], ...loaderArgs, script, "watch-child"];
|
|
28995
29439
|
}
|
|
@@ -29766,14 +30210,14 @@ var init_terminal_images = __esm({
|
|
|
29766
30210
|
|
|
29767
30211
|
// web-src/server/terminal/images.ts
|
|
29768
30212
|
import { realpathSync as realpathSync7, statSync as statSync7 } from "node:fs";
|
|
29769
|
-
import { homedir as
|
|
29770
|
-
import { basename as
|
|
30213
|
+
import { homedir as homedir4 } from "node:os";
|
|
30214
|
+
import { basename as basename4, isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
|
|
29771
30215
|
function resolveTerminalImage(cwd2, candidate) {
|
|
29772
30216
|
if (typeof candidate !== "string" || candidate === "") return null;
|
|
29773
30217
|
if (candidate.includes("\0")) return null;
|
|
29774
30218
|
if (!terminalImageExtension(candidate)) return null;
|
|
29775
|
-
const expanded = candidate.startsWith("~/") ?
|
|
29776
|
-
const full = isAbsolute2(expanded) ? expanded :
|
|
30219
|
+
const expanded = candidate.startsWith("~/") ? resolve3(homedir4(), candidate.slice(2)) : candidate;
|
|
30220
|
+
const full = isAbsolute2(expanded) ? expanded : resolve3(cwd2, expanded);
|
|
29777
30221
|
try {
|
|
29778
30222
|
const real = realpathSync7(full);
|
|
29779
30223
|
const stat3 = statSync7(real);
|
|
@@ -29798,7 +30242,7 @@ function resolveTerminalImages(cwd2, candidates) {
|
|
|
29798
30242
|
path: image.path,
|
|
29799
30243
|
// 画面で探すのは、渡された綴りそのもの。実体のパスとは違うことがある。
|
|
29800
30244
|
candidate,
|
|
29801
|
-
name:
|
|
30245
|
+
name: basename4(image.path),
|
|
29802
30246
|
url: terminalImageUrl(image.path)
|
|
29803
30247
|
});
|
|
29804
30248
|
}
|
|
@@ -29815,7 +30259,7 @@ var init_images = __esm({
|
|
|
29815
30259
|
|
|
29816
30260
|
// web-src/server/terminal/paste.ts
|
|
29817
30261
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
29818
|
-
import { join as
|
|
30262
|
+
import { join as join23 } from "node:path";
|
|
29819
30263
|
async function savePastedImage(cwd2, mime, base64) {
|
|
29820
30264
|
const extension = pasteImageExtension(mime);
|
|
29821
30265
|
if (!extension) {
|
|
@@ -29840,8 +30284,8 @@ async function savePastedImage(cwd2, mime, base64) {
|
|
|
29840
30284
|
return { status: "invalid", message: "image too large" };
|
|
29841
30285
|
}
|
|
29842
30286
|
const name = `${makeTimedId("paste")}.${extension}`;
|
|
29843
|
-
const dir =
|
|
29844
|
-
const path =
|
|
30287
|
+
const dir = join23(cwd2, PASTE_DIR);
|
|
30288
|
+
const path = join23(dir, name);
|
|
29845
30289
|
try {
|
|
29846
30290
|
await mkdir2(dir, { recursive: true });
|
|
29847
30291
|
await writeFile2(path, bytes);
|
|
@@ -29858,7 +30302,7 @@ var init_paste = __esm({
|
|
|
29858
30302
|
"web-src/server/terminal/paste.ts"() {
|
|
29859
30303
|
init_id();
|
|
29860
30304
|
init_terminal_paste();
|
|
29861
|
-
PASTE_DIR =
|
|
30305
|
+
PASTE_DIR = join23(".code-viewer", "pasted");
|
|
29862
30306
|
}
|
|
29863
30307
|
});
|
|
29864
30308
|
|
|
@@ -30261,22 +30705,14 @@ var init_activity = __esm({
|
|
|
30261
30705
|
// web-src/server/preview.ts
|
|
30262
30706
|
var preview_exports = {};
|
|
30263
30707
|
import {
|
|
30264
|
-
|
|
30265
|
-
|
|
30266
|
-
existsSync as existsSync8,
|
|
30267
|
-
lstatSync as lstatSync5,
|
|
30268
|
-
mkdirSync as mkdirSync4,
|
|
30269
|
-
openSync as openSync2,
|
|
30708
|
+
existsSync as existsSync9,
|
|
30709
|
+
mkdirSync as mkdirSync5,
|
|
30270
30710
|
readFileSync as readFileSync8,
|
|
30271
30711
|
realpathSync as realpathSync8,
|
|
30272
|
-
renameSync,
|
|
30273
30712
|
statSync as statSync8,
|
|
30274
|
-
|
|
30275
|
-
watch,
|
|
30276
|
-
writeFileSync as writeFileSync2
|
|
30713
|
+
watch
|
|
30277
30714
|
} from "node:fs";
|
|
30278
|
-
import {
|
|
30279
|
-
import { basename as basename4, dirname as dirname6, extname as extname2, join as join23, relative as relative8 } from "node:path";
|
|
30715
|
+
import { basename as basename5, dirname as dirname7, extname as extname2, join as join24, relative as relative8 } from "node:path";
|
|
30280
30716
|
function parseCli() {
|
|
30281
30717
|
const rest = [];
|
|
30282
30718
|
for (let i = 2; i < process.argv.length; i++) {
|
|
@@ -30400,7 +30836,7 @@ Examples:
|
|
|
30400
30836
|
}
|
|
30401
30837
|
function warnIfLegacyConfigPresent() {
|
|
30402
30838
|
try {
|
|
30403
|
-
if (
|
|
30839
|
+
if (existsSync9(join24(cwd, ".code-viewer.json"))) {
|
|
30404
30840
|
console.warn(
|
|
30405
30841
|
"[code-viewer] .code-viewer.json is no longer used; configure scope and upload from Viewer Settings instead. The file can be safely removed."
|
|
30406
30842
|
);
|
|
@@ -30507,8 +30943,8 @@ function staticFile(pathname) {
|
|
|
30507
30943
|
}
|
|
30508
30944
|
const spec = map[pathname];
|
|
30509
30945
|
if (!spec) return null;
|
|
30510
|
-
const full =
|
|
30511
|
-
if (!
|
|
30946
|
+
const full = join24(WEB_ROOT, spec[0]);
|
|
30947
|
+
if (!existsSync9(full)) return text("not found", 404);
|
|
30512
30948
|
return new Response(readFileSync8(full), {
|
|
30513
30949
|
headers: { "Content-Type": spec[1], "Cache-Control": "no-store" }
|
|
30514
30950
|
});
|
|
@@ -30602,7 +31038,7 @@ async function computePayload(extras, range, pathFilter = "", responseGeneration
|
|
|
30602
31038
|
files: [],
|
|
30603
31039
|
totals: { files: 0, additions: 0, deletions: 0 },
|
|
30604
31040
|
range: "worktree .. worktree",
|
|
30605
|
-
project:
|
|
31041
|
+
project: basename5(cwd),
|
|
30606
31042
|
branch: await currentBranchMetadata(),
|
|
30607
31043
|
generation: responseGeneration
|
|
30608
31044
|
};
|
|
@@ -30645,7 +31081,7 @@ async function computePayload(extras, range, pathFilter = "", responseGeneration
|
|
|
30645
31081
|
files: meta,
|
|
30646
31082
|
totals,
|
|
30647
31083
|
range: label || "HEAD",
|
|
30648
|
-
project:
|
|
31084
|
+
project: basename5(cwd),
|
|
30649
31085
|
branch: await currentBranchMetadata(),
|
|
30650
31086
|
generation: responseGeneration,
|
|
30651
31087
|
...metaResult.error ? { error: metaResult.error } : {}
|
|
@@ -30766,7 +31202,7 @@ function safeWorktreePath2(path) {
|
|
|
30766
31202
|
return safeWorktreePath(currentSearchEnv(), path);
|
|
30767
31203
|
}
|
|
30768
31204
|
function worktreePath(path) {
|
|
30769
|
-
return
|
|
31205
|
+
return join24(cwd, path);
|
|
30770
31206
|
}
|
|
30771
31207
|
function safeOpenWorktreePath(path) {
|
|
30772
31208
|
if (path === "") {
|
|
@@ -30781,7 +31217,7 @@ function safeOpenWorktreePath(path) {
|
|
|
30781
31217
|
return safeWorktreePath2(path);
|
|
30782
31218
|
}
|
|
30783
31219
|
function parentRepoPath(path) {
|
|
30784
|
-
const parent =
|
|
31220
|
+
const parent = dirname7(path);
|
|
30785
31221
|
return parent === "." ? "" : parent;
|
|
30786
31222
|
}
|
|
30787
31223
|
function isoDate(ms) {
|
|
@@ -30930,7 +31366,7 @@ async function handleTree(url) {
|
|
|
30930
31366
|
return json2({
|
|
30931
31367
|
ref: target,
|
|
30932
31368
|
path,
|
|
30933
|
-
project:
|
|
31369
|
+
project: basename5(cwd),
|
|
30934
31370
|
branch: await currentBranchMetadata(),
|
|
30935
31371
|
entries: recursive ? entries.map(withStatus) : [
|
|
30936
31372
|
...await Promise.all(
|
|
@@ -30946,7 +31382,7 @@ async function handleTree(url) {
|
|
|
30946
31382
|
}
|
|
30947
31383
|
async function handleSettings() {
|
|
30948
31384
|
return json2({
|
|
30949
|
-
project:
|
|
31385
|
+
project: basename5(cwd),
|
|
30950
31386
|
branch: await currentBranchMetadata(),
|
|
30951
31387
|
repo_web_url: cwdHasGitRepository ? await remoteWebUrlAsync(cwd) : null,
|
|
30952
31388
|
scope: {
|
|
@@ -31103,7 +31539,7 @@ async function handleLog(url) {
|
|
|
31103
31539
|
}
|
|
31104
31540
|
function blamePathKey(p) {
|
|
31105
31541
|
try {
|
|
31106
|
-
const st = statSync8(
|
|
31542
|
+
const st = statSync8(join24(cwd, p));
|
|
31107
31543
|
return `${st.mtimeMs}:${st.size}`;
|
|
31108
31544
|
} catch {
|
|
31109
31545
|
return "missing";
|
|
@@ -31591,9 +32027,6 @@ function safeUploadFileName(name) {
|
|
|
31591
32027
|
if (!SAFE_UPLOAD_EXTENSIONS.has(extname2(trimmed).toLowerCase())) return null;
|
|
31592
32028
|
return trimmed;
|
|
31593
32029
|
}
|
|
31594
|
-
function uploadOpenFlags() {
|
|
31595
|
-
return constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | (constants3.O_NOFOLLOW || 0);
|
|
31596
|
-
}
|
|
31597
32030
|
async function handleUploadFiles(req) {
|
|
31598
32031
|
if (!uploadEnabled) return text("upload disabled by viewer settings", 403);
|
|
31599
32032
|
if (req.method !== "POST") return text("method not allowed", 405);
|
|
@@ -31637,33 +32070,18 @@ async function handleUploadFiles(req) {
|
|
|
31637
32070
|
if (file.size > MAX_UPLOAD_FILE_BYTES) return text("file too large", 413);
|
|
31638
32071
|
total += file.size;
|
|
31639
32072
|
if (total > MAX_UPLOAD_TOTAL_BYTES) return text("upload too large", 413);
|
|
31640
|
-
const target =
|
|
31641
|
-
if (relative8(realDir,
|
|
32073
|
+
const target = join24(realDir, safeName);
|
|
32074
|
+
if (relative8(realDir, dirname7(target)) !== "")
|
|
31642
32075
|
return text("invalid filename", 400);
|
|
31643
|
-
if (
|
|
32076
|
+
if (existsSync9(target)) return text("file exists", 409);
|
|
31644
32077
|
uploads.push({ file, name: safeName, target });
|
|
31645
32078
|
}
|
|
31646
|
-
const written = [];
|
|
31647
32079
|
try {
|
|
31648
|
-
|
|
31649
|
-
const fd = openSync2(upload.target, uploadOpenFlags(), 420);
|
|
31650
|
-
try {
|
|
31651
|
-
writeFileSync2(fd, new Uint8Array(await upload.file.arrayBuffer()));
|
|
31652
|
-
} finally {
|
|
31653
|
-
closeSync2(fd);
|
|
31654
|
-
}
|
|
31655
|
-
written.push(upload.target);
|
|
31656
|
-
}
|
|
32080
|
+
await writeUploadedFiles(uploads);
|
|
31657
32081
|
} catch (error) {
|
|
31658
|
-
for (const path of written) {
|
|
31659
|
-
try {
|
|
31660
|
-
unlinkSync2(path);
|
|
31661
|
-
} catch {
|
|
31662
|
-
}
|
|
31663
|
-
}
|
|
31664
32082
|
if (error.code === "EEXIST")
|
|
31665
|
-
return text(
|
|
31666
|
-
return text(
|
|
32083
|
+
return text(formatErrorDetail(error), 409);
|
|
32084
|
+
return text(formatErrorDetail(error), 500);
|
|
31667
32085
|
}
|
|
31668
32086
|
triggerUpdate(
|
|
31669
32087
|
uploads.map((upload) => dir ? `${dir}/${upload.name}` : upload.name)
|
|
@@ -31674,78 +32092,6 @@ async function handleUploadFiles(req) {
|
|
|
31674
32092
|
generation
|
|
31675
32093
|
});
|
|
31676
32094
|
}
|
|
31677
|
-
function openOsPath(path) {
|
|
31678
|
-
const cmd = process.platform === "darwin" ? ["open", "--", path] : process.platform === "win32" ? ["explorer.exe", path] : ["xdg-open", path];
|
|
31679
|
-
spawnDetached(cmd);
|
|
31680
|
-
}
|
|
31681
|
-
function windowsTrashScript(path) {
|
|
31682
|
-
const quotedPath = path.replace(/'/g, "''");
|
|
31683
|
-
return [
|
|
31684
|
-
"$ErrorActionPreference = 'Stop';",
|
|
31685
|
-
`$path = '${quotedPath}';`,
|
|
31686
|
-
"Add-Type -TypeDefinition @'",
|
|
31687
|
-
"using System;",
|
|
31688
|
-
"using System.Runtime.InteropServices;",
|
|
31689
|
-
"public static class CodeViewerRecycleBin {",
|
|
31690
|
-
" [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]",
|
|
31691
|
-
" public struct SHFILEOPSTRUCT {",
|
|
31692
|
-
" public IntPtr hwnd;",
|
|
31693
|
-
" public uint wFunc;",
|
|
31694
|
-
" public string pFrom;",
|
|
31695
|
-
" public string pTo;",
|
|
31696
|
-
" public ushort fFlags;",
|
|
31697
|
-
" [MarshalAs(UnmanagedType.Bool)] public bool fAnyOperationsAborted;",
|
|
31698
|
-
" public IntPtr hNameMappings;",
|
|
31699
|
-
" public string lpszProgressTitle;",
|
|
31700
|
-
" }",
|
|
31701
|
-
' [DllImport("shell32.dll", CharSet = CharSet.Unicode)]',
|
|
31702
|
-
" private static extern int SHFileOperationW(ref SHFILEOPSTRUCT lpFileOp);",
|
|
31703
|
-
" public static void MoveToRecycleBin(string path) {",
|
|
31704
|
-
" const uint FO_DELETE = 0x0003;",
|
|
31705
|
-
" const ushort FOF_SILENT = 0x0004;",
|
|
31706
|
-
" const ushort FOF_NOCONFIRMATION = 0x0010;",
|
|
31707
|
-
" const ushort FOF_ALLOWUNDO = 0x0040;",
|
|
31708
|
-
" const ushort FOF_NOERRORUI = 0x0400;",
|
|
31709
|
-
" var op = new SHFILEOPSTRUCT {",
|
|
31710
|
-
" hwnd = IntPtr.Zero,",
|
|
31711
|
-
" wFunc = FO_DELETE,",
|
|
31712
|
-
' pFrom = path + "\\0\\0",',
|
|
31713
|
-
" pTo = null,",
|
|
31714
|
-
" fFlags = (ushort)(FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT),",
|
|
31715
|
-
" fAnyOperationsAborted = false,",
|
|
31716
|
-
" hNameMappings = IntPtr.Zero,",
|
|
31717
|
-
" lpszProgressTitle = null",
|
|
31718
|
-
" };",
|
|
31719
|
-
" int result = SHFileOperationW(ref op);",
|
|
31720
|
-
' if (result != 0) throw new InvalidOperationException("SHFileOperationW failed: " + result);',
|
|
31721
|
-
' if (op.fAnyOperationsAborted) throw new OperationCanceledException("SHFileOperationW aborted");',
|
|
31722
|
-
" }",
|
|
31723
|
-
"}",
|
|
31724
|
-
"'@;",
|
|
31725
|
-
"[CodeViewerRecycleBin]::MoveToRecycleBin($path);"
|
|
31726
|
-
].join(" ");
|
|
31727
|
-
}
|
|
31728
|
-
function windowsRestoreTrashScript(originalPath) {
|
|
31729
|
-
const quotedPath = originalPath.replace(/'/g, "''");
|
|
31730
|
-
return [
|
|
31731
|
-
"$ErrorActionPreference = 'Stop';",
|
|
31732
|
-
`$original = '${quotedPath}';`,
|
|
31733
|
-
"$parent = [System.IO.Path]::GetDirectoryName($original);",
|
|
31734
|
-
"$name = [System.IO.Path]::GetFileName($original);",
|
|
31735
|
-
"$shell = New-Object -ComObject Shell.Application;",
|
|
31736
|
-
"$bin = $shell.Namespace(10);",
|
|
31737
|
-
"$restored = $false;",
|
|
31738
|
-
"foreach ($item in $bin.Items()) {",
|
|
31739
|
-
" $deletedFrom = $item.ExtendedProperty('System.Recycle.DeletedFrom');",
|
|
31740
|
-
" if ($item.Name -eq $name -and $deletedFrom -eq $parent) {",
|
|
31741
|
-
" $item.InvokeVerb('ESTORE');",
|
|
31742
|
-
" $restored = $true;",
|
|
31743
|
-
" break;",
|
|
31744
|
-
" }",
|
|
31745
|
-
"}",
|
|
31746
|
-
"if (-not $restored) { throw 'recycle bin item not found'; }"
|
|
31747
|
-
].join(" ");
|
|
31748
|
-
}
|
|
31749
32095
|
function makeUndoId() {
|
|
31750
32096
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
31751
32097
|
}
|
|
@@ -31760,86 +32106,6 @@ function triggerUpdate(changedPaths) {
|
|
|
31760
32106
|
const data = changedPaths?.length && changedPaths.length <= 50 ? JSON.stringify({ generation, paths: changedPaths }) : "tick";
|
|
31761
32107
|
sendSse("update", data);
|
|
31762
32108
|
}
|
|
31763
|
-
function moveMacPathIntoTrash(path) {
|
|
31764
|
-
const trashDir = join23(homedir4(), ".Trash");
|
|
31765
|
-
const base = basename4(path) || "code-viewer-trash-item";
|
|
31766
|
-
const target = join23(
|
|
31767
|
-
trashDir,
|
|
31768
|
-
`${base}-${Date.now()}-${process.pid}-${Math.random().toString(36).slice(2, 8)}`
|
|
31769
|
-
);
|
|
31770
|
-
try {
|
|
31771
|
-
mkdirSync4(trashDir, { recursive: true });
|
|
31772
|
-
renameSync(path, target);
|
|
31773
|
-
return { ok: true, trashPath: target };
|
|
31774
|
-
} catch (error) {
|
|
31775
|
-
return { ok: false, error: String(error) };
|
|
31776
|
-
}
|
|
31777
|
-
}
|
|
31778
|
-
async function movePathToTrash(path) {
|
|
31779
|
-
lstatSync5(path);
|
|
31780
|
-
if (process.platform === "darwin") {
|
|
31781
|
-
return moveMacPathIntoTrash(path);
|
|
31782
|
-
}
|
|
31783
|
-
if (process.platform === "win32") {
|
|
31784
|
-
const res = await runAsync(
|
|
31785
|
-
[
|
|
31786
|
-
"powershell.exe",
|
|
31787
|
-
"-NoProfile",
|
|
31788
|
-
"-NonInteractive",
|
|
31789
|
-
"-ExecutionPolicy",
|
|
31790
|
-
"Bypass",
|
|
31791
|
-
"-Command",
|
|
31792
|
-
windowsTrashScript(path)
|
|
31793
|
-
],
|
|
31794
|
-
cwd,
|
|
31795
|
-
{ timeout: 6e4 }
|
|
31796
|
-
);
|
|
31797
|
-
return res.code === 0 ? { ok: true } : { ok: false, error: res.stderr || res.stdout };
|
|
31798
|
-
}
|
|
31799
|
-
return { ok: false, error: "trash unsupported" };
|
|
31800
|
-
}
|
|
31801
|
-
async function restoreTrashPath(originalPath, trashPath) {
|
|
31802
|
-
const parent = parentRepoPath(originalPath);
|
|
31803
|
-
const parentFullPath = safeOpenWorktreePath(parent);
|
|
31804
|
-
if (!parentFullPath) return { ok: false, error: "invalid restore target" };
|
|
31805
|
-
const original = worktreePath(originalPath);
|
|
31806
|
-
if (existsSync8(original))
|
|
31807
|
-
return { ok: false, error: "restore target exists" };
|
|
31808
|
-
if (trashPath) {
|
|
31809
|
-
if (process.platform !== "darwin")
|
|
31810
|
-
return { ok: false, error: "invalid trash handle" };
|
|
31811
|
-
if (!existsSync8(trashPath))
|
|
31812
|
-
return { ok: false, error: "trash item not found" };
|
|
31813
|
-
try {
|
|
31814
|
-
const trashRoot = join23(homedir4(), ".Trash");
|
|
31815
|
-
const trashRelative = relative8(trashRoot, trashPath);
|
|
31816
|
-
if (trashRelative === "" || trashRelative.startsWith("..") || trashRelative.startsWith("/") || trashRelative.startsWith("\\"))
|
|
31817
|
-
return { ok: false, error: "invalid trash handle" };
|
|
31818
|
-
mkdirSync4(dirname6(original), { recursive: true });
|
|
31819
|
-
renameSync(trashPath, original);
|
|
31820
|
-
return { ok: true };
|
|
31821
|
-
} catch (error) {
|
|
31822
|
-
return { ok: false, error: String(error) };
|
|
31823
|
-
}
|
|
31824
|
-
}
|
|
31825
|
-
if (process.platform === "win32") {
|
|
31826
|
-
const res = await runAsync(
|
|
31827
|
-
[
|
|
31828
|
-
"powershell.exe",
|
|
31829
|
-
"-NoProfile",
|
|
31830
|
-
"-NonInteractive",
|
|
31831
|
-
"-ExecutionPolicy",
|
|
31832
|
-
"Bypass",
|
|
31833
|
-
"-Command",
|
|
31834
|
-
windowsRestoreTrashScript(original)
|
|
31835
|
-
],
|
|
31836
|
-
cwd,
|
|
31837
|
-
{ timeout: 6e4 }
|
|
31838
|
-
);
|
|
31839
|
-
return res.code === 0 ? { ok: true } : { ok: false, error: res.stderr || res.stdout };
|
|
31840
|
-
}
|
|
31841
|
-
return { ok: false, error: "undo unavailable for this trash operation" };
|
|
31842
|
-
}
|
|
31843
32109
|
async function handleOpenPath(req) {
|
|
31844
32110
|
if (req.method !== "POST") return text("method not allowed", 405);
|
|
31845
32111
|
if (!sideEffectRequestAllowed2(req)) return text("forbidden", 403);
|
|
@@ -31868,7 +32134,12 @@ async function handleOpenPath(req) {
|
|
|
31868
32134
|
if (!target) return text("not found", 404);
|
|
31869
32135
|
const stats = statSync8(target);
|
|
31870
32136
|
if (!stats.isDirectory()) return text("not a directory", 400);
|
|
31871
|
-
|
|
32137
|
+
try {
|
|
32138
|
+
await openDirectoryInOs(target);
|
|
32139
|
+
} catch (error) {
|
|
32140
|
+
console.error("[code-viewer] failed to open path in OS:", error);
|
|
32141
|
+
return text(formatErrorDetail(error), 500);
|
|
32142
|
+
}
|
|
31872
32143
|
return json2({ ok: true });
|
|
31873
32144
|
}
|
|
31874
32145
|
async function handleTrashPath(req) {
|
|
@@ -31890,17 +32161,23 @@ async function handleTrashPath(req) {
|
|
|
31890
32161
|
const path = typeof body.path === "string" ? body.path.replace(/^\/+|\/+$/g, "") : "";
|
|
31891
32162
|
if (!path) return text("invalid path", 400);
|
|
31892
32163
|
if (!safeRepoPath(path)) return text("invalid path", 400);
|
|
31893
|
-
if (isGitInternalPath(path)
|
|
32164
|
+
if (isGitInternalPath(path) || isCodeViewerInternalPath(path))
|
|
32165
|
+
return text("forbidden", 403);
|
|
31894
32166
|
const originalFullPath = safeWorktreePath2(path);
|
|
31895
32167
|
if (!originalFullPath) return text("not found", 404);
|
|
31896
32168
|
let changedPaths;
|
|
31897
32169
|
try {
|
|
31898
32170
|
const stats = statSync8(originalFullPath);
|
|
31899
32171
|
if (!stats.isDirectory()) changedPaths = [path];
|
|
31900
|
-
} catch {
|
|
32172
|
+
} catch (error) {
|
|
32173
|
+
return text(formatErrorDetail(error), 500);
|
|
32174
|
+
}
|
|
32175
|
+
let moved;
|
|
32176
|
+
try {
|
|
32177
|
+
moved = await movePathToTrash(worktreePath(path), cwd);
|
|
32178
|
+
} catch (error) {
|
|
32179
|
+
return text(formatErrorDetail(error), 500);
|
|
31901
32180
|
}
|
|
31902
|
-
const moved = await movePathToTrash(worktreePath(path));
|
|
31903
|
-
if (!moved.ok) return text(moved.error || "trash failed", 500);
|
|
31904
32181
|
const undo = {
|
|
31905
32182
|
id: makeUndoId(),
|
|
31906
32183
|
type: "trash",
|
|
@@ -31944,10 +32221,10 @@ async function handleCreateDirectory(req) {
|
|
|
31944
32221
|
const targetPath = dir ? `${dir}/${name}` : name;
|
|
31945
32222
|
if (!safeRepoPath(targetPath) || isGitInternalPath(targetPath))
|
|
31946
32223
|
return text("invalid target", 400);
|
|
31947
|
-
const target =
|
|
31948
|
-
if (
|
|
32224
|
+
const target = join24(parent, name);
|
|
32225
|
+
if (existsSync9(target)) return text("already exists", 409);
|
|
31949
32226
|
try {
|
|
31950
|
-
|
|
32227
|
+
mkdirSync5(target, { recursive: false });
|
|
31951
32228
|
} catch (error) {
|
|
31952
32229
|
if (error.code === "EEXIST")
|
|
31953
32230
|
return text("already exists", 409);
|
|
@@ -31976,14 +32253,22 @@ async function handleRestoreTrash(req) {
|
|
|
31976
32253
|
const trashPath = typeof body.trashPath === "string" ? body.trashPath : "";
|
|
31977
32254
|
if (!originalPath || !safeRepoPath(originalPath))
|
|
31978
32255
|
return text("invalid restore target", 400);
|
|
31979
|
-
if (isGitInternalPath(originalPath)
|
|
31980
|
-
|
|
31981
|
-
|
|
32256
|
+
if (isGitInternalPath(originalPath) || isCodeViewerInternalPath(originalPath))
|
|
32257
|
+
return text("forbidden", 403);
|
|
32258
|
+
const parent = parentRepoPath(originalPath);
|
|
32259
|
+
if (!safeOpenWorktreePath(parent)) return text("invalid restore target", 400);
|
|
32260
|
+
const original = worktreePath(originalPath);
|
|
32261
|
+
try {
|
|
32262
|
+
await restorePathFromTrash(original, trashPath || void 0, cwd);
|
|
32263
|
+
} catch (error) {
|
|
32264
|
+
return text(formatErrorDetail(error), 409);
|
|
32265
|
+
}
|
|
31982
32266
|
let changedPaths;
|
|
31983
32267
|
try {
|
|
31984
|
-
const stats = statSync8(
|
|
32268
|
+
const stats = statSync8(original);
|
|
31985
32269
|
if (!stats.isDirectory()) changedPaths = [originalPath];
|
|
31986
|
-
} catch {
|
|
32270
|
+
} catch (error) {
|
|
32271
|
+
return text(formatErrorDetail(error), 500);
|
|
31987
32272
|
}
|
|
31988
32273
|
triggerUpdate(changedPaths);
|
|
31989
32274
|
return json2({ ok: true, generation });
|
|
@@ -32480,10 +32765,6 @@ function closeSseClients() {
|
|
|
32480
32765
|
}
|
|
32481
32766
|
}
|
|
32482
32767
|
}
|
|
32483
|
-
function openBrowser(url) {
|
|
32484
|
-
const cmd = process.platform === "darwin" ? ["open", url] : process.platform === "win32" ? ["cmd.exe", "/c", "start", "", url] : ["xdg-open", url];
|
|
32485
|
-
spawnDetached(cmd);
|
|
32486
|
-
}
|
|
32487
32768
|
async function shutdown(exitCode = 0) {
|
|
32488
32769
|
if (shuttingDown) {
|
|
32489
32770
|
process.exit(1);
|
|
@@ -32574,10 +32855,13 @@ var init_preview = __esm({
|
|
|
32574
32855
|
init_command_resolver();
|
|
32575
32856
|
init_dev_assets();
|
|
32576
32857
|
init_doctor();
|
|
32858
|
+
init_file_upload();
|
|
32577
32859
|
init_git();
|
|
32578
32860
|
init_github_issues();
|
|
32579
32861
|
init_journal2();
|
|
32580
32862
|
init_mcp();
|
|
32863
|
+
init_os_opener();
|
|
32864
|
+
init_os_trash();
|
|
32581
32865
|
init_range();
|
|
32582
32866
|
init_raw_file_headers();
|
|
32583
32867
|
init_request_origin();
|
|
@@ -32589,8 +32873,8 @@ var init_preview = __esm({
|
|
|
32589
32873
|
init_state_store();
|
|
32590
32874
|
init_watch_supervisor();
|
|
32591
32875
|
init_worktree_watcher();
|
|
32592
|
-
WEB_ROOT =
|
|
32593
|
-
VERSION = JSON.parse(readFileSync8(
|
|
32876
|
+
WEB_ROOT = join24(ROOT, "web");
|
|
32877
|
+
VERSION = JSON.parse(readFileSync8(join24(ROOT, "package.json"), "utf8")).version;
|
|
32594
32878
|
DEFAULT_ARGS = ["HEAD"];
|
|
32595
32879
|
PREVIEW_HUNKS_DEFAULT = 3;
|
|
32596
32880
|
PREVIEW_LINES_DEFAULT = 1200;
|
|
@@ -32828,7 +33112,7 @@ data: ${watchLimitReached}
|
|
|
32828
33112
|
});
|
|
32829
33113
|
listenPort = server.port;
|
|
32830
33114
|
if (openAfterStart) {
|
|
32831
|
-
|
|
33115
|
+
await openUrlInOs(`http://127.0.0.1:${server.port}/`, cwd);
|
|
32832
33116
|
}
|
|
32833
33117
|
writeServerRegistry({
|
|
32834
33118
|
url: `http://127.0.0.1:${server.port}/`,
|