Skip to content

Commit 90e5a87

Browse files
committed
build: prepare npm packaging and verification
1 parent 95bd096 commit 90e5a87

4 files changed

Lines changed: 165 additions & 5 deletions

File tree

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,41 @@ jobs:
5555
- name: TTY smoke tests
5656
run: bun run test:tty-smoke
5757

58+
pack-npm:
59+
name: Verify npm package
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: Check out repository
63+
uses: actions/checkout@v4
64+
65+
- name: Set up Bun
66+
uses: oven-sh/setup-bun@v2
67+
with:
68+
bun-version: 1.3.10
69+
70+
- name: Set up Node
71+
uses: actions/setup-node@v4
72+
with:
73+
node-version: 22
74+
75+
- name: Install dependencies
76+
run: bun install --frozen-lockfile
77+
78+
- name: Build npm runtime bundle
79+
run: bun run build:npm
80+
81+
- name: Verify npm pack output
82+
run: bun run check:pack
83+
84+
- name: Simulate global npm install
85+
run: |
86+
pkg_dir="$(mktemp -d)"
87+
install_dir="$(mktemp -d)"
88+
npm pack --pack-destination "$pkg_dir" >/dev/null
89+
pkg="$(find "$pkg_dir" -maxdepth 1 -name 'hunkdiff-*.tgz' | head -n1)"
90+
npm install -g --prefix "$install_dir" "$pkg"
91+
PATH="$install_dir/bin:$PATH" hunk --help | grep 'Usage: hunk'
92+
5893
build-bin:
5994
name: Build compiled binary
6095
runs-on: ubuntu-latest

package.json

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,56 @@
11
{
2-
"name": "hunk",
2+
"name": "hunkdiff",
33
"version": "0.1.0",
4-
"description": "Desktop-inspired terminal diff viewer for agent-authored changesets.",
5-
"module": "src/main.tsx",
4+
"description": "Desktop-inspired terminal diff viewer for understanding agent-authored changesets.",
65
"type": "module",
7-
"private": true,
6+
"packageManager": "bun@1.3.10",
87
"bin": {
9-
"hunk": "./src/main.tsx"
8+
"hunk": "./dist/npm/main.js"
109
},
10+
"files": [
11+
"dist/npm",
12+
"README.md",
13+
"LICENSE",
14+
"CONTRIBUTING.md",
15+
"SECURITY.md"
16+
],
1117
"scripts": {
1218
"start": "bun run src/main.tsx",
1319
"dev": "bun --watch src/main.tsx",
20+
"build:npm": "bash ./scripts/build-npm.sh",
1421
"build:bin": "bash ./scripts/build-bin.sh",
1522
"install:bin": "bash ./scripts/install-bin.sh",
1623
"typecheck": "tsc --noEmit",
1724
"test": "bun test",
1825
"test:tty-smoke": "bun test test/tty-render-smoke.test.ts",
26+
"check:pack": "bun run ./scripts/check-pack.ts",
27+
"prepack": "bun run build:npm",
1928
"bench:bootstrap-load": "bun run test/bootstrap-load-benchmark.ts",
2029
"bench:highlight-prefetch": "bun run test/adjacent-highlight-prefetch-benchmark.ts",
2130
"bench:large-stream": "bun run test/large-stream-windowing-benchmark.ts"
2231
},
32+
"keywords": [
33+
"diff",
34+
"git",
35+
"tui",
36+
"terminal",
37+
"code-review",
38+
"ai"
39+
],
40+
"repository": {
41+
"type": "git",
42+
"url": "git+https://github.com/modem-dev/hunk.git"
43+
},
44+
"homepage": "https://github.com/modem-dev/hunk#readme",
45+
"bugs": {
46+
"url": "https://github.com/modem-dev/hunk/issues"
47+
},
48+
"engines": {
49+
"bun": ">=1.3.10"
50+
},
51+
"publishConfig": {
52+
"access": "public"
53+
},
2354
"devDependencies": {
2455
"@types/bun": "latest",
2556
"@types/react": "^19.2.14",

scripts/build-npm.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
set -Eeuo pipefail
3+
4+
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
outdir="${repo_root}/dist/npm"
6+
7+
rm -rf "${outdir}"
8+
mkdir -p "${outdir}"
9+
10+
BUN_TMPDIR="${repo_root}/.bun-tmp" \
11+
BUN_INSTALL="${repo_root}/.bun-install" \
12+
bun build "${repo_root}/src/main.tsx" \
13+
--target bun \
14+
--format esm \
15+
--outdir "${outdir}" \
16+
--entry-naming main.js
17+
18+
chmod 0755 "${outdir}/main.js"
19+
20+
printf 'Built %s\n' "${outdir}/main.js"

scripts/check-pack.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bun
2+
3+
interface PackedFile {
4+
path: string;
5+
size: number;
6+
}
7+
8+
interface PackResult {
9+
name: string;
10+
version: string;
11+
filename: string;
12+
entryCount: number;
13+
files: PackedFile[];
14+
}
15+
16+
const proc = Bun.spawnSync(["npm", "pack", "--dry-run", "--json"], {
17+
cwd: process.cwd(),
18+
stdin: "ignore",
19+
stdout: "pipe",
20+
stderr: "pipe",
21+
env: process.env,
22+
});
23+
24+
const stdout = Buffer.from(proc.stdout).toString("utf8").trim();
25+
const stderr = Buffer.from(proc.stderr).toString("utf8").trim();
26+
27+
if (proc.exitCode !== 0) {
28+
throw new Error(stderr || stdout || "npm pack --dry-run failed");
29+
}
30+
31+
const jsonMatch = stdout.match(/(\[\s*\{[\s\S]*\}\s*\])\s*$/);
32+
const jsonText = jsonMatch?.[1];
33+
34+
if (!jsonText) {
35+
throw new Error(`Could not find npm pack JSON output. Full stdout:\n${stdout}`);
36+
}
37+
38+
const parsed = JSON.parse(jsonText) as PackResult[];
39+
const pack = parsed[0];
40+
41+
if (!pack) {
42+
throw new Error("npm pack --dry-run returned no pack result.");
43+
}
44+
45+
const publishedPaths = new Set(pack.files.map((file) => file.path));
46+
const requiredPaths = [
47+
"dist/npm/main.js",
48+
"README.md",
49+
"LICENSE",
50+
"CONTRIBUTING.md",
51+
"SECURITY.md",
52+
"package.json",
53+
];
54+
55+
for (const path of requiredPaths) {
56+
if (!publishedPaths.has(path)) {
57+
throw new Error(`Expected npm package to include ${path}.`);
58+
}
59+
}
60+
61+
const forbiddenPrefixes = [".github/", "src/", "test/", "scripts/", "tmp/"];
62+
const forbiddenPaths = ["AGENTS.md", "autoresearch.checks.sh", "autoresearch.sh", "bun.lock"];
63+
64+
for (const file of pack.files) {
65+
if (forbiddenPrefixes.some((prefix) => file.path.startsWith(prefix)) || forbiddenPaths.includes(file.path)) {
66+
throw new Error(`Unexpected file in npm package: ${file.path}`);
67+
}
68+
}
69+
70+
if (pack.name !== "hunkdiff") {
71+
throw new Error(`Expected npm package name to be hunkdiff, got ${pack.name}.`);
72+
}
73+
74+
console.log(`Verified npm pack output for ${pack.name}@${pack.version} (${pack.entryCount} files).`);

0 commit comments

Comments
 (0)