Skip to content

tunnel: package hygiene — split build/dist, untrack artifacts, harden publish#56

Open
joelgwebber wants to merge 1 commit intomainfrom
joel/tunnel-package-hygiene
Open

tunnel: package hygiene — split build/dist, untrack artifacts, harden publish#56
joelgwebber wants to merge 1 commit intomainfrom
joel/tunnel-package-hygiene

Conversation

@joelgwebber
Copy link
Copy Markdown
Contributor

Summary

Cleans up the tunnel package's publish flow so the tarball is always self-contained and local builds can't get into a half-built state.

The phantom-diff problem. `rollup.config.mjs` had `input` and `output` pointing at the same file (`build/src/third_party/index.js`). `npm run build` produced a 6-line ESM re-export there; `npm run bundle` overwrote it with a 38k-line bundled artifact. The state on disk swung between the two depending on which command ran last, producing perpetual "changes" in `build/` whenever the artifact was committed.

The fix.

  • Untrack `build/` and `dist/`. Both are reproducible; nothing in git should track them. Phantom diff disappears.
  • Split outputs into disjoint trees. `tsc` → `build/` (used by tests + dev), `rollup` → `dist/index.js` (the published binary). They no longer fight over a path.
  • Bundle the whole CLI into one file. `dist/index.js` is a single self-contained ESM file containing the Node-version-check shim, `main.ts`, and all bundled deps. Tarball ships exactly two files: `dist/index.js` (1.2 MB) + `package.json`.
  • Lifecycle scripts on rails.
    • `clean` wipes both `build/` and `dist/`.
    • `build = clean && tsc` — always fresh, never stale.
    • `bundle = build && rollup` — bundle implies build.
    • `test = build && node --test` — self-bootstrapping; works from a clean tree.
    • `prepack = bundle` — runs on both `npm pack` AND `npm publish` (more robust than `prepublishOnly`, which only fires for publish). Drops the redundant `prepublishOnly`.
    • `verify = npm pack --dry-run` — quick "what would ship?" sanity.
  • `main.ts` walks up to find package.json instead of hard-coding `../..`. The bundled file at `dist/index.js` is one level above `package.json`; the tsc output at `build/src/main.js` is two levels above. Walk-up handles both.

Test plan

  • `npm test` from a clean tree (127 tests pass).
  • `npm pack --dry-run` shows exactly `dist/index.js` + `package.json`.
  • Install the packed tarball into an empty dir (`npm init -y && npm install `); `./node_modules/.bin/subtext-tunnel --version` prints the package version with no transitive `node_modules` pulled.
  • After merge, the next publish runs `prepack` automatically and produces the same tarball shape.

🤖 Generated with Claude Code

… publish

Cleans up the publish flow so the tarball is always self-contained and
local builds can't get into a half-built state.

- .gitignore: untrack tunnel/build/ and tunnel/dist/. tsc and rollup outputs
  are reproducible from sources; carrying them in git produced a 38k-line
  phantom diff every time `bundle` was run because rollup overwrote the
  small re-export with the full bundled output at the same path.
- rollup.config.mjs: bundle the entire CLI (input build/src/index.js, where
  the Node-version-check entrypoint lives) into a single dist/index.js.
  Build (tsc → build/) and bundle (rollup → dist/) now write to disjoint
  trees; no more clobbering. Shebang carries through from index.ts so the
  banner option is gone.
- package.json:
  - bin/files now point at dist/.
  - clean wipes both build/ and dist/.
  - build = clean && tsc (always a fresh build).
  - bundle = build && rollup.
  - test = build && node --test (self-bootstrapping).
  - prepack = bundle (covers both `npm pack` and `npm publish` — more
    robust than prepublishOnly, which only runs on publish).
  - verify = npm pack --dry-run (quick "what would ship?" check).
  - prepublishOnly removed (covered by prepack).
- main.ts: walk up to find package.json instead of hard-coding ../..,
  since the bundled file at dist/index.js sits one level above package.json
  and the tsc output at build/src/main.js sits two levels above.

Verified: `npm pack --dry-run` ships exactly two files (dist/index.js +
package.json); installing the tarball into a clean dir and running the
binary returns the expected version with no node_modules pulls.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant