Skip to content

feat: use tsdown for bundling#759

Merged
kettanaito merged 10 commits intomainfrom
chore/use-tsdown
Feb 3, 2026
Merged

feat: use tsdown for bundling#759
kettanaito merged 10 commits intomainfrom
chore/use-tsdown

Conversation

@kettanaito
Copy link
Copy Markdown
Member

@kettanaito kettanaito commented Dec 19, 2025

  • Use tsdown for bundling.
  • Update exports, including at the nested paths, like /presets.
  • Drop alias from tsdown config as it resolves aliases from tsconfig instead.
  • Add a new tsconfig.browser.json to resolve the internal:brotli-compress correctly during the build.
  • Removes explicit types from export extensions to rely on implicit dts lookup.

Motivation

  • Trusted publishing (chore: enable trusted publishing #758) needs the new version of ossjs/release.
  • The new version of ossjs/release uses publint for package linting.
  • Publint complains on incorrect CJS/MJS type definition files mixing (actual issue).
  • tsup doesn't produce different .d.ts for different formats, but tsdown does.

@Stanzilla
Copy link
Copy Markdown
Contributor

@kettanaito I can help with this, if you want?

@kettanaito
Copy link
Copy Markdown
Member Author

@Stanzilla, absolutely! Any help would be appreciated, especially if we can keep the changes to the minimum here.

@kettanaito kettanaito marked this pull request as ready for review February 3, 2026 16:19
@kettanaito kettanaito changed the title chore: use tsdown chore: use tsdown for bundling Feb 3, 2026
@Stanzilla
Copy link
Copy Markdown
Contributor

Hey! I noticed a couple of typos in tsconfig.browser.json that might cause build issues:

  1. Line 2: "extend" should be "extends"

    - "extend": "./tsconfig.json",
    + "extends": "./tsconfig.json",
  2. Line 9: "baseUrl:" has an errant colon - should be "baseUrl"

    - "baseUrl:": ".",
    + "baseUrl": ".",

Also worth double-checking: in tsdown.config.mts line 33, the browser target is set to 'chrome190' - Chrome 190 doesn't exist yet (current stable is around 130). Was this meant to be 'chrome90' or similar?

@kettanaito
Copy link
Copy Markdown
Member Author

Thanks, @Stanzilla, good finds! Meanwhile, I solve the e2e tests so the builds are passing.

@kettanaito
Copy link
Copy Markdown
Member Author

kettanaito commented Feb 3, 2026

Failing Nock tests

  1) Native Fetch
       should return a url for cloned response URL :

      AssertionError: expected '' to equal 'http://example.test/'
      + expected - actual

      +http://example.test/

      at Context.<anonymous> (tests/test_fetch.js:173:37)
      at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

A single test is failing, which is related to Node.js v24, somehow. On v24, the same scenario on our end is failing also, likely related to #762 (breaking changes in Node.js). Weird, since our compat/nock job uses Node.js v20.

It's worth mentioning that the actual failure reason on the CI is obscure, highly suggesting that the Nock repo can no longer be run on Node.js v20. But not what's claimed in engines.

Update: the mistake is on our end, it just doesn't surface nicely:

const {
  default: nodeInterceptors,
} = require('@mswjs/interceptors/presets/node')
const SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n'
let recordingInProgress = false
let outputs = []

// TODO: don't reuse the nodeInterceptors, create new ones.
const clientRequestInterceptor = nodeInterceptors[0]

Here, nodeInterceptors[0] throws because nodeInterceptors is undefined.

Update: Nope, we export things correctly. What a wild ride. The issue was that only one export condition of presets/node had incorrect file extension in our export conditions.

Root cause

tsdown started skipping .cjs extension because of type: commonjs in package.json. That broke some export conditions we had that were expecting .cjs.

Solution

Ensured consistent .cjs and .mjs extensions for all built modules.

@kettanaito
Copy link
Copy Markdown
Member Author

/presets/node no longer exports default

export default [
  new ClientRequestInterceptor(),
  new XMLHttpRequestInterceptor(),
  new FetchInterceptor(),
] as const

This code no longer produces a named default export as it did with tsup. Rightfully, the way Nock gets the default value breaks:

https://github.com/nock/nock/blob/e7418da29feb4a7bf0aa1612bfb9d32a4051651e/lib/recorder.js#L10-L12

This can be fixed on Nock's side by rewriting the require to:

const nodeInterceptors = require('@mswjs/interceptors/presets/node') 

@kettanaito
Copy link
Copy Markdown
Member Author

Opened a pull request to Nock to see if dropping that require alias would not be an issue: nock/nock#2938.

@kettanaito
Copy link
Copy Markdown
Member Author

I've confirmed that the Nock changes are valid against this version of Interceptors and their entire test suite is passing. This has to be released with a broken Nock compatibility until I bump the Interceptors version in Nock.

@kettanaito kettanaito changed the title chore: use tsdown for bundling feat: use tsdown for bundling Feb 3, 2026
@kettanaito kettanaito merged commit b3091b5 into main Feb 3, 2026
2 of 3 checks passed
@kettanaito kettanaito deleted the chore/use-tsdown branch February 3, 2026 20:21
@kettanaito
Copy link
Copy Markdown
Member Author

Released: v0.41.0 🎉

This has been released in v0.41.0.

Get these changes by running the following command:

npm i @mswjs/interceptors@latest

Predictable release automation by Release.

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