Skip to content

fix: tsdown overwrites "sta" bin command.#1808

Open
takayukioda wants to merge 3 commits into
acacode:mainfrom
takayukioda:fix/tsdown-erase-sta
Open

fix: tsdown overwrites "sta" bin command.#1808
takayukioda wants to merge 3 commits into
acacode:mainfrom
takayukioda:fix/tsdown-erase-sta

Conversation

@takayukioda

@takayukioda takayukioda commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

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.

Written for commit eaf5c3b. Summary will update on new commits.

Review in cubic

Also remove the bin command section from package.json
to make sure that the tsdown configuration is the
single source of truth.

From tsdown 0.22.0, they started to support generating
"bin" automatically, but that behaviour was not
matching with this repository's structure.
@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eaf5c3b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
swagger-typescript-api Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="package.json">

<violation number="1" location="package.json:28">
P2: Removing the static `bin` declaration from `package.json` makes CLI availability depend entirely on `tsdown` rewriting the manifest at build/pack time. This breaks workflows where `prepack` does not run, such as git dependency installs (`npm install <git-repo>`) and `npm link` before a local build, because the source manifest no longer advertises any bin commands. A safer alternative is to keep the `bin` field in `package.json` and set `exports: { bin: false }` in `tsdown.config.ts` so tsdown stops overwriting it.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread package.json
"sta": "./dist/cli.mjs",
"swagger-typescript-api": "./dist/cli.mjs"
},
"files": [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Removing the static bin declaration from package.json makes CLI availability depend entirely on tsdown rewriting the manifest at build/pack time. This breaks workflows where prepack does not run, such as git dependency installs (npm install <git-repo>) and npm link before a local build, because the source manifest no longer advertises any bin commands. A safer alternative is to keep the bin field in package.json and set exports: { bin: false } in tsdown.config.ts so tsdown stops overwriting it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At package.json, line 28:

<comment>Removing the static `bin` declaration from `package.json` makes CLI availability depend entirely on `tsdown` rewriting the manifest at build/pack time. This breaks workflows where `prepack` does not run, such as git dependency installs (`npm install <git-repo>`) and `npm link` before a local build, because the source manifest no longer advertises any bin commands. A safer alternative is to keep the `bin` field in `package.json` and set `exports: { bin: false }` in `tsdown.config.ts` so tsdown stops overwriting it.</comment>

<file context>
@@ -25,10 +25,6 @@
-    "sta": "./dist/cli.mjs",
-    "swagger-typescript-api": "./dist/cli.mjs"
-  },
   "files": [
     "dist",
     "templates"
</file context>

@js2me

js2me commented Jul 3, 2026

Copy link
Copy Markdown
Member

@takayukioda haha "someone who remove sta" that was me, thanks for your PR, please add changeset!

@takayukioda

Copy link
Copy Markdown
Contributor Author

@js2me added the changeset 👍🏽

btw, I would like to have an opinion about removing bin section from package.json.
I thought using tsdown configuration as a single source of truth would be nice, but also it means you need to understand how tsdown works and I wasn't so sure it's a good idea or not in this project.

@js2me

js2me commented Jul 4, 2026

Copy link
Copy Markdown
Member

@takayukioda thank you

@js2me

js2me commented Jul 4, 2026

Copy link
Copy Markdown
Member

@takayukioda if this removed bin property will not brake executing this package using sta and swagger-typescript-api then it's ok

@takayukioda

Copy link
Copy Markdown
Contributor Author

@js2me thanks for sharing your opinion. Then I think it's ready to review.👍🏽

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.

2 participants