wxt 0.17.6 → 0.17.8

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.
package/README.md CHANGED
@@ -35,14 +35,14 @@
35
35
 
36
36
  ## Demo
37
37
 
38
- https://github.com/wxt-dev/wxt/assets/10101283/07359e53-f491-43b6-8e8f-fae94aec8063
38
+ https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94
39
39
 
40
40
  ## Quick Start
41
41
 
42
42
  Bootstrap a new project:
43
43
 
44
44
  ```sh
45
- pnpx wxt@latest init <project-name>
45
+ pnpm dlx wxt@latest init <project-name>
46
46
  ```
47
47
 
48
48
  Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-VBXJIVYU.js";
4
4
 
5
5
  // package.json
6
- var version = "0.17.6";
6
+ var version = "0.17.8";
7
7
 
8
8
  // src/core/utils/paths.ts
9
9
  import systemPath from "node:path";
@@ -47,6 +47,7 @@ async function buildEntrypoints(groups, spinner) {
47
47
  try {
48
48
  steps.push(await wxt.config.builder.build(group));
49
49
  } catch (err) {
50
+ spinner.stop().clear();
50
51
  wxt.logger.error(err);
51
52
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
52
53
  }
@@ -1774,6 +1775,7 @@ async function resolveConfig(inlineConfig, command, server) {
1774
1775
  },
1775
1776
  analysis: {
1776
1777
  enabled: mergedConfig.analysis?.enabled ?? false,
1778
+ open: mergedConfig.analysis?.open ?? false,
1777
1779
  template: mergedConfig.analysis?.template ?? "treemap",
1778
1780
  outputFile: analysisOutputFile,
1779
1781
  outputDir: analysisOutputDir,
@@ -2925,6 +2927,7 @@ var ValidationError = class extends Error {
2925
2927
  // src/core/utils/building/internal-build.ts
2926
2928
  import consola3 from "consola";
2927
2929
  import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
2930
+ import { isCI } from "ci-info";
2928
2931
  async function internalBuild() {
2929
2932
  await wxt.hooks.callHook("build:before", wxt);
2930
2933
  const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
@@ -2967,6 +2970,15 @@ async function internalBuild() {
2967
2970
  `Analysis complete:
2968
2971
  ${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
2969
2972
  );
2973
+ if (wxt.config.analysis.open) {
2974
+ if (isCI) {
2975
+ wxt.logger.debug(`Skipped opening ${pc5.yellow(statsPath)} in CI`);
2976
+ } else {
2977
+ wxt.logger.info(`Opening ${pc5.yellow(statsPath)} in browser...`);
2978
+ const { default: open } = await import("open");
2979
+ open(wxt.config.analysis.outputFile);
2980
+ }
2981
+ }
2970
2982
  }
2971
2983
  return output;
2972
2984
  }
package/dist/cli.js CHANGED
@@ -279,6 +279,7 @@ async function buildEntrypoints(groups, spinner) {
279
279
  try {
280
280
  steps.push(await wxt.config.builder.build(group));
281
281
  } catch (err) {
282
+ spinner.stop().clear();
282
283
  wxt.logger.error(err);
283
284
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
284
285
  }
@@ -1981,6 +1982,7 @@ async function resolveConfig(inlineConfig, command, server) {
1981
1982
  },
1982
1983
  analysis: {
1983
1984
  enabled: mergedConfig.analysis?.enabled ?? false,
1985
+ open: mergedConfig.analysis?.open ?? false,
1984
1986
  template: mergedConfig.analysis?.template ?? "treemap",
1985
1987
  outputFile: analysisOutputFile,
1986
1988
  outputDir: analysisOutputDir,
@@ -2415,7 +2417,7 @@ function getChunkSortWeight(filename) {
2415
2417
  import pc4 from "picocolors";
2416
2418
 
2417
2419
  // package.json
2418
- var version = "0.17.6";
2420
+ var version = "0.17.8";
2419
2421
 
2420
2422
  // src/core/utils/log/printHeader.ts
2421
2423
  import { consola as consola2 } from "consola";
@@ -3141,6 +3143,7 @@ var ValidationError = class extends Error {
3141
3143
  // src/core/utils/building/internal-build.ts
3142
3144
  import consola3 from "consola";
3143
3145
  import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
3146
+ import { isCI } from "ci-info";
3144
3147
  async function internalBuild() {
3145
3148
  await wxt.hooks.callHook("build:before", wxt);
3146
3149
  const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
@@ -3183,6 +3186,15 @@ async function internalBuild() {
3183
3186
  `Analysis complete:
3184
3187
  ${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
3185
3188
  );
3189
+ if (wxt.config.analysis.open) {
3190
+ if (isCI) {
3191
+ wxt.logger.debug(`Skipped opening ${pc5.yellow(statsPath)} in CI`);
3192
+ } else {
3193
+ wxt.logger.info(`Opening ${pc5.yellow(statsPath)} in browser...`);
3194
+ const { default: open } = await import("open");
3195
+ open(wxt.config.analysis.outputFile);
3196
+ }
3197
+ }
3186
3198
  }
3187
3199
  return output;
3188
3200
  }
@@ -3529,30 +3541,33 @@ function createFileReloader(server) {
3529
3541
  `Changed: ${Array.from(new Set(fileChanges)).map((file) => pc7.dim(relative10(wxt.config.root, file))).join(", ")}`
3530
3542
  );
3531
3543
  const allEntrypoints = await findEntrypoints();
3532
- const { output: newOutput } = await rebuild(
3533
- allEntrypoints,
3534
- // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
3535
- changes.rebuildGroups,
3536
- changes.cachedOutput
3537
- );
3538
- server.currentOutput = newOutput;
3539
- switch (changes.type) {
3540
- case "extension-reload":
3541
- server.reloadExtension();
3542
- consola5.success(`Reloaded extension`);
3543
- break;
3544
- case "html-reload":
3545
- const { reloadedNames } = reloadHtmlPages(
3546
- changes.rebuildGroups,
3547
- server
3548
- );
3549
- consola5.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
3550
- break;
3551
- case "content-script-reload":
3552
- reloadContentScripts(changes.changedSteps, server);
3553
- const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
3554
- consola5.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
3555
- break;
3544
+ try {
3545
+ const { output: newOutput } = await rebuild(
3546
+ allEntrypoints,
3547
+ // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
3548
+ changes.rebuildGroups,
3549
+ changes.cachedOutput
3550
+ );
3551
+ server.currentOutput = newOutput;
3552
+ switch (changes.type) {
3553
+ case "extension-reload":
3554
+ server.reloadExtension();
3555
+ consola5.success(`Reloaded extension`);
3556
+ break;
3557
+ case "html-reload":
3558
+ const { reloadedNames } = reloadHtmlPages(
3559
+ changes.rebuildGroups,
3560
+ server
3561
+ );
3562
+ consola5.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
3563
+ break;
3564
+ case "content-script-reload":
3565
+ reloadContentScripts(changes.changedSteps, server);
3566
+ const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
3567
+ consola5.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
3568
+ break;
3569
+ }
3570
+ } catch (err) {
3556
3571
  }
3557
3572
  });
3558
3573
  };
@@ -3663,6 +3678,16 @@ async function initialize(options) {
3663
3678
  input.directory ??= options.directory;
3664
3679
  input.template ??= defaultTemplate;
3665
3680
  input.packageManager ??= options.packageManager;
3681
+ const isExists = await fs15.pathExists(input.directory);
3682
+ if (isExists) {
3683
+ const isEmpty = (await fs15.readdir(input.directory)).length === 0;
3684
+ if (!isEmpty) {
3685
+ consola6.error(
3686
+ `The directory ${path8.resolve(input.directory)} is not empty. Aborted.`
3687
+ );
3688
+ process.exit(1);
3689
+ }
3690
+ }
3666
3691
  await cloneProject(input);
3667
3692
  const cdPath = path8.relative(process.cwd(), path8.resolve(input.directory));
3668
3693
  console.log();
@@ -3692,7 +3717,8 @@ async function listTemplates() {
3692
3717
  return l.name.localeCompare(r.name);
3693
3718
  });
3694
3719
  } catch (err) {
3695
- throw Error(`Cannot load templates: ${JSON.stringify(err, null, 2)}`);
3720
+ consola6.error(err);
3721
+ throw Error(`Failed to load templates`);
3696
3722
  }
3697
3723
  }
3698
3724
  async function cloneProject({
@@ -3774,9 +3800,9 @@ async function zip(config) {
3774
3800
  await zipDir(wxt.config.zip.sourcesRoot, sourcesZipPath, {
3775
3801
  include: wxt.config.zip.includeSources,
3776
3802
  exclude: wxt.config.zip.excludeSources,
3777
- transform(file, content) {
3778
- if (file.endsWith("package.json")) {
3779
- return addOverridesToPackageJson(content, overrides);
3803
+ transform(absolutePath, zipPath, content) {
3804
+ if (zipPath.endsWith("package.json")) {
3805
+ return addOverridesToPackageJson(absolutePath, content, overrides);
3780
3806
  }
3781
3807
  },
3782
3808
  additionalFiles: downloadedPackages
@@ -3817,7 +3843,7 @@ async function zipDir(directory, outputPath, options) {
3817
3843
  const content = await fs16.readFile(absolutePath, "utf-8");
3818
3844
  archive.file(
3819
3845
  file,
3820
- await options?.transform?.(file, content) || content
3846
+ await options?.transform?.(absolutePath, file, content) || content
3821
3847
  );
3822
3848
  } else {
3823
3849
  const content = await fs16.readFile(absolutePath);
@@ -3848,22 +3874,23 @@ async function downloadPrivatePackages() {
3848
3874
  wxt.config.zip.downloadedPackagesDir
3849
3875
  );
3850
3876
  files.push(tgzPath);
3851
- overrides[id] = "file://./" + normalizePath(path9.relative(wxt.config.root, tgzPath));
3877
+ overrides[id] = tgzPath;
3852
3878
  }
3853
3879
  }
3854
3880
  return { overrides, files };
3855
3881
  }
3856
- function addOverridesToPackageJson(content, overrides) {
3882
+ function addOverridesToPackageJson(absolutePackageJsonPath, content, overrides) {
3857
3883
  if (Object.keys(overrides).length === 0)
3858
3884
  return content;
3885
+ const packageJsonDir = path9.dirname(absolutePackageJsonPath);
3859
3886
  const oldPackage = JSON.parse(content);
3860
3887
  const newPackage = {
3861
3888
  ...oldPackage,
3862
- [wxt.pm.overridesKey]: {
3863
- ...oldPackage[wxt.pm.overridesKey],
3864
- ...overrides
3865
- }
3889
+ [wxt.pm.overridesKey]: { ...oldPackage[wxt.pm.overridesKey] }
3866
3890
  };
3891
+ Object.entries(overrides).forEach(([key, absolutePath]) => {
3892
+ newPackage[wxt.pm.overridesKey][key] = "file://./" + normalizePath(path9.relative(packageJsonDir, absolutePath));
3893
+ });
3867
3894
  return JSON.stringify(newPackage, null, 2);
3868
3895
  }
3869
3896
 
@@ -3952,7 +3979,7 @@ cli.command("build [root]", "build for production").option("-c, --config <file>"
3952
3979
  {
3953
3980
  type: []
3954
3981
  }
3955
- ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").action(
3982
+ ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").option("--analyze-open", "automatically open stats.html in browser").action(
3956
3983
  wrapAction(async (root, flags) => {
3957
3984
  await build({
3958
3985
  root,
@@ -3961,7 +3988,10 @@ cli.command("build [root]", "build for production").option("-c, --config <file>"
3961
3988
  manifestVersion: flags.mv3 ? 3 : flags.mv2 ? 2 : void 0,
3962
3989
  configFile: flags.config,
3963
3990
  debug: flags.debug,
3964
- analysis: flags.analyze ? { enabled: true } : void 0,
3991
+ analysis: flags.analyze ? {
3992
+ enabled: true,
3993
+ open: flags.analyzeOpen
3994
+ } : void 0,
3965
3995
  filterEntrypoints: getArrayFromFlags(flags, "filterEntrypoint")
3966
3996
  });
3967
3997
  })
package/dist/client.d.ts CHANGED
@@ -167,7 +167,7 @@ interface ContentScriptAnchoredOptions {
167
167
  * In combination with `anchor`, decide how to add the UI to the DOM.
168
168
  *
169
169
  * - `"last"` (default) - Add the UI as the last child of the `anchor` element
170
- * - `"first"` - Add the UI as the last child of the `anchor` element
170
+ * - `"first"` - Add the UI as the first child of the `anchor` element
171
171
  * - `"replace"` - Replace the `anchor` element with the UI.
172
172
  * - `"before"` - Add the UI as the sibling before the `anchor` element
173
173
  * - `"after"` - Add the UI as the sibling after the `anchor` element
@@ -346,6 +346,12 @@ interface InlineConfig {
346
346
  * @default false
347
347
  */
348
348
  enabled?: boolean;
349
+ /**
350
+ * Set to true to automatically open the `stats.html` file when the build is finished. When building in CI, the browser will never open.
351
+ *
352
+ * @default false
353
+ */
354
+ open?: boolean;
349
355
  /**
350
356
  * When running `wxt build --analyze` or setting `analysis.enabled` to true, customize how the
351
357
  * bundle will be visualized. See
@@ -1046,6 +1052,7 @@ interface ResolvedConfig {
1046
1052
  transformManifest: (manifest: Manifest.WebExtensionManifest) => void;
1047
1053
  analysis: {
1048
1054
  enabled: boolean;
1055
+ open: boolean;
1049
1056
  template: NonNullable<PluginVisualizerOptions['template']>;
1050
1057
  /** Absolute file path to the `stats.html` file */
1051
1058
  outputFile: string;
@@ -346,6 +346,12 @@ interface InlineConfig {
346
346
  * @default false
347
347
  */
348
348
  enabled?: boolean;
349
+ /**
350
+ * Set to true to automatically open the `stats.html` file when the build is finished. When building in CI, the browser will never open.
351
+ *
352
+ * @default false
353
+ */
354
+ open?: boolean;
349
355
  /**
350
356
  * When running `wxt build --analyze` or setting `analysis.enabled` to true, customize how the
351
357
  * bundle will be visualized. See
@@ -1046,6 +1052,7 @@ interface ResolvedConfig {
1046
1052
  transformManifest: (manifest: Manifest.WebExtensionManifest) => void;
1047
1053
  analysis: {
1048
1054
  enabled: boolean;
1055
+ open: boolean;
1049
1056
  template: NonNullable<PluginVisualizerOptions['template']>;
1050
1057
  /** Absolute file path to the `stats.html` file */
1051
1058
  outputFile: string;
package/dist/index.cjs CHANGED
@@ -2693,6 +2693,7 @@ async function buildEntrypoints(groups, spinner) {
2693
2693
  try {
2694
2694
  steps.push(await wxt.config.builder.build(group));
2695
2695
  } catch (err) {
2696
+ spinner.stop().clear();
2696
2697
  wxt.logger.error(err);
2697
2698
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
2698
2699
  }
@@ -4399,6 +4400,7 @@ async function resolveConfig(inlineConfig, command, server) {
4399
4400
  },
4400
4401
  analysis: {
4401
4402
  enabled: mergedConfig.analysis?.enabled ?? false,
4403
+ open: mergedConfig.analysis?.open ?? false,
4402
4404
  template: mergedConfig.analysis?.template ?? "treemap",
4403
4405
  outputFile: analysisOutputFile,
4404
4406
  outputDir: analysisOutputDir,
@@ -4834,7 +4836,7 @@ function getChunkSortWeight(filename) {
4834
4836
  var import_picocolors4 = __toESM(require("picocolors"), 1);
4835
4837
 
4836
4838
  // package.json
4837
- var version = "0.17.6";
4839
+ var version = "0.17.8";
4838
4840
 
4839
4841
  // src/core/utils/log/printHeader.ts
4840
4842
  var import_consola2 = require("consola");
@@ -5556,6 +5558,7 @@ var ValidationError = class extends Error {
5556
5558
  // src/core/utils/building/internal-build.ts
5557
5559
  var import_consola3 = __toESM(require("consola"), 1);
5558
5560
  var import_rollup_plugin_visualizer2 = require("@aklinker1/rollup-plugin-visualizer");
5561
+ var import_ci_info = require("ci-info");
5559
5562
  async function internalBuild() {
5560
5563
  await wxt.hooks.callHook("build:before", wxt);
5561
5564
  const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
@@ -5598,6 +5601,15 @@ async function internalBuild() {
5598
5601
  `Analysis complete:
5599
5602
  ${import_picocolors5.default.gray("\u2514\u2500")} ${import_picocolors5.default.yellow(statsPath)}`
5600
5603
  );
5604
+ if (wxt.config.analysis.open) {
5605
+ if (import_ci_info.isCI) {
5606
+ wxt.logger.debug(`Skipped opening ${import_picocolors5.default.yellow(statsPath)} in CI`);
5607
+ } else {
5608
+ wxt.logger.info(`Opening ${import_picocolors5.default.yellow(statsPath)} in browser...`);
5609
+ const { default: open } = await import("open");
5610
+ open(wxt.config.analysis.outputFile);
5611
+ }
5612
+ }
5601
5613
  }
5602
5614
  return output;
5603
5615
  }
@@ -5954,30 +5966,33 @@ function createFileReloader(server) {
5954
5966
  `Changed: ${Array.from(new Set(fileChanges)).map((file) => import_picocolors7.default.dim((0, import_node_path20.relative)(wxt.config.root, file))).join(", ")}`
5955
5967
  );
5956
5968
  const allEntrypoints = await findEntrypoints();
5957
- const { output: newOutput } = await rebuild(
5958
- allEntrypoints,
5959
- // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
5960
- changes.rebuildGroups,
5961
- changes.cachedOutput
5962
- );
5963
- server.currentOutput = newOutput;
5964
- switch (changes.type) {
5965
- case "extension-reload":
5966
- server.reloadExtension();
5967
- import_consola5.consola.success(`Reloaded extension`);
5968
- break;
5969
- case "html-reload":
5970
- const { reloadedNames } = reloadHtmlPages(
5971
- changes.rebuildGroups,
5972
- server
5973
- );
5974
- import_consola5.consola.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
5975
- break;
5976
- case "content-script-reload":
5977
- reloadContentScripts(changes.changedSteps, server);
5978
- const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
5979
- import_consola5.consola.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
5980
- break;
5969
+ try {
5970
+ const { output: newOutput } = await rebuild(
5971
+ allEntrypoints,
5972
+ // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
5973
+ changes.rebuildGroups,
5974
+ changes.cachedOutput
5975
+ );
5976
+ server.currentOutput = newOutput;
5977
+ switch (changes.type) {
5978
+ case "extension-reload":
5979
+ server.reloadExtension();
5980
+ import_consola5.consola.success(`Reloaded extension`);
5981
+ break;
5982
+ case "html-reload":
5983
+ const { reloadedNames } = reloadHtmlPages(
5984
+ changes.rebuildGroups,
5985
+ server
5986
+ );
5987
+ import_consola5.consola.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
5988
+ break;
5989
+ case "content-script-reload":
5990
+ reloadContentScripts(changes.changedSteps, server);
5991
+ const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
5992
+ import_consola5.consola.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
5993
+ break;
5994
+ }
5995
+ } catch (err) {
5981
5996
  }
5982
5997
  });
5983
5998
  };
@@ -6088,6 +6103,16 @@ async function initialize(options) {
6088
6103
  input.directory ??= options.directory;
6089
6104
  input.template ??= defaultTemplate;
6090
6105
  input.packageManager ??= options.packageManager;
6106
+ const isExists = await import_fs_extra16.default.pathExists(input.directory);
6107
+ if (isExists) {
6108
+ const isEmpty = (await import_fs_extra16.default.readdir(input.directory)).length === 0;
6109
+ if (!isEmpty) {
6110
+ import_consola6.consola.error(
6111
+ `The directory ${import_node_path21.default.resolve(input.directory)} is not empty. Aborted.`
6112
+ );
6113
+ process.exit(1);
6114
+ }
6115
+ }
6091
6116
  await cloneProject(input);
6092
6117
  const cdPath = import_node_path21.default.relative(process.cwd(), import_node_path21.default.resolve(input.directory));
6093
6118
  console.log();
@@ -6117,7 +6142,8 @@ async function listTemplates() {
6117
6142
  return l.name.localeCompare(r.name);
6118
6143
  });
6119
6144
  } catch (err) {
6120
- throw Error(`Cannot load templates: ${JSON.stringify(err, null, 2)}`);
6145
+ import_consola6.consola.error(err);
6146
+ throw Error(`Failed to load templates`);
6121
6147
  }
6122
6148
  }
6123
6149
  async function cloneProject({
@@ -6199,9 +6225,9 @@ async function zip(config) {
6199
6225
  await zipDir(wxt.config.zip.sourcesRoot, sourcesZipPath, {
6200
6226
  include: wxt.config.zip.includeSources,
6201
6227
  exclude: wxt.config.zip.excludeSources,
6202
- transform(file, content) {
6203
- if (file.endsWith("package.json")) {
6204
- return addOverridesToPackageJson(content, overrides);
6228
+ transform(absolutePath, zipPath, content) {
6229
+ if (zipPath.endsWith("package.json")) {
6230
+ return addOverridesToPackageJson(absolutePath, content, overrides);
6205
6231
  }
6206
6232
  },
6207
6233
  additionalFiles: downloadedPackages
@@ -6242,7 +6268,7 @@ async function zipDir(directory, outputPath, options) {
6242
6268
  const content = await import_fs_extra17.default.readFile(absolutePath, "utf-8");
6243
6269
  archive.file(
6244
6270
  file,
6245
- await options?.transform?.(file, content) || content
6271
+ await options?.transform?.(absolutePath, file, content) || content
6246
6272
  );
6247
6273
  } else {
6248
6274
  const content = await import_fs_extra17.default.readFile(absolutePath);
@@ -6273,22 +6299,23 @@ async function downloadPrivatePackages() {
6273
6299
  wxt.config.zip.downloadedPackagesDir
6274
6300
  );
6275
6301
  files.push(tgzPath);
6276
- overrides[id] = "file://./" + normalizePath(import_node_path22.default.relative(wxt.config.root, tgzPath));
6302
+ overrides[id] = tgzPath;
6277
6303
  }
6278
6304
  }
6279
6305
  return { overrides, files };
6280
6306
  }
6281
- function addOverridesToPackageJson(content, overrides) {
6307
+ function addOverridesToPackageJson(absolutePackageJsonPath, content, overrides) {
6282
6308
  if (Object.keys(overrides).length === 0)
6283
6309
  return content;
6310
+ const packageJsonDir = import_node_path22.default.dirname(absolutePackageJsonPath);
6284
6311
  const oldPackage = JSON.parse(content);
6285
6312
  const newPackage = {
6286
6313
  ...oldPackage,
6287
- [wxt.pm.overridesKey]: {
6288
- ...oldPackage[wxt.pm.overridesKey],
6289
- ...overrides
6290
- }
6314
+ [wxt.pm.overridesKey]: { ...oldPackage[wxt.pm.overridesKey] }
6291
6315
  };
6316
+ Object.entries(overrides).forEach(([key, absolutePath]) => {
6317
+ newPackage[wxt.pm.overridesKey][key] = "file://./" + normalizePath(import_node_path22.default.relative(packageJsonDir, absolutePath));
6318
+ });
6292
6319
  return JSON.stringify(newPackage, null, 2);
6293
6320
  }
6294
6321
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-l43sonfW.cjs';
2
- export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, F as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, a5 as Dependency, p as Entrypoint, q as EntrypointGroup, $ as EslintGlobalsPropValue, a0 as Eslintrc, Z as ExtensionRunner, Y as FsCache, G as GenericEntrypoint, N as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, R as ReloadContentScriptPayload, X as ResolvedConfig, a1 as ResolvedEslintrc, z as ResolvedPerBrowserOptions, K as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, A as UserManifest, D as UserManifestFn, _ as VirtualEntrypointType, V as Wxt, H as WxtBuilder, J as WxtBuilderServer, Q as WxtHooks, a4 as WxtPackageManager, a3 as WxtResolvedUnimportOptions, a2 as WxtUnimportOptions, a as WxtViteConfig } from './index-l43sonfW.cjs';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-cFBbMXAl.cjs';
2
+ export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, F as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, a5 as Dependency, p as Entrypoint, q as EntrypointGroup, $ as EslintGlobalsPropValue, a0 as Eslintrc, Z as ExtensionRunner, Y as FsCache, G as GenericEntrypoint, N as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, R as ReloadContentScriptPayload, X as ResolvedConfig, a1 as ResolvedEslintrc, z as ResolvedPerBrowserOptions, K as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, A as UserManifest, D as UserManifestFn, _ as VirtualEntrypointType, V as Wxt, H as WxtBuilder, J as WxtBuilderServer, Q as WxtHooks, a4 as WxtPackageManager, a3 as WxtResolvedUnimportOptions, a2 as WxtUnimportOptions, a as WxtViteConfig } from './index-cFBbMXAl.cjs';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -65,6 +65,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
65
65
  */
66
66
  declare function zip(config?: InlineConfig): Promise<string[]>;
67
67
 
68
- var version = "0.17.6";
68
+ var version = "0.17.8";
69
69
 
70
70
  export { BuildOutput, ExtensionRunnerConfig, InlineConfig, UserConfig, WxtDevServer, build, clean, createServer, defineConfig, defineRunnerConfig, initialize, prepare, version, zip };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-l43sonfW.js';
2
- export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, F as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, a5 as Dependency, p as Entrypoint, q as EntrypointGroup, $ as EslintGlobalsPropValue, a0 as Eslintrc, Z as ExtensionRunner, Y as FsCache, G as GenericEntrypoint, N as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, R as ReloadContentScriptPayload, X as ResolvedConfig, a1 as ResolvedEslintrc, z as ResolvedPerBrowserOptions, K as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, A as UserManifest, D as UserManifestFn, _ as VirtualEntrypointType, V as Wxt, H as WxtBuilder, J as WxtBuilderServer, Q as WxtHooks, a4 as WxtPackageManager, a3 as WxtResolvedUnimportOptions, a2 as WxtUnimportOptions, a as WxtViteConfig } from './index-l43sonfW.js';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-cFBbMXAl.js';
2
+ export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, F as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, a5 as Dependency, p as Entrypoint, q as EntrypointGroup, $ as EslintGlobalsPropValue, a0 as Eslintrc, Z as ExtensionRunner, Y as FsCache, G as GenericEntrypoint, N as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, R as ReloadContentScriptPayload, X as ResolvedConfig, a1 as ResolvedEslintrc, z as ResolvedPerBrowserOptions, K as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, A as UserManifest, D as UserManifestFn, _ as VirtualEntrypointType, V as Wxt, H as WxtBuilder, J as WxtBuilderServer, Q as WxtHooks, a4 as WxtPackageManager, a3 as WxtResolvedUnimportOptions, a2 as WxtUnimportOptions, a as WxtViteConfig } from './index-cFBbMXAl.js';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -65,6 +65,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
65
65
  */
66
66
  declare function zip(config?: InlineConfig): Promise<string[]>;
67
67
 
68
- var version = "0.17.6";
68
+ var version = "0.17.8";
69
69
 
70
70
  export { BuildOutput, ExtensionRunnerConfig, InlineConfig, UserConfig, WxtDevServer, build, clean, createServer, defineConfig, defineRunnerConfig, initialize, prepare, version, zip };
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  unnormalizePath,
19
19
  version,
20
20
  wxt
21
- } from "./chunk-3ZE2CHPV.js";
21
+ } from "./chunk-5XQOZCZF.js";
22
22
  import "./chunk-VBXJIVYU.js";
23
23
 
24
24
  // src/core/build.ts
@@ -332,30 +332,33 @@ function createFileReloader(server) {
332
332
  `Changed: ${Array.from(new Set(fileChanges)).map((file) => pc2.dim(relative4(wxt.config.root, file))).join(", ")}`
333
333
  );
334
334
  const allEntrypoints = await findEntrypoints();
335
- const { output: newOutput } = await rebuild(
336
- allEntrypoints,
337
- // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
338
- changes.rebuildGroups,
339
- changes.cachedOutput
340
- );
341
- server.currentOutput = newOutput;
342
- switch (changes.type) {
343
- case "extension-reload":
344
- server.reloadExtension();
345
- consola2.success(`Reloaded extension`);
346
- break;
347
- case "html-reload":
348
- const { reloadedNames } = reloadHtmlPages(
349
- changes.rebuildGroups,
350
- server
351
- );
352
- consola2.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
353
- break;
354
- case "content-script-reload":
355
- reloadContentScripts(changes.changedSteps, server);
356
- const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
357
- consola2.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
358
- break;
335
+ try {
336
+ const { output: newOutput } = await rebuild(
337
+ allEntrypoints,
338
+ // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
339
+ changes.rebuildGroups,
340
+ changes.cachedOutput
341
+ );
342
+ server.currentOutput = newOutput;
343
+ switch (changes.type) {
344
+ case "extension-reload":
345
+ server.reloadExtension();
346
+ consola2.success(`Reloaded extension`);
347
+ break;
348
+ case "html-reload":
349
+ const { reloadedNames } = reloadHtmlPages(
350
+ changes.rebuildGroups,
351
+ server
352
+ );
353
+ consola2.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
354
+ break;
355
+ case "content-script-reload":
356
+ reloadContentScripts(changes.changedSteps, server);
357
+ const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
358
+ consola2.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
359
+ break;
360
+ }
361
+ } catch (err) {
359
362
  }
360
363
  });
361
364
  };
@@ -466,6 +469,16 @@ async function initialize(options) {
466
469
  input.directory ??= options.directory;
467
470
  input.template ??= defaultTemplate;
468
471
  input.packageManager ??= options.packageManager;
472
+ const isExists = await fs2.pathExists(input.directory);
473
+ if (isExists) {
474
+ const isEmpty = (await fs2.readdir(input.directory)).length === 0;
475
+ if (!isEmpty) {
476
+ consola3.error(
477
+ `The directory ${path2.resolve(input.directory)} is not empty. Aborted.`
478
+ );
479
+ process.exit(1);
480
+ }
481
+ }
469
482
  await cloneProject(input);
470
483
  const cdPath = path2.relative(process.cwd(), path2.resolve(input.directory));
471
484
  console.log();
@@ -495,7 +508,8 @@ async function listTemplates() {
495
508
  return l.name.localeCompare(r.name);
496
509
  });
497
510
  } catch (err) {
498
- throw Error(`Cannot load templates: ${JSON.stringify(err, null, 2)}`);
511
+ consola3.error(err);
512
+ throw Error(`Failed to load templates`);
499
513
  }
500
514
  }
501
515
  async function cloneProject({
@@ -577,9 +591,9 @@ async function zip(config) {
577
591
  await zipDir(wxt.config.zip.sourcesRoot, sourcesZipPath, {
578
592
  include: wxt.config.zip.includeSources,
579
593
  exclude: wxt.config.zip.excludeSources,
580
- transform(file, content) {
581
- if (file.endsWith("package.json")) {
582
- return addOverridesToPackageJson(content, overrides);
594
+ transform(absolutePath, zipPath, content) {
595
+ if (zipPath.endsWith("package.json")) {
596
+ return addOverridesToPackageJson(absolutePath, content, overrides);
583
597
  }
584
598
  },
585
599
  additionalFiles: downloadedPackages
@@ -620,7 +634,7 @@ async function zipDir(directory, outputPath, options) {
620
634
  const content = await fs3.readFile(absolutePath, "utf-8");
621
635
  archive.file(
622
636
  file,
623
- await options?.transform?.(file, content) || content
637
+ await options?.transform?.(absolutePath, file, content) || content
624
638
  );
625
639
  } else {
626
640
  const content = await fs3.readFile(absolutePath);
@@ -651,22 +665,23 @@ async function downloadPrivatePackages() {
651
665
  wxt.config.zip.downloadedPackagesDir
652
666
  );
653
667
  files.push(tgzPath);
654
- overrides[id] = "file://./" + normalizePath(path3.relative(wxt.config.root, tgzPath));
668
+ overrides[id] = tgzPath;
655
669
  }
656
670
  }
657
671
  return { overrides, files };
658
672
  }
659
- function addOverridesToPackageJson(content, overrides) {
673
+ function addOverridesToPackageJson(absolutePackageJsonPath, content, overrides) {
660
674
  if (Object.keys(overrides).length === 0)
661
675
  return content;
676
+ const packageJsonDir = path3.dirname(absolutePackageJsonPath);
662
677
  const oldPackage = JSON.parse(content);
663
678
  const newPackage = {
664
679
  ...oldPackage,
665
- [wxt.pm.overridesKey]: {
666
- ...oldPackage[wxt.pm.overridesKey],
667
- ...overrides
668
- }
680
+ [wxt.pm.overridesKey]: { ...oldPackage[wxt.pm.overridesKey] }
669
681
  };
682
+ Object.entries(overrides).forEach(([key, absolutePath]) => {
683
+ newPackage[wxt.pm.overridesKey][key] = "file://./" + normalizePath(path3.relative(packageJsonDir, absolutePath));
684
+ });
670
685
  return JSON.stringify(newPackage, null, 2);
671
686
  }
672
687
  export {
package/dist/testing.cjs CHANGED
@@ -1084,6 +1084,7 @@ async function resolveConfig(inlineConfig, command, server) {
1084
1084
  },
1085
1085
  analysis: {
1086
1086
  enabled: mergedConfig.analysis?.enabled ?? false,
1087
+ open: mergedConfig.analysis?.open ?? false,
1087
1088
  template: mergedConfig.analysis?.template ?? "treemap",
1088
1089
  outputFile: analysisOutputFile,
1089
1090
  outputDir: analysisOutputDir,
@@ -1301,6 +1302,7 @@ var import_defu2 = __toESM(require("defu"), 1);
1301
1302
  var import_node_path13 = require("path");
1302
1303
  var import_consola3 = __toESM(require("consola"), 1);
1303
1304
  var import_rollup_plugin_visualizer2 = require("@aklinker1/rollup-plugin-visualizer");
1305
+ var import_ci_info = require("ci-info");
1304
1306
 
1305
1307
  // src/testing/wxt-vitest-plugin.ts
1306
1308
  function WxtVitest(inlineConfig) {
@@ -1,6 +1,6 @@
1
1
  export { FakeBrowser, fakeBrowser } from '@webext-core/fake-browser';
2
2
  import * as vite from 'vite';
3
- import { I as InlineConfig } from './index-l43sonfW.cjs';
3
+ import { I as InlineConfig } from './index-cFBbMXAl.cjs';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
6
6
  import 'consola';
package/dist/testing.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { FakeBrowser, fakeBrowser } from '@webext-core/fake-browser';
2
2
  import * as vite from 'vite';
3
- import { I as InlineConfig } from './index-l43sonfW.js';
3
+ import { I as InlineConfig } from './index-cFBbMXAl.js';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
6
6
  import 'consola';
package/dist/testing.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  tsconfigPaths,
6
6
  unimport,
7
7
  webextensionPolyfillMock
8
- } from "./chunk-3ZE2CHPV.js";
8
+ } from "./chunk-5XQOZCZF.js";
9
9
  import "./chunk-VBXJIVYU.js";
10
10
 
11
11
  // src/testing/fake-browser.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wxt",
3
3
  "type": "module",
4
- "version": "0.17.6",
4
+ "version": "0.17.8",
5
5
  "description": "Next gen framework for developing web extensions",
6
6
  "engines": {
7
7
  "node": ">=18",
@@ -94,6 +94,7 @@
94
94
  "c12": "^1.5.1",
95
95
  "cac": "^6.7.14",
96
96
  "chokidar": "^3.5.3",
97
+ "ci-info": "^4.0.0",
97
98
  "consola": "^3.2.3",
98
99
  "defu": "^6.1.3",
99
100
  "dequal": "^2.0.3",
@@ -113,6 +114,7 @@
113
114
  "natural-compare": "^1.4.0",
114
115
  "normalize-path": "^3.0.0",
115
116
  "nypm": "^0.3.6",
117
+ "open": "^10.1.0",
116
118
  "ora": "^7.0.1",
117
119
  "picocolors": "^1.0.0",
118
120
  "prompts": "^2.4.2",
@@ -150,6 +152,7 @@
150
152
  "vitepress": "1.0.0-rc.34",
151
153
  "vitest": "^1.2.2",
152
154
  "vitest-mock-extended": "^1.3.1",
155
+ "vitest-plugin-random-seed": "^1.0.2",
153
156
  "vue": "^3.3.10"
154
157
  },
155
158
  "packageManager": "pnpm@8.6.3",