fix: tsdown overwrites "sta" bin command.

TA
4mo ago
+11-5

Recently I found that somehow "sta" command was gone from the npm registry even it exists in the code.

I've asked an AI for the investigation and found a cause, so here's the fix.
It seems tsdown can generate whole "exports" section as well, but I focused on fixing the "bin" section.

Here's the AI analysis


Context

Starting with v13.12.1, the package published to npm no longer includes the sta command in the bin field — only swagger-typescript-api remains. Verified via npm view:

  • swagger-typescript-api@13.12.0 → { "sta": "dist/cli.mjs", "swagger-typescript-api": "dist/cli.mjs" }
  • swagger-typescript-api@13.12.1 … @13.12.4 (latest) → { "swagger-typescript-api": "dist/cli.mjs" }

The repo's package.json still declares both bins at every tag, so the source is not the problem — the published tarball is rewritten at publish time.

Root cause

  1. package.json has "prepack": "tsdown", so tsdown runs right before npm pack/publish.
  2. tsdown.config.ts sets exports: true, which lets tsdown's package-exports feature rewrite package.json.
  3. v13.12.1 bumped tsdown 0.21.10 → 0.22.2. tsdown v0.22.0 added automatic bin generation: when exports.bin is unset, it scans entry chunks for a shebang, and if exactly one is found it overwrites the bin field with a single command named after the package (src/features/pkg/exports.ts in rolldown/tsdown: binName = pkg.name[0] === '@' ? … : pkg.name, return { [binName]: detected }).
  4. index.ts (the CLI entry, bundled to dist/cli.mjs) starts with #!/usr/bin/env node — exactly one shebang chunk — so tsdown replaces the hand-written two-entry bin map with { "swagger-typescript-api": "./dist/cli.mjs" } in the packed tarball, silently dropping sta.

Fix

Edit tsdown.config.ts to configure bin explicitly instead of relying on shebang auto-detection:

export default defineConfig({
  entry: {
    index: "src/index.ts",
    cli: "index.ts",
  },
  dts: true,
  format: ["esm", "cjs"],
  sourcemap: true,
  exports: {
    bin: {
      sta: "./index.ts",
      "swagger-typescript-api": "./index.ts",
    },
  },
});

(Alternative: exports: { bin: false } also works — tsdown then leaves the manually-authored bin field untouched. The explicit map is preferred since it keeps tsdown as the single source of truth for the generated fields.)

Verification

  1. bun install --frozen-lockfile && bun run build — confirm package.json bin still contains both sta and swagger-typescript-api after the build (tsdown rewrites it during build when exports is enabled).
  2. npm pack --dry-run (or bun pm pack) and inspect the packed package.json to confirm both bin entries survive the prepack hook.
  3. bun run test to make sure nothing else regressed.

Summary by cubic

Restore the missing sta CLI by configuring tsdown to emit both bin commands and prevent overwrite during pack/publish. Both sta and swagger-typescript-api now install correctly.

  • Bug Fixes
    • Set exports.bin in tsdown.config.ts to map sta and swagger-typescript-api to ./index.ts.
    • Removed bin from package.json so tsdown is the single source of truth and avoids the single-bin auto-detection in tsdown@0.22.x.
    • Added a changeset to release this as a patch.