diffx-cli 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +24 -5
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
4
|
+
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
5
5
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import getPort from "get-port";
|
|
7
7
|
import { execSync } from "node:child_process";
|
|
@@ -10,6 +10,21 @@ import { readFile } from "node:fs/promises";
|
|
|
10
10
|
import { Hono } from "hono";
|
|
11
11
|
import { serve } from "@hono/node-server";
|
|
12
12
|
import { homedir } from "node:os";
|
|
13
|
+
//#region src/path.ts
|
|
14
|
+
function decodeAndNormalize(p) {
|
|
15
|
+
let decoded = p;
|
|
16
|
+
try {
|
|
17
|
+
decoded = decodeURIComponent(p);
|
|
18
|
+
} catch {}
|
|
19
|
+
return decoded.replace(/\\/g, "/");
|
|
20
|
+
}
|
|
21
|
+
function isSafePath(relativePath, baseDir) {
|
|
22
|
+
const normalized = decodeAndNormalize(relativePath);
|
|
23
|
+
if (normalized.includes("..") || normalized.includes("\0") || isAbsolute(normalized)) return false;
|
|
24
|
+
const resolved = resolve(baseDir, normalized);
|
|
25
|
+
return resolved.startsWith(resolve(baseDir) + "/") || resolved === resolve(baseDir);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
13
28
|
//#region src/git.ts
|
|
14
29
|
function isBinaryFile(absolutePath) {
|
|
15
30
|
try {
|
|
@@ -23,8 +38,10 @@ function isBinaryFile(absolutePath) {
|
|
|
23
38
|
}
|
|
24
39
|
function getFileContent(filePath, version) {
|
|
25
40
|
const root = getRepoRoot();
|
|
41
|
+
if (!isSafePath(filePath, root)) return null;
|
|
42
|
+
const resolved = resolve(root, filePath);
|
|
26
43
|
if (version === "new") try {
|
|
27
|
-
return readFileSync(
|
|
44
|
+
return readFileSync(resolved);
|
|
28
45
|
} catch {
|
|
29
46
|
return null;
|
|
30
47
|
}
|
|
@@ -333,7 +350,9 @@ function createApp(clientDir, customDiffArgs, commentStore) {
|
|
|
333
350
|
app.get("/*", async (c) => {
|
|
334
351
|
let filePath = c.req.path;
|
|
335
352
|
if (filePath === "/") filePath = "/index.html";
|
|
336
|
-
const
|
|
353
|
+
const relativePath = filePath.slice(1);
|
|
354
|
+
if (!isSafePath(relativePath, clientDir)) return c.text("Forbidden", 403);
|
|
355
|
+
const fullPath = resolve(clientDir, relativePath);
|
|
337
356
|
try {
|
|
338
357
|
const content = await readFile(fullPath);
|
|
339
358
|
const contentType = MIME_TYPES[extname(fullPath)] || "application/octet-stream";
|
|
@@ -382,7 +401,7 @@ if (values.help) {
|
|
|
382
401
|
Usage: diffx [options] [-- <git diff args>]
|
|
383
402
|
|
|
384
403
|
Options:
|
|
385
|
-
-p, --port <port> Port to run the server on (default:
|
|
404
|
+
-p, --port <port> Port to run the server on (default: random available port)
|
|
386
405
|
--no-open Don't open the browser automatically
|
|
387
406
|
-v, --version Show version number
|
|
388
407
|
-h, --help Show this help message
|
|
@@ -405,7 +424,7 @@ if (!isGitRepo()) {
|
|
|
405
424
|
console.error("Error: not inside a git repository");
|
|
406
425
|
process.exit(1);
|
|
407
426
|
}
|
|
408
|
-
const port = await getPort(
|
|
427
|
+
const port = await getPort(values.port ? { port: parseInt(values.port, 10) } : void 0);
|
|
409
428
|
const clientDir = resolve(dirname(fileURLToPath(import.meta.url)), "client");
|
|
410
429
|
const { existsSync } = await import("node:fs");
|
|
411
430
|
const { port: actualPort } = await startServer({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "diffx-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Local code review tool for git diffs with a GitHub PR-like web UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"open": "^11.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@changesets/changelog-git": "^0.2.1",
|
|
36
37
|
"@changesets/cli": "^2.30.0",
|
|
37
38
|
"@pierre/diffs": "^1.1.11",
|
|
38
39
|
"@types/react": "^19.1.2",
|