gunshi aims to be a zero-dependency package on npm to maximize npm install performance for end users. To achieve this, runtime dependencies such as args-tokens are inlined into the published bundle rather than declared as dependencies. This keeps the install graph minimal and avoids forcing consumers to download additional packages just to use gunshi.
The notes below describe how this is implemented in practice and the constraints it places on the build toolchain.
How each package under packages/* handles args-tokens, based on actual inspection of build outputs (lib/*.js, lib/*.d.ts).
Verified with: tsdown@0.21.0 + rolldown-plugin-dts@0.20.0 (pinned via overrides in pnpm-workspace.yaml).
| Package | What src/index.ts mainly contains |
Bundled into JS | Inlined into .d.ts |
Category |
|---|---|---|---|---|
gunshi |
Core implementation (uses parseArgs / resolveArgs directly) |
Yes (combinators.js, core-*.js, utils-*.js) |
Yes | JS impl included |
bone |
export * from 'gunshi/bone' |
Yes (index.js contains parser/utils/resolver) |
Yes | JS impl included |
combinators |
export * from 'gunshi/combinators' |
Yes (index.js contains combinators) |
Yes | JS impl included |
shared |
export * from 'gunshi/utils' + own logic |
Yes (index.js contains utils) |
Yes | JS impl included |
definition |
Type-only references from gunshi/context |
No | Yes | Types only |
plugin |
Type-only references from gunshi |
No | Yes | Types only |
plugin-i18n |
Type-only references from gunshi / @gunshi/* |
No | Yes | Types only |
- JS bundle:
args-tokensis declared underdevDependencies, so tsdown bundles it by default (onlydependencies/peerDependencies/optionalDependenciesare auto-externalized). .d.tsinlining: Eachtsdown.config.tsexplicitly inlines the types viadts.resolve: ['args-tokens', ...].
The goal is to completely hide args-tokens from the public API of gunshi. Consumers should not need to install args-tokens separately — both runtime and types stay enclosed within gunshi / @gunshi/*.
- "JS impl included" group (
gunshi/bone/combinators/shared): both runtime and types are inlined. - "Types only" group (
definition/plugin/plugin-i18n): does not use theargs-tokensruntime internally, but the re-exported type chain referencesargs-tokens, so only.d.tsinlining is required.
- The array form of
dts.resolvewas removed inrolldown-plugin-dtsv0.21.0 (issue #106). - A replacement API for "keep JS external while inlining only types" is not yet provided (tracked at issue #199).
- For this reason,
pnpm-workspace.yamlpinstsdown>rolldown-plugin-dts: 0.20.0viaoverrides.
The current tsdown-based bundling setup is a workaround. We plan to revisit and improve it in the future — for example, by migrating to a newer rolldown-plugin-dts API once an equivalent of the array-form dts.resolve becomes available, or by adopting a different toolchain that better supports the "bundle JS, hide as type-only dependency" pattern. Until then, the version pin and dts.resolve configuration described above should be kept in place.
The repository stays on pnpm v10. The exact version is pinned by the packageManager field in package.json.
Do not upgrade to pnpm@11 yet. CI started failing after the upgrade from pnpm@10.33.2 to pnpm@11.0.9 because rolldown could not resolve its Linux native optional dependency on GitHub Actions:
Cannot find module '@rolldown/binding-linux-x64-gnu'Adding @rolldown/binding-linux-x64-gnu directly as a root optionalDependency did not fix the issue, because rolldown still could not resolve the binding from its own package location under pnpm's install layout.
Stay on pnpm v10 until pnpm v11's optional native dependency linking behavior is confirmed to work with rolldown in CI.