Skip to content

chore(infra) - migrate to typescript v7 && tsdown - #1325

Merged
gabrielseco merged 14 commits into
mainfrom
spike/tsdown-migration
Sep 18, 2026
Merged

gabrielseco merged 14 commits into
mainfrom
spike/tsdown-migration

Conversation

@gabrielseco

@gabrielseco gabrielseco commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Spike, not a finished migration — opened as draft to get real size-check numbers from CI, per this investigation: tsup vendors rollup-plugin-dts@6.1.1 internally and crashes on TypeScript 7's dts build; there's been no tsup release since Nov 2025 to pick up the fix. tsdown (tsup's own recommended successor) builds and type-checks cleanly against typescript@7.0.2.

  • npm run build (tsdown) → clean against typescript@7.0.2
  • npm run type-check → 0 errors
  • npm run check-exports (attw) → all green
  • typescript@7.0.2 itself ships the native (Go-ported) compiler by default now (platform binary via optionalDependencies, e.g. @typescript/typescript-darwin-arm64) — no separate tsgo/@typescript/native-preview install needed, tsc already is the native binary.
  • external/noExternal config from tsup.config.ts (external: ['react', 'react-dom'], noExternal: ['react-hook-form', '@hookform/resolvers']) carried over unchanged to tsdown.config.ts — same option semantics in rolldown, verified working via the green check-exports run.

size-check CI results (real numbers from this branch)

  • Total (gzip): 163.68 kB / 350 kB — -42.1% vs main's 282.51 kB
  • Total (raw): 544.65 kB / 850 kB — -27.0% vs main's 745.97 kB
  • CSS (gzip): 21.91 kB / 25 kB (~flat vs main)

Two chunks (CheckBoxField-CNRUimYw.js, ContractorOnboarding-BMNuPI6T.js) initially exceeded the old fixed 50 kB/15 kB per-chunk caps despite the large overall size win — rolldown (tsdown's bundler) consolidates shared code into fewer, larger chunks than esbuild (tsup's bundler) did, so a fixed per-chunk ceiling that made sense under the old chunking strategy doesn't directly carry over. Bumped .sizelimit.json's maxChunkSize/maxChunkSizeGzip from 50 kB/15 kB to 100 kB/30 kB (headroom above the current largest chunk at 78.93 kB/24.52 kB) — size:check passes clean now.

Known gaps (not blocking this CI check, but blocking a real merge)

  • No tsdown equivalent to tsup's keepNames (prevents the minifier renaming functions/classes) — dropped, needs a manual check for anywhere relying on Function.name/displayName post-minification.
  • styles.css is produced via a hand-rolled onSuccess file copy of the deduped index.css (verified byte-identical to tsup's own output except the sourcemap comment), not a native per-entry CSS output — tsdown's CSS pipeline dedupes identical CSS across entries by default.
  • tsup is still listed in package.json/lockfile — left in place since this is a spike, not a cutover.
  • size-check.yml's path filters list tsup.config.ts but not tsdown.config.ts — would need updating for a real migration so the workflow still triggers on build-config-only changes.
  • The new maxChunkSize/maxChunkSizeGzip values are a first pass sized to current output, not a deliberately-chosen budget — worth revisiting once the chunking strategy settles for a real migration.
  • package.json's overrides pinning @remoteoss/json-schema-form-v0-deprecated to a dev build (0.12.5-dev.20260916142420) is temporary, for testing an unrelated json-schema-form fix against this build pipeline — should be reverted before this spike is merged, it isn't part of the tsdown migration itself.

Test plan

  • Confirm size-check CI job runs and compare its numbers against main's current bundle sizes
  • Full test suite (npm test) unaffected — not yet run in this spike, build-tool swap is orthogonal to vitest but should be checked
  • size:check locally against .sizelimit.json thresholds

🤖 Generated with Claude Code


Note

Medium Risk
Swapping the publish build pipeline and TypeScript major version can change bundle shape, minification, and types consumers see; chunk limits were relaxed rather than re-tuned to a new chunking strategy.

Overview
Replaces tsup with tsdown (Rolldown-based) for library builds and bumps TypeScript to 7.0.2, driven by tsup’s broken dts path on TS 7. Root build/dev scripts now run tsdown with the unrun config loader; bundling rules from the old setup are preserved in tsdown.config.ts (react/react-dom external, react-hook-form + @hookform/resolvers bundled, multi-entry ESM, PostCSS/Tailwind CSS with a post-build copy so styles.css mirrors deduped index.css).

CI and docs are aligned with the new config: bundle workflows watch tsdown.config.ts instead of tsup.config.ts, and contributor docs/Cursor env describe tsdown watch builds. .sizelimit.json raises per-chunk caps (maxChunkSize 50→100 kB, gzip 15→30 kB) so size-check passes under tsdown’s larger chunk consolidation while overall bundle size reportedly drops vs main. The example app lockfile picks up TS 7.0.2 and refreshed parent-package dev deps (@tsdown/css, postcss-import, unrun, @remoteoss/remote-json-schema-form-kit 1.1.1).

Reviewed by Cursor Bugbot for commit 3f9fce1. Bugbot is set up for automated code reviews on this repo. Configure here.

tsup vendors rollup-plugin-dts@6.1.1 internally and crashes on TS7's
dts build; there's been no tsup release to pick up the fix since
Nov 2025. tsdown (rolldown-based, tsup's own recommended successor)
builds and type-checks cleanly against typescript@7.0.2.

Translating tsup.config.ts required:
- @tsdown/css + postcss-import + explicit css.transformer: 'postcss'
  (the default lightningcss transformer silently drops @apply)
- outExtensions forced to .js/.d.ts (tsdown defaults to .mjs/.d.mts,
  which breaks every package.json exports path)
- --config-loader unrun so the config's extensionless import satisfies
  both tsdown's loader and tsc's import-extension rules
- src/flows/*/index.ts as bundled per-flow entries (tsup's directory-
  entry shorthand isn't supported) — restores single-file noExternal
  inlining and per-entry CSS naming that unbundle mode broke
- onSuccess hook mirrors the deduped index.css to styles.css (verified
  byte-identical to tsup's output except the sourcemap comment)

Known gaps: no tsdown equivalent to tsup's `keepNames`; tsup itself
is left in package.json/lockfile for now since this is a size/CI
spike, not a finished migration.
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Metric Current Previous Change Status
Total (gzip) 165.16 kB 283.42 kB -118.27 kB (-41.7%) 🟢
Total (raw) 550.29 kB 751.96 kB -201.67 kB (-26.8%) 🟢
CSS (gzip) 21.91 kB 21.93 kB -22 B (-0.1%) 🟢
CSS (raw) 114.38 kB 113.97 kB +411 B (+0.4%) 🔴

Size Limits

  • ✅ Total gzipped: 165.16 kB / 350 kB (47.2%)
  • ✅ Total raw: 550.29 kB / 850 kB (64.7%)
  • ✅ CSS gzipped: 21.91 kB / 25 kB (87.6%)

Largest Files (Top 5)

  1. CheckBoxField-DSq9Qf8u.js - 19.38 kB (new)
  2. ContractorOnboarding-QSgRChZR.js - 14.69 kB (new)
  3. Onboarding-axVT9XVh.js - 11.26 kB (new)
  4. Termination-sjnHMs8m.js - 11.09 kB (new)
  5. styles.css - 10.96 kB (-11 B (-0.1%))
View All Files (74 total)
File Size (gzip) Change
CheckBoxField-DSq9Qf8u.js 19.38 kB new
ContractorOnboarding-QSgRChZR.js 14.69 kB new
Onboarding-axVT9XVh.js 11.26 kB new
Termination-sjnHMs8m.js 11.09 kB new
styles.css 10.96 kB -11 B (-0.1%)
index.css 10.96 kB -11 B (-0.1%)
CostCalculator-CoUCw59l.js 10.7 kB new
internals-CzDL30xI.js 8.25 kB new
sdk.gen-C7MLoCMc.js 5.55 kB new
JSONSchemaForm-DehMm5lM.js 5.03 kB new

✅ Bundle size check passed

@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

📊 Coverage Report

⚪ Coverage unchanged

Metric Current Previous Change Status
Lines 86.19% 86.19% 0% ⚪
Statements 85.77% 85.77% 0% ⚪
Functions 84.73% 84.73% 0% ⚪
Branches 77.66% 77.66% 0% ⚪

Detailed Breakdown

Lines Coverage
  • Covered: 4780 / 5546
  • Coverage: 86.19%
  • Change: 0% (0 lines)
Statements Coverage
  • Covered: 4864 / 5671
  • Coverage: 85.77%
  • Change: 0% (0 statements)
Functions Coverage
  • Covered: 1276 / 1506
  • Coverage: 84.73%
  • Change: 0% (0 functions)
Branches Coverage
  • Covered: 2962 / 3814
  • Coverage: 77.66%
  • Change: 0% (0 branches)

✅ Coverage check passed

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for adp-cost-calculator ready!

Project:adp-cost-calculator
Status: ✅  Deploy successful!
Preview URL:https://adp-cost-calculator-af6x7hnk0-remotecom.vercel.app
Latest Commit:3f9fce1

Deployed with vercel-action

@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for remote-flows ready!

Project:remote-flows
Status: ✅  Deploy successful!
Preview URL:https://remote-flows-28idcd10t-remotecom.vercel.app
Latest Commit:3f9fce1

Deployed with vercel-action

rolldown (tsdown's bundler) consolidates shared code into fewer, larger
chunks than tsup/esbuild did. Total bundle size dropped 42% gzipped in
this migration, but two chunks (CheckBoxField, ContractorOnboarding)
now exceed the old fixed 50kB/15kB per-chunk caps. Bumped to 100kB/30kB
with headroom above current sizes (78.93kB/24.52kB largest).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@gabrielseco gabrielseco changed the title spike: tsup -> tsdown for TypeScript 7 support chore(infra) - migrate to typescript v7 && tsdown Sep 16, 2026
@gabrielseco
gabrielseco marked this pull request as ready for review September 16, 2026 14:47

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread tsdown.config.ts Resolved

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6022f28. Configure here.

Comment thread package.json Resolved
@gabrielseco
gabrielseco merged commit 0c1e24e into main Sep 18, 2026
15 checks passed
@gabrielseco
gabrielseco deleted the spike/tsdown-migration branch September 18, 2026 16:21
gabrielseco added a commit that referenced this pull request Sep 21, 2026
Renovate's lockfile-only install (used for most dependency bumps)
never populates node_modules/.bin, so the repo's `prepare` script
(`npm run build` -> tsdown) fails with "tsdown: command not found",
aborting the whole update. Renovate then commits only the
package.json bump without a matching package-lock.json, which
breaks `npm ci` in CI for every subsequent PR check.

This previously went unnoticed because Renovate reuses a cached
node_modules across runs, and a working tsup binary was already
present from earlier installs. The tsup -> tsdown migration (#1325)
reset that cache, and the next two dependency PRs (#1339, #1340)
hit the bug for the first time.

ignoreScripts tells Renovate to skip lifecycle scripts during its
own lockfile computation. It has no effect on real CI or local
installs, which still run prepare/build as normal.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
gabrielseco added a commit that referenced this pull request Sep 24, 2026
#1368)

* ci: smoke-test that npm run openapi-ts still works on dependency bumps

Nothing in CI actually exercises the openapi-ts codegen path today, so a
dependency bump that breaks it (e.g. the typescript 6->7 migration in
#1325, which broke @hey-api/openapi-ts's peer-dependency compatibility —
see #1367) only surfaces when someone manually regenerates the client.

Runs on any PR touching package.json/package-lock.json rather than just
@hey-api/openapi-ts's own line, since the actual trigger can be any
dependency in that graph. Only fails on a nonzero exit (the generator
crashing) — deliberately does not diff the regenerated output against
what's committed, since the production schema drifts independently of
any given PR and a diff there isn't itself a failure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* ci: drop comment from openapi codegen smoke-test workflow

Rationale belongs in the PR description, not a multi-line comment block.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
gabrielseco added a commit that referenced this pull request Sep 30, 2026
* fix(build): restore per-file ./flows/* subpath modules

The tsdown migration (#1325) only built each flow's index.ts, so
dist/flows went from 192 modules in 1.55.0 to 11 in 1.56.0 and
partner imports like flows/CostCalculator/api stopped resolving.
Build every non-test flow file again, matching the old tsup entry,
and fail check-exports if any flow module is missing from the tarball.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(build): surface npm pack errors in flow subpath check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(build): import partner-reported flow subpaths

Resolve the three subpaths partners reported through the package
exports map and assert their exports, so a regression surfaces as
the same error partners would hit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix exports and mark some as deprecated

* chore(editor): enable type-aware oxc in editor

Share .vscode/settings.json so the oxc extension runs type-aware rules
(e.g. typescript/no-deprecated) like `npm run lint --type-aware` does,
and recommend the oxc extension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix import

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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