Package metadata for release: engines, exports, prepublishOnly #6

Closed
opened 2026-08-09 03:44:08 +02:00 by clawbot · 2 comments
Collaborator

Problem

package.json declares "files": ["dist/", "README.md", "LICENSE"], but dist/ is
gitignored and there is no prepublishOnly or prepare script. Packing from a clean checkout
would produce an empty package.

There is also no engines field, despite the code depending on global fetch and
ReadableStream (Node 18+) and script/bootstrap pinning a specific Node 22 release. And
there is no exports map, so every internal module path is part of the public API surface by
accident — bin/quak.ts already deep-imports src/backup.ts, src/thumbnails.ts and
src/metadata-backup.ts, none of which are re-exported from src/index.ts.

None of this can be fixed after a 1.0.0 tag without a breaking change.

Definition of done

  1. package.json has a prepublishOnly (or prepack) script that runs the build, so a
    packed tarball always contains dist/.
  2. npm pack --dry-run (or yarn pack) from a clean checkout lists the built JavaScript,
    declaration files, README.md, and LICENSE, and nothing else. Record the verified file
    list in the PR body.
  3. package.json has an engines.node range matching what the code actually requires, and
    consistent with the Node version script/bootstrap pins.
  4. package.json has an exports map that deliberately declares the public entrypoints,
    including ./package.json, with types and import conditions ordered correctly.
  5. A decision is made and documented in the PR body for each of runBackup,
    runMetadataBackup, listMissingThumbnails, fixMissingThumbnails, BackupResult,
    BackupError, MissingThumbnailInfo, ThumbnailFixResult and RawMagicMetadata: either
    they become real public exports from src/index.ts, or they stay internal and the
    exports map keeps them unreachable. The README API reference issue depends on this
    answer, so it must be explicit.
  6. The CLI still works after a build, whichever way item 5 goes.
  7. make check green; make build green.
  8. TODO.md updated in the same commit.

Depends on

The build fix issue.

Note

Whether this package is ever published to a public npm registry is a separate open question
tracked in its own issue; this work is correct regardless of the answer.

## Problem `package.json` declares `"files": ["dist/", "README.md", "LICENSE"]`, but `dist/` is gitignored and there is no `prepublishOnly` or `prepare` script. Packing from a clean checkout would produce an **empty package**. There is also no `engines` field, despite the code depending on global `fetch` and `ReadableStream` (Node 18+) and `script/bootstrap` pinning a specific Node 22 release. And there is no `exports` map, so every internal module path is part of the public API surface by accident — `bin/quak.ts` already deep-imports `src/backup.ts`, `src/thumbnails.ts` and `src/metadata-backup.ts`, none of which are re-exported from `src/index.ts`. None of this can be fixed after a 1.0.0 tag without a breaking change. ## Definition of done 1. `package.json` has a `prepublishOnly` (or `prepack`) script that runs the build, so a packed tarball always contains `dist/`. 2. `npm pack --dry-run` (or `yarn pack`) from a clean checkout lists the built JavaScript, declaration files, `README.md`, and `LICENSE`, and nothing else. Record the verified file list in the PR body. 3. `package.json` has an `engines.node` range matching what the code actually requires, and consistent with the Node version `script/bootstrap` pins. 4. `package.json` has an `exports` map that deliberately declares the public entrypoints, including `./package.json`, with `types` and `import` conditions ordered correctly. 5. A decision is made and documented in the PR body for each of `runBackup`, `runMetadataBackup`, `listMissingThumbnails`, `fixMissingThumbnails`, `BackupResult`, `BackupError`, `MissingThumbnailInfo`, `ThumbnailFixResult` and `RawMagicMetadata`: either they become real public exports from `src/index.ts`, or they stay internal and the `exports` map keeps them unreachable. The README API reference issue depends on this answer, so it must be explicit. 6. The CLI still works after a build, whichever way item 5 goes. 7. `make check` green; `make build` green. 8. `TODO.md` updated in the same commit. ## Depends on The build fix issue. ## Note Whether this package is ever published to a public npm registry is a separate open question tracked in its own issue; this work is correct regardless of the answer.
clawbot added this to the 1.0.0 milestone 2026-08-09 03:44:08 +02:00
clawbot self-assigned this 2026-08-09 03:44:08 +02:00
Author
Collaborator

Rescoped under the ruling on #16

quak is not published to npm or to any other Microsoft service. Each item of the original definition of done, decided by whether it still serves a purpose:

  • Dropped: prepublishOnly/prepack (item 1) and the npm pack file list (item 2). They only shape a published package.
  • Removed: the files field in package.json. It only controls what goes into a published package, so keeping it suggests a publish that will not happen.
  • Added: "private": true. It makes an accidental npm publish or yarn publish fail.
  • Kept: engines.node (item 3). It tells anyone running quak which Node it needs. Set it to the major version the code is built and tested on: script/bootstrap pins Node 22.17.0 and the Dockerfile uses node:22-alpine. Do not claim support for older versions that nothing tests.
  • Kept: the exports map (item 4). The README documents a library API (import { Client, Library } from "quak"), and the map makes that the only importable surface. Declare . (with types before import) and ./package.json.
  • Settled: item 5. runBackup, BackupResult and BackupError are already exported from src/index.ts and stay public. runMetadataBackup, listMissingThumbnails, fixMissingThumbnails, MissingThumbnailInfo, ThumbnailFixResult and RawMagicMetadata serve the CLI only and stay internal, unreachable through the exports map.
  • Kept: item 6. The CLI still works after a build. bin/quak.ts imports by relative path, so the map does not affect it.

Definition of done

  1. package.json has "private": true, an engines.node range as above and the exports map as above, and no files field. No other field changes.
  2. The built CLI runs: script/build still runs it with --version.
  3. TODO.md updated in the same commit.

Model: opus-5-5

## Rescoped under the ruling on https://git.eeqj.de/sneak/quak/issues/16 quak is not published to npm or to any other Microsoft service. Each item of the original definition of done, decided by whether it still serves a purpose: - **Dropped: `prepublishOnly`/`prepack` (item 1) and the `npm pack` file list (item 2).** They only shape a published package. - **Removed: the `files` field in `package.json`.** It only controls what goes into a published package, so keeping it suggests a publish that will not happen. - **Added: `"private": true`.** It makes an accidental `npm publish` or `yarn publish` fail. - **Kept: `engines.node` (item 3).** It tells anyone running quak which Node it needs. Set it to the major version the code is built and tested on: `script/bootstrap` pins Node 22.17.0 and the `Dockerfile` uses `node:22-alpine`. Do not claim support for older versions that nothing tests. - **Kept: the `exports` map (item 4).** The README documents a library API (`import { Client, Library } from "quak"`), and the map makes that the only importable surface. Declare `.` (with `types` before `import`) and `./package.json`. - **Settled: item 5.** `runBackup`, `BackupResult` and `BackupError` are already exported from `src/index.ts` and stay public. `runMetadataBackup`, `listMissingThumbnails`, `fixMissingThumbnails`, `MissingThumbnailInfo`, `ThumbnailFixResult` and `RawMagicMetadata` serve the CLI only and stay internal, unreachable through the `exports` map. - **Kept: item 6.** The CLI still works after a build. `bin/quak.ts` imports by relative path, so the map does not affect it. ## Definition of done 1. `package.json` has `"private": true`, an `engines.node` range as above and the `exports` map as above, and no `files` field. No other field changes. 2. The built CLI runs: `script/build` still runs it with `--version`. 3. `TODO.md` updated in the same commit. Model: opus-5-5
Author
Collaborator

Built in #127: package.json is private, has no files field, declares engines.node >=22 and an exports map of . and ./package.json.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/quak/pulls/127: `package.json` is private, has no `files` field, declares `engines.node` `>=22` and an `exports` map of `.` and `./package.json`. Model: opus-5-5
Sign in to join this conversation.