Repository navigation
Export a Plugin type for the plugin API - #408
Conversation
The plugin contract was untyped, so every third-party plugin had to re-declare it, and the first-party plugins shipped no types at all. Add `Plugin`, `PluginHook`, `PluginStep`, `PluginConfig` and `PluginCheck` to `size-limit` and type the `plugins` argument of the JS API with them. Steps are typed for every number `calc()` runs, `0` to `100`, not only the ones used by the plugins in this repository. Ship a declaration file and a `types` field for every plugin package, so `@size-limit/*` imports are typed without a local shim. `TimeOptions.latency` is optional: a check can set only `networkSpeed`, which `fixtures/time-network-speed` already does. Closes ai#407
When a package has an `exports` map, the `types` condition is what modern TypeScript resolution reads, and it is what arethetypeswrong checks. The declarations sit next to `index.js`, so the ESM-only packages do not need the top-level field either: the node10 column stays green through the root `index.d.ts`. Checked on the packed tarballs with arethetypeswrong: node10, node16 (from ESM), node16 (from CJS) and bundler all resolve the declarations; the CJS row keeps its pre-existing ESM-only warning, which no types declaration can remove.
|
Thanks. Can you check that everything is ok using github version? Do you need release of types? |
|
Verified against the GitHub version, in
What a consumer has to change: the type names ( Two things I ran into while porting, in case you prefer them in this PR rather than separately:
On the release: the shim can only be deleted for published consumers once the types are out, so a release would be welcome — but the check above ran against this branch, so nothing here is blocked on it. |
Closes #407.
The plugin contract was untyped: every third-party plugin had to re-declare it (for example
size-limit-node-esbuildships ashim.d.ts), and the first-party plugin packages shipped no types at all.Core types
size-limitnow exports:Plugin— the plugin object:name,before,finally, and everystep<N>/wait<N>hook.PluginHook— the(config, check)signature the hooks are called with.PluginStep— the step numberscalc()runs. It callsstep0…step100for every plugin, so all of them are typed, not only the numbers the plugins in this repository happen to use.PluginConfig— the run configuration the hooks receive.PluginCheck— the check afterget-config.jsnormalized it, together with the fields the plugins which ran before have added (bundles,size,esbuildConfig,webpackConfig,loadTime, …).The
pluginsargument of the JS API is typed with them too.Every package ships its own types
All thirteen packages,
size-limitincluded, declare the declarations inexports—"types"before"default"— and ship anindex.d.tsnext toindex.js, soimport esbuildPlugin from '@size-limit/esbuild'is typed without a local shim. Thetypescondition is what resolution reads when a package has anexportsmap, andsize-limititself was the only package with a top-leveltypesfield before; that field is gone, since the declarations sit next to the entry and these packages require Node 22+ anyway.That is what makes the
shim.d.tsinsize-limit-node-esbuild(and the equivalents needed by@size-limit/esbuild/@size-limit/file) unnecessary.One fix
TimeOptions.latencyis optional now:get-config.jsonly normalizes it when it is set, andfixtures/time-network-speedalready configurestimewithout it.Verification
oxlintis clean, and the core package's tests pass (vitest run packages/size-limit/test: 148 tests).tsc --strictagainst a scratch file covering a plugin written by hand, everystep/waitname, astepoutside0…100and a missingnamebeing rejected, extendingPlugin, importing every plugin package, and calling the JS API — under bothnodenextandbundlerresolution.arethetypeswrong: node10, node16 (from ESM), node16 (from CJS) and bundler all resolve the declarations. The only warning left is the pre-existing “arequirecall resolved to an ESM JavaScript file”, which these ESM-only packages cannot avoid without a dual build.vitest runon the whole repository: 268 of 269 tests pass on the machine I used.packages/time/test/get-running-time.test.jsfails there because it has no Chrome, and it fails the same way on a cleanmain, so it is unrelated to this change.