wxt 0.18.4 → 0.18.6

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.
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-VBXJIVYU.js";
13
13
 
14
14
  // package.json
15
- var version = "0.18.3";
15
+ var version = "0.18.6";
16
16
 
17
17
  // src/core/utils/paths.ts
18
18
  import systemPath from "node:path";
@@ -691,6 +691,62 @@ function removeEntrypointMainFunction(config, path8) {
691
691
  };
692
692
  }
693
693
 
694
+ // src/core/builders/vite/plugins/wxtPluginLoader.ts
695
+ import { parseHTML as parseHTML2 } from "linkedom";
696
+ function wxtPluginLoader(config) {
697
+ const virtualModuleId = "virtual:wxt-plugins";
698
+ const resolvedVirtualModuleId = "\0" + virtualModuleId;
699
+ const virtualHtmlModuleId = "virtual:wxt-html-plugins";
700
+ const resolvedVirtualHtmlModuleId = "\0" + virtualHtmlModuleId;
701
+ return {
702
+ name: "wxt:plugin-loader",
703
+ resolveId(id) {
704
+ if (id === virtualModuleId)
705
+ return resolvedVirtualModuleId;
706
+ if (id === virtualHtmlModuleId)
707
+ return resolvedVirtualHtmlModuleId;
708
+ },
709
+ load(id) {
710
+ if (id === resolvedVirtualModuleId) {
711
+ const imports = config.plugins.map(
712
+ (plugin, i) => `import initPlugin${i} from '${normalizePath(plugin)}';`
713
+ ).join("\n");
714
+ const initCalls = config.plugins.map((_, i) => ` initPlugin${i}();`).join("\n");
715
+ return `${imports}
716
+
717
+ export function initPlugins() {
718
+ ${initCalls}
719
+ }`;
720
+ }
721
+ if (id === resolvedVirtualHtmlModuleId) {
722
+ return `import { initPlugins } from '${virtualModuleId}';
723
+
724
+ try {
725
+ initPlugins();
726
+ } catch (err) {
727
+ console.error("[wxt] Failed to initialize plugins", err);
728
+ }`;
729
+ }
730
+ },
731
+ transformIndexHtml: {
732
+ // Use "pre" so the new script is added before vite bundles all the scripts
733
+ order: "pre",
734
+ handler(html, _ctx) {
735
+ const { document } = parseHTML2(html);
736
+ const script = document.createElement("script");
737
+ script.type = "module";
738
+ script.src = "virtual:wxt-html-plugins";
739
+ if (document.head == null) {
740
+ const newHead = document.createElement("head");
741
+ document.documentElement.prepend(newHead);
742
+ }
743
+ document.head.prepend(script);
744
+ return document.toString();
745
+ }
746
+ }
747
+ };
748
+ }
749
+
694
750
  // src/core/utils/strings.ts
695
751
  function kebabCaseAlphanumeric(str) {
696
752
  return str.toLowerCase().replace(/[^a-z0-9-\s]/g, "").replace(/\s+/g, "-");
@@ -750,18 +806,21 @@ async function buildEntrypoints(groups, spinner) {
750
806
  return { publicAssets, steps };
751
807
  }
752
808
  async function copyPublicDirectory() {
753
- const files = await getPublicFiles();
809
+ const files = (await getPublicFiles()).map((file) => ({
810
+ absoluteSrc: resolve6(wxt.config.publicDir, file),
811
+ relativeDest: file
812
+ }));
813
+ await wxt.hooks.callHook("build:publicAssets", wxt, files);
754
814
  if (files.length === 0)
755
815
  return [];
756
816
  const publicAssets = [];
757
- for (const file of files) {
758
- const srcPath = resolve6(wxt.config.publicDir, file);
759
- const outPath = resolve6(wxt.config.outDir, file);
760
- await fs4.ensureDir(dirname3(outPath));
761
- await fs4.copyFile(srcPath, outPath);
817
+ for (const { absoluteSrc, relativeDest } of files) {
818
+ const absoluteDest = resolve6(wxt.config.outDir, relativeDest);
819
+ await fs4.ensureDir(dirname3(absoluteDest));
820
+ await fs4.copyFile(absoluteSrc, absoluteDest);
762
821
  publicAssets.push({
763
822
  type: "asset",
764
- fileName: file
823
+ fileName: relativeDest
765
824
  });
766
825
  }
767
826
  return publicAssets;
@@ -865,7 +924,7 @@ function findEffectedSteps(changedFile, currentOutput) {
865
924
  import { relative as relative4, resolve as resolve8 } from "path";
866
925
  import fs6 from "fs-extra";
867
926
  import { minimatch } from "minimatch";
868
- import { parseHTML as parseHTML2 } from "linkedom";
927
+ import { parseHTML as parseHTML3 } from "linkedom";
869
928
  import JSON5 from "json5";
870
929
  import glob2 from "fast-glob";
871
930
  import pc2 from "picocolors";
@@ -936,7 +995,7 @@ async function importEntrypointFile(path8) {
936
995
  if (err instanceof ReferenceError) {
937
996
  const variableName = err.message.replace(" is not defined", "");
938
997
  throw Error(
939
- `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/entrypoints.html#side-effects`,
998
+ `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/go-further/entrypoint-side-effects.html`,
940
999
  { cause: err }
941
1000
  );
942
1001
  } else {
@@ -972,7 +1031,7 @@ async function findEntrypoints() {
972
1031
  const inputPath = resolve8(wxt.config.entrypointsDir, relativePath);
973
1032
  const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
974
1033
  const matchingGlob = pathGlobs.find(
975
- (glob4) => minimatch(relativePath, glob4)
1034
+ (glob5) => minimatch(relativePath, glob5)
976
1035
  );
977
1036
  if (matchingGlob) {
978
1037
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
@@ -1266,7 +1325,7 @@ async function getSidepanelEntrypoint(info) {
1266
1325
  }
1267
1326
  async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
1268
1327
  const content = await fs6.readFile(info.inputPath, "utf-8");
1269
- const { document } = parseHTML2(content);
1328
+ const { document } = parseHTML3(content);
1270
1329
  const options = {};
1271
1330
  const defaultQuery = (manifestKey) => document.querySelector(`meta[name='manifest.${manifestKey}']`)?.getAttribute("content");
1272
1331
  Object.entries(keyMap).forEach(([_key, manifestKey]) => {
@@ -1517,7 +1576,14 @@ async function writeMainDeclarationFile(references) {
1517
1576
  `/// <reference types="wxt/vite-builder-env" />`,
1518
1577
  ...references.map(
1519
1578
  (ref) => `/// <reference types="./${normalizePath(relative5(dir, ref))}" />`
1520
- )
1579
+ ),
1580
+ // Add references to modules installed from NPM to the TS project so
1581
+ // their type augmentation can update InlineConfig correctly. Local
1582
+ // modules defined in <root>/modules are already apart of the project, so
1583
+ // we don't need to add them.
1584
+ ...wxt.config.modules.filter(
1585
+ (module) => module.type === "node_module" && module.configKey != null
1586
+ ).map((module) => `/// <reference types="${module.id}" />`)
1521
1587
  ].join("\n") + "\n"
1522
1588
  );
1523
1589
  return filePath;
@@ -1610,6 +1676,7 @@ function isModuleInstalled(name) {
1610
1676
 
1611
1677
  // src/core/utils/building/resolve-config.ts
1612
1678
  import fs10 from "fs-extra";
1679
+ import glob3 from "fast-glob";
1613
1680
  async function resolveConfig(inlineConfig, command) {
1614
1681
  let userConfig = {};
1615
1682
  let userConfigMetadata;
@@ -1645,6 +1712,7 @@ async function resolveConfig(inlineConfig, command) {
1645
1712
  srcDir,
1646
1713
  mergedConfig.entrypointsDir ?? "entrypoints"
1647
1714
  );
1715
+ const modulesDir = path5.resolve(srcDir, mergedConfig.modulesDir ?? "modules");
1648
1716
  if (await isDirMissing(entrypointsDir)) {
1649
1717
  logMissingDir(logger, "Entrypoints", entrypointsDir);
1650
1718
  }
@@ -1686,11 +1754,20 @@ async function resolveConfig(inlineConfig, command) {
1686
1754
  hostname: "localhost"
1687
1755
  };
1688
1756
  }
1757
+ const modules = await resolveWxtModules(modulesDir, mergedConfig.modules);
1758
+ const moduleOptions = modules.reduce((map, module) => {
1759
+ if (module.configKey) {
1760
+ map[module.configKey] = // @ts-expect-error
1761
+ mergedConfig[module.configKey];
1762
+ }
1763
+ return map;
1764
+ }, {});
1689
1765
  return {
1690
1766
  browser,
1691
1767
  command,
1692
1768
  debug,
1693
1769
  entrypointsDir,
1770
+ modulesDir,
1694
1771
  filterEntrypoints,
1695
1772
  env,
1696
1773
  fsCache: createFsCache(wxtDir),
@@ -1722,7 +1799,10 @@ async function resolveConfig(inlineConfig, command) {
1722
1799
  reloadCommand
1723
1800
  },
1724
1801
  hooks: mergedConfig.hooks ?? {},
1725
- vite: mergedConfig.vite ?? (() => ({}))
1802
+ vite: mergedConfig.vite ?? (() => ({})),
1803
+ modules,
1804
+ plugins: [],
1805
+ ...moduleOptions
1726
1806
  };
1727
1807
  }
1728
1808
  async function resolveManifestConfig(env, manifest) {
@@ -1861,6 +1941,52 @@ async function mergeBuilderConfig(inlineConfig, userConfig) {
1861
1941
  }
1862
1942
  throw Error("Builder not found. Make sure vite is installed.");
1863
1943
  }
1944
+ async function resolveWxtModules(modulesDir, modules = []) {
1945
+ const npmModules = await Promise.all(
1946
+ modules.map(async (moduleId) => {
1947
+ const mod = await import(
1948
+ /* @vite-ignore */
1949
+ moduleId
1950
+ );
1951
+ if (mod.default == null) {
1952
+ throw Error("Module missing default export: " + moduleId);
1953
+ }
1954
+ return {
1955
+ ...mod.default,
1956
+ type: "node_module",
1957
+ id: moduleId
1958
+ };
1959
+ })
1960
+ );
1961
+ const localModulePaths = await glob3(["*.[tj]s", "*/index.[tj]s"], {
1962
+ cwd: modulesDir,
1963
+ onlyFiles: true
1964
+ }).catch(() => []);
1965
+ const localModules = await Promise.all(
1966
+ localModulePaths.map(async (file) => {
1967
+ const absolutePath = normalizePath(path5.resolve(modulesDir, file));
1968
+ const { config } = await loadConfig({
1969
+ configFile: absolutePath,
1970
+ globalRc: false,
1971
+ rcFile: false,
1972
+ packageJson: false,
1973
+ envName: false,
1974
+ dotenv: false
1975
+ });
1976
+ if (config == null)
1977
+ throw Error(
1978
+ `No config found for ${file}. Did you forget to add a default export?`
1979
+ );
1980
+ config.name ??= file;
1981
+ return {
1982
+ ...config,
1983
+ type: "local",
1984
+ id: absolutePath
1985
+ };
1986
+ })
1987
+ );
1988
+ return [...npmModules, ...localModules];
1989
+ }
1864
1990
 
1865
1991
  // src/core/utils/building/group-entrypoints.ts
1866
1992
  function groupEntrypoints(entrypoints) {
@@ -2016,7 +2142,7 @@ function getChunkSortWeight(filename) {
2016
2142
  import pc4 from "picocolors";
2017
2143
 
2018
2144
  // src/core/utils/building/internal-build.ts
2019
- import glob3 from "fast-glob";
2145
+ import glob4 from "fast-glob";
2020
2146
 
2021
2147
  // src/core/utils/manifest.ts
2022
2148
  import fs12 from "fs-extra";
@@ -2808,7 +2934,7 @@ async function internalBuild() {
2808
2934
  return output;
2809
2935
  }
2810
2936
  async function combineAnalysisStats() {
2811
- const unixFiles = await glob3(`${wxt.config.analysis.outputName}-*.json`, {
2937
+ const unixFiles = await glob4(`${wxt.config.analysis.outputName}-*.json`, {
2812
2938
  cwd: wxt.config.analysis.outputDir,
2813
2939
  absolute: true
2814
2940
  });
@@ -2869,7 +2995,7 @@ var npm = {
2869
2995
  overridesKey: "overrides",
2870
2996
  async downloadDependency(id, downloadDir) {
2871
2997
  await ensureDir3(downloadDir);
2872
- const { execa } = await import("./execa-VDW6HLFV.js");
2998
+ const { execa } = await import("./execa-5TSWMF32.js");
2873
2999
  const res = await execa("npm", ["pack", id, "--json"], {
2874
3000
  cwd: downloadDir
2875
3001
  });
@@ -2881,7 +3007,7 @@ var npm = {
2881
3007
  if (options?.all) {
2882
3008
  args.push("--depth", "Infinity");
2883
3009
  }
2884
- const { execa } = await import("./execa-VDW6HLFV.js");
3010
+ const { execa } = await import("./execa-5TSWMF32.js");
2885
3011
  const res = await execa("npm", args, { cwd: options?.cwd });
2886
3012
  const project = JSON.parse(res.stdout);
2887
3013
  return flattenNpmListOutput([project]);
@@ -2938,7 +3064,7 @@ var bun = {
2938
3064
  if (options?.all) {
2939
3065
  args.push("--all");
2940
3066
  }
2941
- const { execa } = await import("./execa-VDW6HLFV.js");
3067
+ const { execa } = await import("./execa-5TSWMF32.js");
2942
3068
  const res = await execa("bun", args, { cwd: options?.cwd });
2943
3069
  return dedupeDependencies(
2944
3070
  res.stdout.split("\n").slice(1).map((line) => line.trim()).map((line) => /.* (@?\S+)@(\S+)$/.exec(line)).filter((match) => !!match).map(([_, name, version2]) => ({ name, version: version2 }))
@@ -2957,7 +3083,7 @@ var yarn = {
2957
3083
  if (options?.all) {
2958
3084
  args.push("--depth", "Infinity");
2959
3085
  }
2960
- const { execa } = await import("./execa-VDW6HLFV.js");
3086
+ const { execa } = await import("./execa-5TSWMF32.js");
2961
3087
  const res = await execa("yarn", args, { cwd: options?.cwd });
2962
3088
  const tree = res.stdout.split("\n").map((line) => JSON.parse(line)).find((line) => line.type === "tree")?.data;
2963
3089
  if (tree == null)
@@ -2994,7 +3120,7 @@ var pnpm = {
2994
3120
  if (typeof process !== "undefined" && process.env.WXT_PNPM_IGNORE_WORKSPACE === "true") {
2995
3121
  args.push("--ignore-workspace");
2996
3122
  }
2997
- const { execa } = await import("./execa-VDW6HLFV.js");
3123
+ const { execa } = await import("./execa-5TSWMF32.js");
2998
3124
  const res = await execa("pnpm", args, { cwd: options?.cwd });
2999
3125
  const projects = JSON.parse(res.stdout);
3000
3126
  return flattenNpmListOutput(projects);
@@ -3088,7 +3214,8 @@ async function createViteBuilder(wxtConfig, hooks, server) {
3088
3214
  noopBackground(),
3089
3215
  globals(wxtConfig),
3090
3216
  excludeBrowserPolyfill(wxtConfig),
3091
- defineImportMeta()
3217
+ defineImportMeta(),
3218
+ wxtPluginLoader(wxtConfig)
3092
3219
  );
3093
3220
  if (wxtConfig.analysis.enabled) {
3094
3221
  config.plugins.push(bundleAnalysis(wxtConfig));
@@ -3324,6 +3451,19 @@ async function registerWxt(command, inlineConfig = {}, getServer) {
3324
3451
  builder,
3325
3452
  server
3326
3453
  };
3454
+ for (const module of config.modules) {
3455
+ if (module.hooks)
3456
+ wxt.hooks.addHooks(module.hooks);
3457
+ if (wxt.config.imports !== false && module.imports) {
3458
+ wxt.config.imports.imports ??= [];
3459
+ wxt.config.imports.imports.push(...module.imports);
3460
+ }
3461
+ await module.setup?.(
3462
+ wxt,
3463
+ // @ts-expect-error: Untyped configKey field
3464
+ module.configKey ? config[module.configKey] : void 0
3465
+ );
3466
+ }
3327
3467
  wxt.hooks.addHooks(config.hooks);
3328
3468
  await wxt.hooks.callHook("ready", wxt);
3329
3469
  }