Skip to content

Upgrading tsdown 0.22 to 0.23

Breaking0.22.14 → 0.23.4Breaking13New8Changed3Fixed20Other1

BreakingUpgrade verdict

12 breaking changes.

  • If you build with Node.js 25, you must switch to Node 22.18+, 24.11+, or 26+.
  • Old tsup-style config options no longer work; use the new tsdown option names instead.
  • Older TypeScript resolution fallbacks are gone; use modern module resolution settings.
  • The package validation now runs a lighter ESM-only check by default.
Top 3 of 12 that need code or config changes

Node.js requirement changed in 0.23.0-beta.1: ^22.18.0 || >=24.11.0 → ^22.18.0 || ^24.11.0 || >=26.0.0.

Adds tinyps ^0.5.1.

Drops ansis, tree-kill.

Installs 54 packages in all (was 66).

Breaking12
Drops support for Node.js 25; supported versions are ^22.18.0, ^24.11.0, or >=26.0.0.
Removes deprecated tsup compatibility options such as bundle, outExtension, publicDir, removeNodeProtocol, and injectStyle.
bundleoutExtensionpublicDirremoveNodeProtocolinjectStyle
Drops the legacy types and typesVersions fields from generated package metadata.
typestypesVersions
Changes the attw default profile from strict to esm-only.
attwprofile
Removes the deprecated deps.onlyAllowBundle option.
deps.onlyAllowBundledeps.onlyBundle
Disables resolveDepSubpath by default.
resolveDepSubpath
Removes the deprecated skipNodeModulesBundle option.
skipNodeModulesBundledeps.neverBundle
Removes the dts.cjsReexport option; dual-format builds now generate CJS declarations in a separate pass.
dts.cjsReexport
Drops the types and typesVersions fields.
typestypesVersions
Removes the deprecated deps.onlyAllowBundle option.
deps.onlyAllowBundle
Removes the dts.cjsReexport option.
dts.cjsReexport
Makes dts.generator the only way to select the declaration generator.
dts.generatordts.oxcdts.tsgo

Generated by DepDelta from published .d.ts files. Not mixed with prose notes.

  • added: export { UserConfigFnContext }
  • changed: function build(inlineConfig?: InlineConfig): Promise<TsdownBundle[]> → function build(inlineConfig?: InlineConfig): Promise<TsdownHandle>
  • changed: function buildWithConfigs(configs: ResolvedConfig[], configDeps: Set<string>, _restart: () => void): Promise<TsdownBundle[]> → function buildWithConfigs(configs: ResolvedConfig[], configDeps: Set<string>, rebuild: () => Promise<TsdownHandle>): Promise<TsdownHandle>
  • added: export { TsdownHandle }
  • added: export { UserConfigFnContext }
  • added: function ShimsPlugin(config: ResolvedConfig, format: NormalizedFormat): Plugin
  • removed: const J: Logger
  • removed: const z: string
  • removed: export { UnusedOptions as u }
  • removed: function W({ pkg, deps: { neverBundle, alwaysBundle: jsAlwaysBundle, onlyBundle, onlyImport, skipNodeModulesBundle, resolveDepSubpath: shouldResolveDepSubpath, dts }, logger, nameLabel, platform }: ResolvedConfig, tsdownBundle: TsdownBundle): Plugin
  • removed: function _<T>(moduleName: string): Promise<T>
  • removed: function x(config: ResolvedConfig, cjsDts?: boolean, isDualFormat?: boolean): Plugin
  • removed: interface F
  • removed: interface K extends Pick<DepsConfig, 'neverBundle' | 'skipNodeModulesBundle' | 'resolveDepSubpath'>
  • removed: interface M
  • removed: interface S<A = any> extends Plugin<A>
  • removed: interface V
  • removed: interface X extends AsyncDisposable
  • removed: interface b
  • removed: interface h
  • removed: interface k
  • removed: interface n extends Options$1
  • removed: interface w extends Omit<Options, 'pack' | 'pkgDir'>
  • removed: property A.format: NormalizedFormat
  • removed: property A.options: InputOptions
  • removed: property A.pkgType?: PackageType
  • removed: property E.ignoreRules?: ('no-resolution' | 'untyped-resolution' | 'false-cjs' | 'false-esm' | 'cjs-resolves-to-esm' | 'fallback-condition' | 'cjs-only-exports-default' | 'named-exports' | 'false-export-default' | 'missing-export-equals' | 'unexpected-module-syntax' | 'internal-resolution-error' | (string & {}))[]
  • removed: property E.level?: 'error' | 'warn'
  • removed: property E.module?: typeof import('@arethetypeswrong/core')
  • removed: property E.profile?: 'strict' | 'node16' | 'esm-only'
  • removed: property F.hooks: Hookable<TsdownHooks>
  • removed: property F.options: ResolvedConfig
  • removed: property H.clean?: boolean
  • removed: property H.ui?: boolean | Partial<StartOptions>
  • removed: property I.buildOptions: BuildOptions
  • removed: property K.alwaysBundle?: NoExternalFn
  • removed: property K.dts: Pick<ResolvedDepsConfig, 'alwaysBundle' | 'neverBundle'>
  • removed: property K.onlyBundle?: Array<string | RegExp> | false
  • removed: property K.onlyImport?: Array<string | RegExp>
  • removed: property L.'build:before': (ctx: BuildContext & RolldownContext) => void | Promise<void>
  • removed: property L.'build:done': (ctx: BuildContext & { chunks: RolldownChunk[] }) => void | Promise<void>
  • removed: property L.'build:prepare': (ctx: BuildContext) => void | Promise<void>
  • removed: property M.dts?: string
  • removed: property M.js?: string
  • removed: property N.packageJsonPath: string
  • removed: property R.fileName?: string | ((chunk: RolldownChunk) => string)
  • removed: property R.outDir?: string
  • removed: property R.seaConfig?: Omit<SeaConfig, 'main' | 'output' | 'mainFormat'>
  • removed: property S.tsdownConfig?: (config: UserConfig, inlineConfig: InlineConfig) => Awaitable<UserConfig | void | null>
  • removed: property S.tsdownConfigResolved?: (resolvedConfig: ResolvedConfig) => Awaitable<void>
  • removed: property T.all?: boolean
  • removed: property T.bin?: boolean | string | Record<string, string>
  • removed: property T.customExports?: Record<string, any> | ((exports: Record<string, any>, context: { pkg: PackageJson; chunks: ChunksByFormat; isPublish: boolean }) => Awaitable<Record<string, any>>)
  • removed: property T.devExports?: boolean | string
  • removed: property T.exclude?: (RegExp | string)[]
  • removed: property T.extensions?: boolean
  • removed: property T.inlinedDependencies?: boolean
  • removed: property T.legacy?: boolean
  • removed: property T.packageJson?: boolean
  • removed: property U.alwaysBundle?: Arrayable<string | RegExp> | NoExternalFn
  • removed: property U.dts?: Pick<DepsConfig, 'alwaysBundle' | 'neverBundle'>
  • removed: property U.neverBundle?: true | ExternalOption
  • removed: property U.onlyAllowBundle?: Arrayable<string | RegExp> | false
  • removed: property U.onlyBundle?: Arrayable<string | RegExp> | false
  • removed: property U.onlyImport?: Arrayable<string | RegExp>
  • removed: property U.resolveDepSubpath?: boolean
  • removed: property U.skipNodeModulesBundle?: boolean
  • removed: property V.assets?: Record<string, string>
  • removed: property V.disableExperimentalSEAWarning?: boolean
  • removed: property V.execArgv?: string[]
  • removed: property V.execArgvExtension?: 'none' | 'env' | 'cli'
  • removed: property V.executable?: string
  • removed: property V.main?: string
  • removed: property V.mainFormat?: 'commonjs' | 'module'
  • removed: property V.output?: string
  • removed: property V.useCodeCache?: boolean
  • removed: property V.useSnapshot?: boolean
  • removed: property X.chunks: RolldownChunk[]
  • removed: property X.config: ResolvedConfig
  • removed: property X.inlinedDeps: Map<string, Set<string>>
  • removed: property Z.flatten?: boolean
  • removed: property Z.from: string | string[]
  • removed: property Z.rename?: string | ((name: string, extension: string, fullPath: string) => string)
  • removed: property Z.to?: string
  • removed: property Z.verbose?: boolean
  • removed: property b.brotli?: boolean
  • removed: property b.gzip?: boolean
  • removed: property b.maxCompressSize?: number
  • removed: property d.bundle?: boolean
  • removed: property d.injectStyle?: boolean
  • removed: property d.inlineOnly?: Arrayable<string | RegExp> | false
  • removed: property d.outExtension?: OutExtensionFactory
  • removed: property d.publicDir?: CopyOptions | CopyOptionsFn
  • removed: property d.removeNodeProtocol?: boolean
  • removed: property d.skipNodeModulesBundle?: boolean
  • removed: property h.config?: boolean | string
  • removed: property h.exclude?: Arrayable<string>
  • removed: property h.include?: 'auto' | (string & {}) | string[]
  • removed: property k.css?: string
  • removed: property k.dts?: string
  • removed: property k.js?: string
  • removed: property n.cjsReexport?: boolean
  • removed: property q.clearScreen: (type: LogType) => void
  • removed: property q.error: (...args: any[]) => void
  • removed: property q.info: (...args: any[]) => void
  • removed: property q.level: LogLevel
  • removed: property q.options?: LoggerOptions
  • removed: property q.success: (...args: any[]) => void
  • removed: property q.warn: (...args: any[]) => void
  • removed: property q.warnOnce: (...args: any[]) => void
  • removed: property w.module?: [typeof import('publint'), typeof import('publint/utils')]
  • removed: type $ = (options: ResolvedConfig) => Awaitable<CopyOptions>
  • removed: type C<A = any> = Awaitable<TsdownPlugin<A> | RolldownPlugin<A> | { name: string } | undefined | null | void | false | TsdownPluginOption<A>[]>
  • removed: type D = ChunkAddonObject | ChunkAddonFunction | string
  • removed: type G = (id: string, importer: string | undefined) => boolean | null | undefined | void
  • removed: type P = 'module' | 'commonjs' | undefined
  • removed: type Q = Arrayable<string | CopyEntry>
  • removed: type Y = (OutputChunk | OutputAsset) & { outDir: string }
  • removed: type g = <T>(task: () => Promise<T>) => Promise<T>
  • removed: type j = (context: OutExtensionContext) => OutExtensionObject | undefined
  • removed: type m<T> = boolean | undefined | CIOption | (T & { enabled?: boolean | CIOption })
  • changed: const B: SemVer → const B: string
  • changed: function v<T extends string>(arr: T[]): T[] → function v<T>(moduleName: string): Promise<T>
  • changed: function y<T>(val: T | T[] | null | undefined, defaultValue?: T): T[] → function y<T extends string>(arr: T[]): T[]
  • changed: interface E extends CheckPackageOptions → interface E
  • changed: interface H extends NonNullable<InputOptions['devtools']> → interface H
  • changed: interface N extends PackageJson → interface N
  • changed: interface R extends ExeExtensionOptions → interface R
  • changed: interface T → interface T extends Omit<Options, 'pack' | 'pkgDir'>
  • changed: interface U → interface U extends NonNullable<InputOptions['devtools']>
  • changed: interface Z → interface Z extends AsyncDisposable
  • changed: interface q → interface q extends Pick<DepsConfig, 'neverBundle' | 'resolveDepSubpath'>
  • changed: property d.envFile?: string → property d.envFile?: string | string[]
  • changed: type O = (ctx: { format: Format; fileName: string }) => ChunkAddonObject | string | undefined → type O = ChunkAddonObject | ChunkAddonFunction | string
  • changed: type et<T> = T | T[] → type et = Arrayable<string | CopyEntry>
  • changed: type nt<T, U> = Omit<T, keyof U> & U → type nt<T> = T | T[]
  • changed: type o = Overwrite<MarkPartial<Omit<UserConfig, 'workspace' | 'fromVite' | 'publicDir' | 'bundle' | 'injectStyle' | 'removeNodeProtocol' | 'outExtension' | 'external' |… → type o = Overwrite<MarkPartial<Omit<UserConfig, 'workspace' | 'fromVite' | 'external' | 'noExternal' | 'logLevel' | 'failOnWarn' | 'suppressWarnings' | 'customLogger' |…
  • changed: type p = (inlineConfig: InlineConfig, context: { ci: boolean; rootConfig?: UserConfig }) => Awaitable<Arrayable<UserConfig>> → type p = (inlineConfig: InlineConfig, context: UserConfigFnContext) => Awaitable<Arrayable<UserConfig>>
  • changed: type tt<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>> → type tt = (options: ResolvedConfig) => Awaitable<CopyOptions>
  • added: const V: SemVer
  • added: const Y: Logger
  • added: export { DtsOptions as n }
  • added: function G({ pkg, deps: { neverBundle, alwaysBundle: jsAlwaysBundle, onlyBundle, onlyImport, resolveDepSubpath: shouldResolveDepSubpath, dts }, logger, nameLabel, platform }: ResolvedConfig, tsdownBundle: TsdownBundle): Plugin
  • added: function S(config: ResolvedConfig, cjsDts?: boolean, isDualFormat?: boolean): Plugin
  • added: function b<T>(val: T | T[] | null | undefined, defaultValue?: T): T[]
  • added: interface $
  • added: interface C<A = any> extends Plugin<A>
  • added: interface D extends CheckPackageOptions
  • added: interface J
  • added: interface P extends PackageJson
  • added: interface Q
  • added: interface W
  • added: interface g
  • added: interface j
  • added: interface m
  • added: interface x
  • added: interface z extends ExeExtensionOptions
  • added: property $.flatten?: boolean
  • added: property $.from: string | string[]
  • added: property $.rename?: string | ((name: string, extension: string, fullPath: string) => string)
  • added: property $.to?: string
  • added: property $.verbose?: boolean
  • added: property A.css?: string
  • added: property A.dts?: string
  • added: property A.js?: string
  • added: property C.tsdownConfig?: (config: UserConfig, inlineConfig: InlineConfig) => Awaitable<UserConfig | void | null>
  • added: property C.tsdownConfigResolved?: (resolvedConfig: ResolvedConfig) => Awaitable<void>
  • added: property D.ignoreRules?: ('no-resolution' | 'untyped-resolution' | 'false-cjs' | 'false-esm' | 'cjs-resolves-to-esm' | 'fallback-condition' | 'cjs-only-exports-default' | 'named-exports' | 'false-export-default' | 'missing-export-equals' | 'unexpected-module-syntax' | 'internal-resolution-error' | (string & {}))[]
  • added: property D.level?: 'error' | 'warn'
  • added: property D.module?: typeof import('@arethetypeswrong/core')
  • added: property D.profile?: 'strict' | 'node16' | 'esm-only'
  • added: property E.all?: boolean
  • added: property E.bin?: boolean | string | Record<string, string>
  • added: property E.customExports?: Record<string, any> | ((exports: Record<string, any>, context: { pkg: PackageJson; chunks: ChunksByFormat; isPublish: boolean }) => Awaitable<Record<string, any>>)
  • added: property E.devExports?: boolean | string
  • added: property E.exclude?: (RegExp | string)[]
  • added: property E.extensions?: boolean
  • added: property E.inlinedDependencies?: boolean
  • added: property E.legacy?: boolean
  • added: property E.packageJson?: boolean
  • added: property H.assets?: Record<string, string>
  • added: property H.disableExperimentalSEAWarning?: boolean
  • added: property H.execArgv?: string[]
  • added: property H.execArgvExtension?: 'none' | 'env' | 'cli'
  • added: property H.executable?: string
  • added: property H.main?: string
  • added: property H.mainFormat?: 'commonjs' | 'module'
  • added: property H.output?: string
  • added: property H.useCodeCache?: boolean
  • added: property H.useSnapshot?: boolean
  • added: property I.hooks: Hookable<TsdownHooks>
  • added: property I.options: ResolvedConfig
  • added: property J.clearScreen: (type: LogType) => void
  • added: property J.error: (...args: any[]) => void
  • added: property J.info: (...args: any[]) => void
  • added: property J.level: LogLevel
  • added: property J.options?: LoggerOptions
  • added: property J.success: (...args: any[]) => void
  • added: property J.warn: (...args: any[]) => void
  • added: property J.warnOnce: (...args: any[]) => void
  • added: property L.buildOptions: BuildOptions
  • added: property N.dts?: string
  • added: property N.js?: string
  • added: property P.packageJsonPath: string
  • added: property Q.bundles: TsdownBundle[]
  • added: property Q.watch: { restart: () => Promise<TsdownHandle>; close: () => Promise<void> }
  • added: property R.'build:before': (ctx: BuildContext & RolldownContext) => void | Promise<void>
  • added: property R.'build:done': (ctx: BuildContext & { chunks: RolldownChunk[] }) => void | Promise<void>
  • added: property R.'build:prepare': (ctx: BuildContext) => void | Promise<void>
  • added: property T.module?: [typeof import('publint'), typeof import('publint/utils')]
  • added: property U.clean?: boolean
  • added: property U.ui?: boolean | Partial<StartOptions>
  • added: property W.alwaysBundle?: Arrayable<string | RegExp> | NoExternalFn
  • added: property W.dts?: Pick<DepsConfig, 'alwaysBundle' | 'neverBundle'>
  • added: property W.neverBundle?: true | ExternalOption
  • added: property W.onlyBundle?: Arrayable<string | RegExp> | false
  • added: property W.onlyImport?: Arrayable<string | RegExp>
  • added: property W.resolveDepSubpath?: boolean
  • added: property Z.chunks: RolldownChunk[]
  • added: property Z.config: ResolvedConfig
  • added: property Z.inlinedDeps: Map<string, Set<string>>
  • added: property g.config?: boolean | string
  • added: property g.exclude?: Arrayable<string>
  • added: property g.include?: 'auto' | (string & {}) | string[]
  • added: property j.format: NormalizedFormat
  • added: property j.options: InputOptions
  • added: property j.pkgType?: PackageType
  • added: property m.ci: boolean
  • added: property m.rootConfig?: UserConfig
  • added: property m.watch: TsdownHandle['watch']
  • added: property q.alwaysBundle?: NoExternalFn
  • added: property q.dts: Pick<ResolvedDepsConfig, 'alwaysBundle' | 'neverBundle'>
  • added: property q.onlyBundle?: Array<string | RegExp> | false
  • added: property q.onlyImport?: Array<string | RegExp>
  • added: property x.brotli?: boolean
  • added: property x.gzip?: boolean
  • added: property x.maxCompressSize?: number
  • added: property x.summary?: boolean
  • added: property z.fileName?: string | ((chunk: RolldownChunk) => string)
  • added: property z.outDir?: string
  • added: property z.seaConfig?: Omit<SeaConfig, 'main' | 'output' | 'mainFormat'>
  • added: type F = 'module' | 'commonjs' | undefined
  • added: type K = (id: string, importer: string | undefined) => boolean | null | undefined | void
  • added: type M = (context: OutExtensionContext) => OutExtensionObject | undefined
  • added: type X = (OutputChunk | OutputAsset) & { outDir: string }
  • added: type _ = <T>(task: () => Promise<T>) => Promise<T>
  • added: type h<T> = boolean | undefined | CIOption | (T & { enabled?: boolean | CIOption })
  • added: type it<T, U> = Omit<T, keyof U> & U
  • added: type k = (ctx: { format: Format; fileName: string }) => ChunkAddonObject | string | undefined
  • added: type rt<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>
  • added: type u = import('unplugin-unused').Options
  • added: type w<A = any> = Awaitable<TsdownPlugin<A> | RolldownPlugin<A> | { name: string } | undefined | null | void | false | TsdownPluginOption<A>[]>