[WXT Modules] Automatically add build and runtime options without manual module augmentation
@aklinker1 is already working on this.
Since Apr 28, 2025.
- Dominant language
- TypeScript
- Stars
- 10.5k
- Forks
- 564
- PR merge metrics
- No merged PRs in 30d
Description
I attempted to set this up, but ran into an error as soon as I tried building a WXT module that adds types to the WXT config.
$ pnpm tsdown ℹ tsdown v0.10.0 powered by rolldown v1.0.0-beta.8-commit.151352b tsdown 6:04:57 PM [tsdown 6:04:57 PM] ℹ Using tsdown config: /Users/aklinker1/Development/github.com/wxt-dev/wxt/packages/analytics/tsdown.config.ts [tsdown 6:04:57 PM] ℹ entry: modules/analytics/index.ts, modules/analytics/client.ts, modules/analytics/background-plugin.ts, modules/analytics/types.ts, modules/analytics/providers/google-analytics-4.ts, modules/analytics/providers/umami.ts ℹ Using tsconfig: tsconfig.json tsdown 6:04:57 PM ℹ [ESM] Build start tsdown 6:04:57 PM FATAL Build failed with 2 errors: tsdown 6:04:58 PM [UNRESOLVED_IMPORT] Error: Could not resolve '../pkg' in ../../node_modules/.pnpm/lightningcss@1.29.3/node_modules/lightningcss/node/index.js ╭─[ ../../node_modules/.pnpm/lightningcss@1.29.3/node_modules/lightningcss/node/index.js:17:28 ] │ 17 │ module.exports = require(../pkg); │ ────┬─── │ ╰───── Module not found. ────╯ [UNLOADABLE_DEPENDENCY] Error: Could not load ../../node_modules/.pnpm/fsevents@2.3.3/node_modules/fsevents/fsevents.node ╭─[ ../../node_modules/.pnpm/fsevents@2.3.3/node_modules/fsevents/fsevents.js:13:24 ] │ 13 │ const Native = require("./fsevents.node"); │ ────────┬──────── │ ╰────────── stream did not contain valid UTF-8 ────╯ at normalizeErrors (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/rolldown@1.0.0-beta.8-commit.151352b_typescript@5.8.3/node_modules/rolldown/dist/shared/src-DvIQg0VF.mjs:935:18) at handleOutputErrors (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/rolldown@1.0.0-beta.8-commit.151352b_typescript@5.8.3/node_modules/rolldown/dist/shared/src-DvIQg0VF.mjs:1758:34) at transformToRollupOutput (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/rolldown@1.0.0-beta.8-commit.151352b_typescript@5.8.3/node_modules/rolldown/dist/shared/src-DvIQg0VF.mjs:1752:2) at RolldownBuild.write (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/rolldown@1.0.0-beta.8-commit.151352b_typescript@5.8.3/node_modules/rolldown/dist/shared/src-DvIQg0VF.mjs:4168:11) at async build (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/rolldown@1.0.0-beta.8-commit.151352b_typescript@5.8.3/node_modules/rolldown/dist/shared/src-DvIQg0VF.mjs:4210:22) at async /Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/index.js:536:5 at async Promise.all (index 0) at async rebuild (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/index.js:527:3) at async buildSingle (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/index.js:519:2) at async Promise.all (index 0) at async build (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/index.js:491:19) at async CAC.<anonymous> (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/run.js:19:2) at async runCLI (/Users/aklinker1/Development/github.com/wxt-dev/wxt/node_modules/.pnpm/tsdown@0.10.0_publint@0.3.10_typescript@5.8.3/node_modules/tsdown/dist/run.js:37:3)This is caused by the weird circular dependency between WXT and the module agumentation :/
The solution is simple: don't do module augmentation. instead, when a config key is listed in the module options, WXT should generate the module augmentation instead of requiring the module author to include it in the module code.
import { defineWxtModule } from 'wxt/modules'; - import 'wxt'; - export interface MyModuleOptions { + export interface ModuleOptions { // Add your build-time options here... } - declare module 'wxt' { - export interface InlineConfig { - // Add types for the "myModule" key in wxt.config.ts - myModule: MyModuleOptions; - } - } export default defineWxtModule<AnalyticModuleOptions>({ configKey: 'myModule', // Build time config is available via the second argument of setup setup(wxt, options) { console.log(options); }, });Then in the project's
.wxtdirectory, we generate something like the following:// .wxt/module-build-options.d.ts import 'wxt'; declare module 'wxt' { export interface InlineConfig { myModule: import("my-module").ModuleOptions } }Good news, this shouldn't be a breaking change! Regardless of if we migrate to
tsdown, this is something that should be done.
Originally posted by @aklinker1 in #1628
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.