wxt 0.21.0 → 0.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +0 -1
  2. package/bin/wxt-publish-extension.mjs +4 -3
  3. package/dist/browser.d.mts +7 -6
  4. package/dist/browser.mjs +6 -5
  5. package/dist/builtin-modules/favicon-permission.mjs +28 -0
  6. package/dist/builtin-modules/index.mjs +3 -4
  7. package/dist/builtin-modules/unimport.mjs +1 -3
  8. package/dist/cli/cli-utils.mjs +8 -9
  9. package/dist/cli/commands.mjs +1 -3
  10. package/dist/cli/index.mjs +1 -3
  11. package/dist/core/build.d.mts +9 -8
  12. package/dist/core/build.mjs +10 -11
  13. package/dist/core/builders/vite/index.mjs +123 -75
  14. package/dist/core/builders/vite/plugins/bundleAnalysis.mjs +1 -3
  15. package/dist/core/builders/vite/plugins/cssEntrypoints.mjs +6 -6
  16. package/dist/core/builders/vite/plugins/defineImportMeta.mjs +3 -4
  17. package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +34 -26
  18. package/dist/core/builders/vite/plugins/devServerGlobals.mjs +3 -3
  19. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.mjs +2 -6
  20. package/dist/core/builders/vite/plugins/extensionApiMock.mjs +13 -8
  21. package/dist/core/builders/vite/plugins/globals.mjs +1 -3
  22. package/dist/core/builders/vite/plugins/iifeAnonymous.mjs +1 -2
  23. package/dist/core/builders/vite/plugins/iifeFooter.mjs +14 -7
  24. package/dist/core/builders/vite/plugins/index.mjs +17 -19
  25. package/dist/core/builders/vite/plugins/noopBackground.mjs +14 -9
  26. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +10 -12
  27. package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +14 -10
  28. package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +15 -13
  29. package/dist/core/builders/vite/plugins/tsconfigPaths.mjs +1 -2
  30. package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +22 -17
  31. package/dist/core/clean.d.mts +3 -14
  32. package/dist/core/clean.mjs +19 -13
  33. package/dist/core/create-server.d.mts +6 -5
  34. package/dist/core/create-server.mjs +21 -117
  35. package/dist/core/define-config.mjs +1 -2
  36. package/dist/core/define-web-ext-config.d.mts +3 -6
  37. package/dist/core/define-web-ext-config.mjs +3 -12
  38. package/dist/core/generate-wxt-dir.mjs +53 -35
  39. package/dist/core/index.d.mts +3 -2
  40. package/dist/core/index.mjs +11 -11
  41. package/dist/core/initialize.mjs +28 -29
  42. package/dist/core/keyboard-shortcuts.mjs +4 -8
  43. package/dist/core/package-managers/bun.mjs +1 -3
  44. package/dist/core/package-managers/deno.mjs +1 -2
  45. package/dist/core/package-managers/index.mjs +1 -3
  46. package/dist/core/package-managers/npm.mjs +3 -5
  47. package/dist/core/package-managers/pnpm.mjs +1 -3
  48. package/dist/core/package-managers/yarn.mjs +1 -3
  49. package/dist/core/prepare.mjs +1 -3
  50. package/dist/core/resolve-config.mjs +63 -43
  51. package/dist/core/runners/manual.mjs +2 -6
  52. package/dist/core/runners/safari.mjs +3 -4
  53. package/dist/core/runners/web-ext.mjs +8 -11
  54. package/dist/core/runners/wsl.mjs +3 -4
  55. package/dist/core/utils/arrays.mjs +4 -11
  56. package/dist/core/utils/building/build-entrypoints.mjs +10 -11
  57. package/dist/core/utils/building/detect-dev-changes.mjs +37 -19
  58. package/dist/core/utils/building/find-entrypoints.mjs +40 -21
  59. package/dist/core/utils/building/group-entrypoints.mjs +3 -4
  60. package/dist/core/utils/building/index.mjs +7 -8
  61. package/dist/core/utils/building/internal-build.mjs +21 -21
  62. package/dist/core/utils/building/rebuild.mjs +10 -10
  63. package/dist/core/utils/cache.mjs +6 -8
  64. package/dist/core/utils/constants.mjs +3 -4
  65. package/dist/core/utils/content-scripts.mjs +3 -4
  66. package/dist/core/utils/content-security-policy.mjs +2 -5
  67. package/dist/core/utils/create-file-reloader.mjs +158 -0
  68. package/dist/core/utils/entrypoints.d.mts +10 -0
  69. package/dist/core/utils/entrypoints.mjs +6 -10
  70. package/dist/core/utils/env.mjs +24 -19
  71. package/dist/core/utils/environments/browser-environment.mjs +1 -3
  72. package/dist/core/utils/environments/environment.mjs +1 -2
  73. package/dist/core/utils/environments/extension-environment.mjs +1 -3
  74. package/dist/core/utils/environments/index.mjs +3 -4
  75. package/dist/core/utils/eslint.mjs +1 -2
  76. package/dist/core/utils/fs.mjs +23 -14
  77. package/dist/core/utils/globals.mjs +1 -2
  78. package/dist/core/utils/i18n.mjs +2 -3
  79. package/dist/core/utils/index.d.mts +2 -0
  80. package/dist/core/utils/index.mjs +3 -3
  81. package/dist/core/utils/log/index.mjs +5 -6
  82. package/dist/core/utils/log/printBuildSummary.mjs +1 -3
  83. package/dist/core/utils/log/printFileList.mjs +25 -21
  84. package/dist/core/utils/log/printHeader.mjs +3 -5
  85. package/dist/core/utils/log/printTable.mjs +1 -2
  86. package/dist/core/utils/manifest.mjs +39 -46
  87. package/dist/core/utils/number.mjs +1 -2
  88. package/dist/core/utils/package.mjs +3 -5
  89. package/dist/core/utils/paths.d.mts +2 -2
  90. package/dist/core/utils/paths.mjs +7 -9
  91. package/dist/core/utils/strings.mjs +4 -7
  92. package/dist/core/utils/syntax-errors.mjs +3 -5
  93. package/dist/core/utils/theme-icons.mjs +71 -0
  94. package/dist/core/utils/time.mjs +1 -13
  95. package/dist/core/utils/transform.mjs +9 -7
  96. package/dist/core/utils/validation.mjs +1 -2
  97. package/dist/core/utils/virtual-modules.mjs +9 -15
  98. package/dist/core/wxt.mjs +11 -12
  99. package/dist/core/zip.d.mts +1 -0
  100. package/dist/core/zip.mjs +25 -20
  101. package/dist/index.d.mts +4 -4
  102. package/dist/index.mjs +3 -3
  103. package/dist/modules.d.mts +64 -61
  104. package/dist/modules.mjs +70 -66
  105. package/dist/testing/fake-browser.mjs +1 -2
  106. package/dist/testing/wxt-vitest-plugin.d.mts +4 -2
  107. package/dist/testing/wxt-vitest-plugin.mjs +5 -7
  108. package/dist/types.d.mts +636 -450
  109. package/dist/utils/app-config.d.mts +1 -0
  110. package/dist/utils/app-config.mjs +3 -3
  111. package/dist/utils/content-script-context.d.mts +49 -39
  112. package/dist/utils/content-script-context.mjs +37 -32
  113. package/dist/utils/content-script-ui/iframe.d.mts +14 -15
  114. package/dist/utils/content-script-ui/iframe.mjs +1 -3
  115. package/dist/utils/content-script-ui/integrated.d.mts +8 -7
  116. package/dist/utils/content-script-ui/integrated.mjs +1 -3
  117. package/dist/utils/content-script-ui/shadow-root.d.mts +37 -25
  118. package/dist/utils/content-script-ui/shadow-root.mjs +5 -8
  119. package/dist/utils/content-script-ui/shared.mjs +1 -3
  120. package/dist/utils/content-script-ui/types.d.mts +29 -34
  121. package/dist/utils/content-script-ui/types.mjs +1 -1
  122. package/dist/utils/define-app-config.d.mts +4 -3
  123. package/dist/utils/define-app-config.mjs +5 -5
  124. package/dist/utils/define-background.mjs +1 -2
  125. package/dist/utils/define-content-script.mjs +1 -2
  126. package/dist/utils/define-unlisted-script.mjs +1 -2
  127. package/dist/utils/define-wxt-plugin.mjs +1 -2
  128. package/dist/utils/inject-script.d.mts +2 -2
  129. package/dist/utils/inject-script.mjs +4 -5
  130. package/dist/utils/internal/custom-events.mjs +3 -4
  131. package/dist/utils/internal/location-watcher.mjs +4 -6
  132. package/dist/utils/internal/logger.mjs +2 -5
  133. package/dist/utils/match-patterns.mjs +2 -3
  134. package/dist/utils/split-shadow-root-css.d.mts +6 -2
  135. package/dist/utils/split-shadow-root-css.mjs +7 -4
  136. package/dist/utils/storage.mjs +2 -3
  137. package/dist/version.mjs +2 -3
  138. package/dist/virtual/background-entrypoint.mjs +4 -16
  139. package/dist/virtual/content-script-isolated-world-entrypoint.mjs +2 -7
  140. package/dist/virtual/content-script-main-world-entrypoint.mjs +2 -7
  141. package/dist/virtual/mock-browser.d.mts +1 -1
  142. package/dist/virtual/mock-browser.mjs +2 -4
  143. package/dist/virtual/reload-html.mjs +3 -10
  144. package/dist/virtual/unlisted-script-entrypoint.mjs +2 -7
  145. package/package.json +55 -49
  146. package/LICENSE +0 -21
  147. package/dist/core/builders/vite/plugins/download.mjs +0 -25
  148. package/dist/core/runners/index.mjs +0 -17
  149. package/dist/core/utils/minimatch-multiple.mjs +0 -28
  150. package/dist/core/utils/network.mjs +0 -38
  151. package/dist/core/utils/wsl.mjs +0 -12
  152. package/dist/testing/index.d.mts +0 -3
  153. package/dist/testing/index.mjs +0 -4
@@ -1,6 +1,5 @@
1
1
  import { dedupeDependencies, npm } from "./npm.mjs";
2
2
  import spawn from "nano-spawn";
3
-
4
3
  //#region src/core/package-managers/yarn.ts
5
4
  const yarn = {
6
5
  overridesKey: "resolutions",
@@ -29,6 +28,5 @@ const yarn = {
29
28
  return dedupeDependencies(dependencies);
30
29
  }
31
30
  };
32
-
33
31
  //#endregion
34
- export { yarn };
32
+ export { yarn };
@@ -2,13 +2,11 @@ import { registerWxt, wxt } from "./wxt.mjs";
2
2
  import { findEntrypoints } from "./utils/building/find-entrypoints.mjs";
3
3
  import { generateWxtDir } from "./generate-wxt-dir.mjs";
4
4
  import "./utils/building/index.mjs";
5
-
6
5
  //#region src/core/prepare.ts
7
6
  async function prepare(config) {
8
7
  await registerWxt("build", config);
9
8
  wxt.logger.info("Generating types...");
10
9
  await generateWxtDir(await findEntrypoints());
11
10
  }
12
-
13
11
  //#endregion
14
- export { prepare };
12
+ export { prepare };
@@ -1,12 +1,15 @@
1
+ import { builtinModules } from "../builtin-modules/index.mjs";
1
2
  import { normalizePath } from "./utils/paths.mjs";
2
- import { createFsCache } from "./utils/cache.mjs";
3
3
  import "./utils/index.mjs";
4
- import { builtinModules } from "../builtin-modules/index.mjs";
4
+ import { createFsCache } from "./utils/cache.mjs";
5
5
  import { getEslintVersion } from "./utils/eslint.mjs";
6
6
  import { safeStringToNumber } from "./utils/number.mjs";
7
7
  import { loadEnv } from "./utils/env.mjs";
8
- import fs from "fs-extra";
9
- import glob from "fast-glob";
8
+ import { createSafariRunner } from "./runners/safari.mjs";
9
+ import { createWslRunner } from "./runners/wsl.mjs";
10
+ import { createManualRunner } from "./runners/manual.mjs";
11
+ import { pathExists } from "./utils/fs.mjs";
12
+ import { glob } from "tinyglobby";
10
13
  import path from "node:path";
11
14
  import { loadConfig } from "c12";
12
15
  import { resolve as resolve$1 } from "import-meta-resolve";
@@ -14,14 +17,15 @@ import consola, { LogLevels } from "consola";
14
17
  import defu from "defu";
15
18
  import { getPort } from "get-port-please";
16
19
  import { fileURLToPath, pathToFileURL } from "node:url";
17
-
20
+ import isWsl from "is-wsl";
18
21
  //#region src/core/resolve-config.ts
19
22
  /**
20
- * Given an inline config, discover the config file if necessary, merge the results, resolve any
21
- * relative paths, and apply any defaults.
23
+ * Given an inline config, discover the config file if necessary, merge the
24
+ * results, resolve any relative paths, and apply any defaults.
22
25
  *
23
- * Inline config always has priority over user config. Cli flags are passed as inline config if set.
24
- * If unset, undefined is passed in, letting this function decide default values.
26
+ * Inline config always has priority over user config. Cli flags are passed as
27
+ * inline config if set. If unset, undefined is passed in, letting this function
28
+ * decide default values.
25
29
  */
26
30
  async function resolveConfig(inlineConfig, command) {
27
31
  let userConfig = {};
@@ -69,14 +73,13 @@ async function resolveConfig(inlineConfig, command) {
69
73
  const outDirTemplate = (mergedConfig.outDirTemplate ?? `${browser}-mv${manifestVersion}${modeSuffix}`).replaceAll("{{browser}}", browser).replaceAll("{{manifestVersion}}", manifestVersion.toString()).replaceAll("{{modeSuffix}}", modeSuffix).replaceAll("{{mode}}", mode).replaceAll("{{command}}", command);
70
74
  const outDir = path.resolve(outBaseDir, outDirTemplate);
71
75
  const reloadCommand = mergedConfig.dev?.reloadCommand ?? "Alt+R";
72
- if (inlineConfig.runner != null || userConfig.runner != null) logger.warn("`InlineConfig#runner` is deprecated, use `InlineConfig#webExt` instead. See https://wxt.dev/guide/resources/upgrading.html#v0-19-0-rarr-v0-20-0");
73
- const runnerConfig = await loadConfig({
76
+ const webExt = await loadConfig({
74
77
  name: "web-ext",
75
78
  cwd: root,
76
79
  globalRc: true,
77
80
  rcFile: ".webextrc",
78
- overrides: inlineConfig.webExt ?? inlineConfig.runner,
79
- defaults: userConfig.webExt ?? userConfig.runner
81
+ overrides: inlineConfig.webExt,
82
+ defaults: userConfig.webExt
80
83
  });
81
84
  const alias = Object.fromEntries(Object.entries({
82
85
  ...mergedConfig.alias,
@@ -87,15 +90,19 @@ async function resolveConfig(inlineConfig, command) {
87
90
  }).map(([key, value]) => [key, path.resolve(root, value)]));
88
91
  let devServerConfig;
89
92
  if (command === "serve") {
90
- if (mergedConfig.dev?.server?.hostname) logger.warn(`The 'hostname' option is deprecated, please use 'host' or 'origin' depending on your circumstances.`);
91
- const host = mergedConfig.dev?.server?.host ?? mergedConfig.dev?.server?.hostname ?? "localhost";
93
+ const host = mergedConfig.dev?.server?.host ?? "localhost";
92
94
  let port = mergedConfig.dev?.server?.port;
93
- const origin = mergedConfig.dev?.server?.origin ?? mergedConfig.dev?.server?.hostname ?? "localhost";
95
+ const origin = mergedConfig.dev?.server?.origin ?? "localhost";
96
+ const strictPort = mergedConfig.dev?.server?.strictPort ?? false;
94
97
  if (port == null || !isFinite(port)) port = await getPort({
95
98
  host,
96
99
  port: 3e3,
97
100
  portRange: [3001, 3010]
98
101
  });
102
+ else if (!strictPort) port = await getPort({
103
+ host,
104
+ port
105
+ });
99
106
  const originWithProtocolAndPort = [
100
107
  origin.match(/^https?:\/\//) ? "" : "http://",
101
108
  origin,
@@ -105,6 +112,7 @@ async function resolveConfig(inlineConfig, command) {
105
112
  host,
106
113
  port,
107
114
  origin: originWithProtocolAndPort,
115
+ strictPort,
108
116
  watchDebounce: safeStringToNumber(process.env.WXT_WATCH_DEBOUNCE) ?? 800
109
117
  };
110
118
  }
@@ -133,7 +141,8 @@ async function resolveConfig(inlineConfig, command) {
133
141
  publicDir,
134
142
  wxtModuleDir,
135
143
  root,
136
- runnerConfig,
144
+ webExt,
145
+ runner: command === "serve" ? await resolveRunner(browser, logger, mergedConfig) : createManualRunner(),
137
146
  srcDir,
138
147
  typesDir,
139
148
  wxtDir,
@@ -142,6 +151,8 @@ async function resolveConfig(inlineConfig, command) {
142
151
  userConfigMetadata: userConfigMetadata ?? {},
143
152
  alias,
144
153
  experimental: defu(mergedConfig.experimental, {}),
154
+ suppressWarnings: mergedConfig.suppressWarnings ?? {},
155
+ watchOptions: mergedConfig.watchOptions ?? {},
145
156
  dev: {
146
157
  server: devServerConfig,
147
158
  reloadCommand
@@ -158,7 +169,8 @@ async function resolveManifestConfig(env, manifest) {
158
169
  return typeof manifest === "function" ? await manifest(env) : await (manifest ?? {});
159
170
  }
160
171
  /**
161
- * Merge the inline config and user config. Inline config is given priority. Defaults are not applied here.
172
+ * Merge the inline config and user config. Inline config is given priority.
173
+ * Defaults are not applied here.
162
174
  */
163
175
  async function mergeInlineConfig(inlineConfig, userConfig) {
164
176
  const imports = inlineConfig.imports === false || userConfig.imports === false ? false : userConfig.imports == null && inlineConfig.imports == null ? void 0 : defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
@@ -179,10 +191,10 @@ function resolveZipConfig(root, browser, outBaseDir, mergedConfig) {
179
191
  const downloadedPackagesDir = path.resolve(root, ".wxt/local_modules");
180
192
  return {
181
193
  name: void 0,
182
- sourcesTemplate: "{{name}}-{{version}}-sources.zip",
183
- artifactTemplate: "{{name}}-{{version}}-{{browser}}.zip",
194
+ sourcesTemplate: "{{name}}-{{packageVersion}}-sources{{modeSuffix}}.zip",
195
+ artifactTemplate: "{{name}}-{{packageVersion}}-{{browser}}{{modeSuffix}}.zip",
184
196
  sourcesRoot: root,
185
- includeSources: [],
197
+ includeSources: mergedConfig.zip?.includeSources ?? ["**/*"],
186
198
  compressionLevel: 9,
187
199
  ...mergedConfig.zip,
188
200
  zipSources: mergedConfig.zip?.zipSources ?? ["firefox", "opera"].includes(browser),
@@ -190,12 +202,12 @@ function resolveZipConfig(root, browser, outBaseDir, mergedConfig) {
190
202
  excludeSources: [
191
203
  "**/node_modules",
192
204
  "**/web-ext.config.ts",
193
- "**/.*",
194
205
  "**/__tests__/**",
195
206
  "**/*.+(test|spec).?(c|m)+(j|t)s?(x)",
196
207
  `${path.relative(root, outBaseDir)}/**`,
197
208
  ...mergedConfig.zip?.excludeSources ?? []
198
209
  ],
210
+ dotSources: mergedConfig.zip?.dotSources ?? false,
199
211
  downloadPackages: mergedConfig.zip?.downloadPackages ?? [],
200
212
  downloadedPackagesDir
201
213
  };
@@ -216,7 +228,7 @@ function resolveAnalysisConfig(root, mergedConfig) {
216
228
  }
217
229
  async function getUnimportOptions(wxtDir, srcDir, logger, config) {
218
230
  const disabled = config.imports === false;
219
- const eslintrc = await getUnimportEslintOptions(wxtDir, config.imports);
231
+ const eslintrc = await getUnimportEslintOptions(logger, wxtDir, config.imports);
220
232
  const invalidExports = ["options"];
221
233
  const defineImportsAndTypes = (imports, typeImports) => [...imports, ...typeImports.map((name) => ({
222
234
  name,
@@ -225,7 +237,7 @@ async function getUnimportOptions(wxtDir, srcDir, logger, config) {
225
237
  const defaultOptions = {
226
238
  imports: [{
227
239
  name: "fakeBrowser",
228
- from: "wxt/testing"
240
+ from: "wxt/testing/fake-browser"
229
241
  }],
230
242
  presets: [
231
243
  {
@@ -329,45 +341,41 @@ async function getUnimportOptions(wxtDir, srcDir, logger, config) {
329
341
  };
330
342
  return defu(config.imports ?? {}, defaultOptions);
331
343
  }
332
- async function getUnimportEslintOptions(wxtDir, options) {
344
+ async function getUnimportEslintOptions(logger, wxtDir, options) {
333
345
  const inlineEnabled = options === false ? false : options?.eslintrc?.enabled ?? "auto";
346
+ const version = await getEslintVersion();
347
+ const major = parseInt(version[0]);
334
348
  let enabled;
335
349
  switch (inlineEnabled) {
336
350
  case "auto":
337
- const version = await getEslintVersion();
338
- let major = parseInt(version[0]);
339
- if (isNaN(major)) enabled = false;
340
- if (major <= 8) enabled = 8;
351
+ case true:
352
+ if (isNaN(major)) {
353
+ if (inlineEnabled === true) logger.warn("Could not determine installed ESLint version, `eslint-auto-imports.mjs` not generated");
354
+ enabled = false;
355
+ } else if (major <= 8) enabled = 8;
341
356
  else if (major >= 9) enabled = 9;
342
357
  else enabled = false;
343
358
  break;
344
- case true:
345
- enabled = 8;
346
- break;
347
359
  default: enabled = inlineEnabled;
348
360
  }
349
361
  return {
350
362
  enabled,
351
- filePath: path.resolve(wxtDir, enabled === 9 ? "eslint-auto-imports.mjs" : "eslintrc-auto-import.json"),
363
+ filePath: path.resolve(wxtDir, enabled === 8 ? "eslintrc-auto-import.json" : "eslint-auto-imports.mjs"),
352
364
  globalsPropValue: true
353
365
  };
354
366
  }
355
- /**
356
- * Returns the path to `node_modules/wxt`.
357
- */
367
+ /** Returns the path to `node_modules/wxt`. */
358
368
  function resolveWxtModuleDir() {
359
369
  const url = resolve$1("wxt", import.meta.url);
360
370
  return path.resolve(fileURLToPath(url), "../..");
361
371
  }
362
372
  async function isDirMissing(dir) {
363
- return !await fs.pathExists(dir);
373
+ return !await pathExists(dir);
364
374
  }
365
375
  function logMissingDir(logger, name, expected) {
366
376
  logger.warn(`${name} directory not found: ./${normalizePath(path.relative(process.cwd(), expected))}`);
367
377
  }
368
- /**
369
- * Map of `ConfigEnv` commands to their default modes.
370
- */
378
+ /** Map of `ConfigEnv` commands to their default modes. */
371
379
  const COMMAND_MODES = {
372
380
  build: "production",
373
381
  serve: "development"
@@ -395,7 +403,8 @@ async function resolveWxtUserModules(root, modulesDir, modules = []) {
395
403
  }));
396
404
  const localModulePaths = await glob(["*.[tj]s", "*/index.[tj]s"], {
397
405
  cwd: modulesDir,
398
- onlyFiles: true
406
+ onlyFiles: true,
407
+ expandDirectories: false
399
408
  }).catch(() => []);
400
409
  localModulePaths.sort();
401
410
  const localModules = await Promise.all(localModulePaths.map(async (file) => {
@@ -418,6 +427,17 @@ async function resolveWxtUserModules(root, modulesDir, modules = []) {
418
427
  }));
419
428
  return [...npmModules, ...localModules];
420
429
  }
421
-
430
+ async function resolveRunner(browser, logger, mergedConfig) {
431
+ if (browser === "safari") return createSafariRunner();
432
+ if (isWsl) return createWslRunner();
433
+ try {
434
+ const { createWebExtRunner } = await import("./runners/web-ext.mjs");
435
+ return mergedConfig.webExt?.disabled ? createManualRunner() : createWebExtRunner();
436
+ } catch (err) {
437
+ if (err?.code !== "ERR_MODULE_NOT_FOUND") throw err;
438
+ logger.debug("Error loading the web-ext runner", err);
439
+ }
440
+ return createManualRunner();
441
+ }
422
442
  //#endregion
423
- export { resolveConfig };
443
+ export { resolveConfig };
@@ -1,15 +1,11 @@
1
1
  import { wxt } from "../wxt.mjs";
2
2
  import { relative } from "node:path";
3
-
4
3
  //#region src/core/runners/manual.ts
5
- /**
6
- * The manual runner tells the user to load the unpacked extension manually.
7
- */
4
+ /** The manual runner tells the user to load the unpacked extension manually. */
8
5
  function createManualRunner() {
9
6
  return { async openBrowser() {
10
7
  wxt.logger.info(`Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
8
  } };
12
9
  }
13
-
14
10
  //#endregion
15
- export { createManualRunner };
11
+ export { createManualRunner };
@@ -1,15 +1,14 @@
1
1
  import { wxt } from "../wxt.mjs";
2
2
  import { relative } from "node:path";
3
-
4
3
  //#region src/core/runners/safari.ts
5
4
  /**
6
- * The Safari runner just logs a warning message because `web-ext` doesn't work with Safari.
5
+ * The Safari runner just logs a warning message because `web-ext` doesn't work
6
+ * with Safari.
7
7
  */
8
8
  function createSafariRunner() {
9
9
  return { async openBrowser() {
10
10
  wxt.logger.warn(`Cannot Safari using web-ext. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
11
  } };
12
12
  }
13
-
14
13
  //#endregion
15
- export { createSafariRunner };
14
+ export { createSafariRunner };
@@ -1,11 +1,10 @@
1
- import { formatDuration } from "../utils/time.mjs";
2
1
  import { wxt } from "../wxt.mjs";
2
+ import { formatDuration } from "../utils/time.mjs";
3
3
  import defu from "defu";
4
-
4
+ import webExt from "web-ext";
5
+ import { consoleStream } from "web-ext/util/logger";
5
6
  //#region src/core/runners/web-ext.ts
6
- /**
7
- * Create an `ExtensionRunner` backed by `web-ext`.
8
- */
7
+ /** Create an `ExtensionRunner` backed by `web-ext`. */
9
8
  function createWebExtRunner() {
10
9
  let runner;
11
10
  return {
@@ -14,12 +13,11 @@ function createWebExtRunner() {
14
13
  },
15
14
  async openBrowser() {
16
15
  const startTime = Date.now();
17
- const webExtLogger = await import("web-ext-run/util/logger");
18
- webExtLogger.consoleStream.write = ({ level, msg, name }) => {
16
+ consoleStream.write = ({ level, msg, name }) => {
19
17
  if (level >= ERROR_LOG_LEVEL) wxt.logger.error(name, msg);
20
18
  if (level >= WARN_LOG_LEVEL) wxt.logger.warn(msg);
21
19
  };
22
- const wxtUserConfig = wxt.config.runnerConfig.config;
20
+ const wxtUserConfig = wxt.config.webExt.config;
23
21
  const finalConfig = {
24
22
  browserConsole: wxtUserConfig?.openConsole,
25
23
  devtools: wxtUserConfig?.openDevtools,
@@ -46,7 +44,7 @@ function createWebExtRunner() {
46
44
  const options = { shouldExitProgram: false };
47
45
  wxt.logger.debug("web-ext config:", finalConfig);
48
46
  wxt.logger.debug("web-ext options:", options);
49
- runner = await (await import("web-ext-run")).default.cmd.run(finalConfig, options);
47
+ runner = await webExt.cmd.run(finalConfig, options);
50
48
  const duration = Date.now() - startTime;
51
49
  wxt.logger.success(`Opened browser in ${formatDuration(duration)}`);
52
50
  },
@@ -61,6 +59,5 @@ const DEFAULT_CHROMIUM_PREFS = { devtools: { synced_preferences_sync_disabled: {
61
59
  skipContentScripts: false,
62
60
  "skip-content-scripts": false
63
61
  } } };
64
-
65
62
  //#endregion
66
- export { createWebExtRunner };
63
+ export { createWebExtRunner };
@@ -1,15 +1,14 @@
1
1
  import { wxt } from "../wxt.mjs";
2
2
  import { relative } from "node:path";
3
-
4
3
  //#region src/core/runners/wsl.ts
5
4
  /**
6
- * The WSL runner just logs a warning message because `web-ext` doesn't work in WSL.
5
+ * The WSL runner just logs a warning message because `web-ext` doesn't work in
6
+ * WSL.
7
7
  */
8
8
  function createWslRunner() {
9
9
  return { async openBrowser() {
10
10
  wxt.logger.warn(`Cannot open browser when using WSL. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
11
  } };
12
12
  }
13
-
14
13
  //#endregion
15
- export { createWslRunner };
14
+ export { createWslRunner };
@@ -1,27 +1,20 @@
1
1
  //#region src/core/utils/arrays.ts
2
- /**
3
- * Checks if `predicate` returns truthy for all elements of the array.
4
- */
2
+ /** Checks if `predicate` returns truthy for all elements of the array. */
5
3
  function every(array, predicate) {
6
4
  for (let i = 0; i < array.length; i++) if (!predicate(array[i], i)) return false;
7
5
  return true;
8
6
  }
9
- /**
10
- * Returns true when any of the predicates return true;
11
- */
7
+ /** Returns true when any of the predicates return true; */
12
8
  function some(array, predicate) {
13
9
  for (let i = 0; i < array.length; i++) if (predicate(array[i], i)) return true;
14
10
  return false;
15
11
  }
16
- /**
17
- * Convert an item or array to an array.
18
- */
12
+ /** Convert an item or array to an array. */
19
13
  function toArray(a) {
20
14
  return Array.isArray(a) ? a : [a];
21
15
  }
22
16
  function filterTruthy(array) {
23
17
  return array.filter((item) => !!item);
24
18
  }
25
-
26
19
  //#endregion
27
- export { every, filterTruthy, some, toArray };
20
+ export { every, filterTruthy, some, toArray };
@@ -1,22 +1,22 @@
1
1
  import { toArray } from "../arrays.mjs";
2
2
  import { wxt } from "../../wxt.mjs";
3
3
  import { getPublicFiles } from "../fs.mjs";
4
- import fs from "fs-extra";
4
+ import { copyFile, mkdir, writeFile } from "node:fs/promises";
5
5
  import { dirname, resolve } from "path";
6
- import pc from "picocolors";
7
-
6
+ import { styleText } from "node:util";
8
7
  //#region src/core/utils/building/build-entrypoints.ts
9
8
  async function buildEntrypoints(groups, spinner) {
10
9
  const steps = [];
11
10
  for (let i = 0; i < groups.length; i++) {
12
11
  const group = groups[i];
13
12
  const groupNames = toArray(group).map((e) => e.name);
14
- const groupNameColored = groupNames.join(pc.dim(", "));
15
- spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
13
+ const groupNameColored = groupNames.join(styleText("dim", ", "));
14
+ spinner.update({ text: styleText("dim", `[${i + 1}/${groups.length}]`) + ` ${groupNameColored}` });
16
15
  try {
17
16
  steps.push(await wxt.builder.build(group));
18
17
  } catch (err) {
19
- spinner.stop().clear();
18
+ spinner.stop();
19
+ spinner.clear();
20
20
  wxt.logger.error(err);
21
21
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
22
22
  }
@@ -36,9 +36,9 @@ async function copyPublicDirectory() {
36
36
  const publicAssets = [];
37
37
  for (const file of files) {
38
38
  const absoluteDest = resolve(wxt.config.outDir, file.relativeDest);
39
- await fs.ensureDir(dirname(absoluteDest));
40
- if ("absoluteSrc" in file) await fs.copyFile(file.absoluteSrc, absoluteDest);
41
- else await fs.writeFile(absoluteDest, file.contents, "utf8");
39
+ await mkdir(dirname(absoluteDest), { recursive: true });
40
+ if ("absoluteSrc" in file) await copyFile(file.absoluteSrc, absoluteDest);
41
+ else await writeFile(absoluteDest, file.contents, "utf8");
42
42
  publicAssets.push({
43
43
  type: "asset",
44
44
  fileName: file.relativeDest
@@ -46,6 +46,5 @@ async function copyPublicDirectory() {
46
46
  }
47
47
  return publicAssets;
48
48
  }
49
-
50
49
  //#endregion
51
- export { buildEntrypoints };
50
+ export { buildEntrypoints };
@@ -1,38 +1,47 @@
1
1
  import { normalizePath } from "../paths.mjs";
2
2
  import { every, some } from "../arrays.mjs";
3
3
  import { wxt } from "../../wxt.mjs";
4
-
5
4
  //#region src/core/utils/building/detect-dev-changes.ts
6
5
  /**
7
- * Compare the changed files vs the build output and determine what kind of reload needs to happen:
6
+ * Compare the changed files vs the build output and determine what kind of
7
+ * reload needs to happen:
8
8
  *
9
9
  * - Do nothing
10
- * - CSS or JS file associated with an HTML page is changed - this is handled automatically by the
11
- * dev server
10
+ *
11
+ * - CSS or JS file associated with an HTML page is changed - this is handled
12
+ * automatically by the dev server
12
13
  * - Change isn't used by any of the entrypoints
13
14
  * - Reload Content script
15
+ *
14
16
  * - CSS or JS file associated with a content script
15
17
  * - Background script will be told to reload the content script
16
18
  * - Reload HTML file
17
- * - HTML file itself is saved - HMR doesn't handle this because the HTML pages are pre-rendered
18
- * - Chrome is OK reloading the page when the HTML file is changed without reloading the whole
19
- * extension. Not sure about firefox, this might need to change to an extension reload
19
+ *
20
+ * - HTML file itself is saved - HMR doesn't handle this because the HTML pages
21
+ * are pre-rendered
22
+ * - Chrome is OK reloading the page when the HTML file is changed without
23
+ * reloading the whole extension. Not sure about firefox, this might need
24
+ * to change to an extension reload
20
25
  * - Reload extension
26
+ *
21
27
  * - Background script is changed
22
28
  * - Manifest is different
23
29
  * - Restart browser
24
- * - web-ext.config.ts (runner config changes)
30
+ *
31
+ * - Web-ext.config.ts (runner config changes)
25
32
  * - Full dev server restart
26
- * - wxt.config.ts (main config file)
27
- * - modules/* (any file related to WXT modules)
33
+ *
34
+ * - Wxt.config.ts (main config file)
35
+ * - Modules/* (any file related to WXT modules)
28
36
  * - .env (environment variable changed could effect build)
29
37
  */
30
38
  function detectDevChanges(changedFiles, currentOutput) {
31
- if (some(changedFiles, (file) => file === wxt.config.userConfigMetadata.configFile)) return { type: "full-restart" };
32
- if (some(changedFiles, (file) => file.startsWith(wxt.config.modulesDir))) return { type: "full-restart" };
33
- if (some(changedFiles, (file) => file === wxt.config.runnerConfig.configFile)) return { type: "browser-restart" };
34
- const changedSteps = new Set(changedFiles.flatMap((changedFile) => findEffectedSteps(changedFile, currentOutput)));
35
- if (changedSteps.size === 0) if (some(changedFiles, (file) => file.startsWith(wxt.config.publicDir))) return {
39
+ const relevantChangedFiles = getRelevantDevChangedFiles(changedFiles, currentOutput);
40
+ if (some(relevantChangedFiles, (file) => file === wxt.config.userConfigMetadata.configFile)) return { type: "full-restart" };
41
+ if (some(relevantChangedFiles, (file) => file.startsWith(wxt.config.modulesDir))) return { type: "full-restart" };
42
+ if (some(relevantChangedFiles, (file) => file === wxt.config.webExt.configFile)) return { type: "browser-restart" };
43
+ const changedSteps = new Set(relevantChangedFiles.flatMap((changedFile) => findEffectedSteps(changedFile, currentOutput)));
44
+ if (changedSteps.size === 0) if (some(relevantChangedFiles, (file) => file.startsWith(wxt.config.publicDir))) return {
36
45
  type: "extension-reload",
37
46
  rebuildGroups: [],
38
47
  cachedOutput: currentOutput
@@ -50,7 +59,7 @@ function detectDevChanges(changedFiles, currentOutput) {
50
59
  };
51
60
  for (const step of currentOutput.steps) if (changedSteps.has(step)) changedOutput.steps.push(step);
52
61
  else unchangedOutput.steps.push(step);
53
- if (changedFiles.length > 0 && every(changedFiles, (file) => file.endsWith(".html"))) return {
62
+ if (relevantChangedFiles.length > 0 && every(relevantChangedFiles, (file) => file.endsWith(".html"))) return {
54
63
  type: "html-reload",
55
64
  cachedOutput: unchangedOutput,
56
65
  rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
@@ -67,8 +76,18 @@ function detectDevChanges(changedFiles, currentOutput) {
67
76
  rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
68
77
  };
69
78
  }
79
+ function getRelevantDevChangedFiles(changedFiles, currentOutput) {
80
+ return Array.from(new Set(changedFiles)).filter((changedFile) => {
81
+ if (changedFile === wxt.config.userConfigMetadata.configFile) return true;
82
+ if (changedFile.startsWith(wxt.config.modulesDir)) return true;
83
+ if (changedFile === wxt.config.webExt.configFile) return true;
84
+ if (changedFile.startsWith(wxt.config.publicDir)) return true;
85
+ return findEffectedSteps(changedFile, currentOutput).length > 0;
86
+ });
87
+ }
70
88
  /**
71
- * For a single change, return all the step of the build output that were effected by it.
89
+ * For a single change, return all the step of the build output that were
90
+ * effected by it.
72
91
  */
73
92
  function findEffectedSteps(changedFile, currentOutput) {
74
93
  const changes = [];
@@ -83,6 +102,5 @@ function findEffectedSteps(changedFile, currentOutput) {
83
102
  for (const step of currentOutput.steps) if (step.chunks.find((chunk) => isChunkEffected(chunk))) changes.push(step);
84
103
  return changes;
85
104
  }
86
-
87
105
  //#endregion
88
- export { detectDevChanges };
106
+ export { detectDevChanges, getRelevantDevChangedFiles };