wxt 0.14.5 → 0.14.7

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/dist/index.cjs CHANGED
@@ -130,12 +130,12 @@ var require_isexe = __commonJS({
130
130
  if (typeof Promise !== "function") {
131
131
  throw new TypeError("callback not provided");
132
132
  }
133
- return new Promise(function(resolve14, reject) {
133
+ return new Promise(function(resolve15, reject) {
134
134
  isexe(path10, options || {}, function(er, is) {
135
135
  if (er) {
136
136
  reject(er);
137
137
  } else {
138
- resolve14(is);
138
+ resolve15(is);
139
139
  }
140
140
  });
141
141
  });
@@ -202,27 +202,27 @@ var require_which = __commonJS({
202
202
  opt = {};
203
203
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
204
204
  const found = [];
205
- const step = (i) => new Promise((resolve14, reject) => {
205
+ const step = (i) => new Promise((resolve15, reject) => {
206
206
  if (i === pathEnv.length)
207
- return opt.all && found.length ? resolve14(found) : reject(getNotFoundError(cmd));
207
+ return opt.all && found.length ? resolve15(found) : reject(getNotFoundError(cmd));
208
208
  const ppRaw = pathEnv[i];
209
209
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
210
210
  const pCmd = path10.join(pathPart, cmd);
211
211
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
212
- resolve14(subStep(p, i, 0));
212
+ resolve15(subStep(p, i, 0));
213
213
  });
214
- const subStep = (p, i, ii) => new Promise((resolve14, reject) => {
214
+ const subStep = (p, i, ii) => new Promise((resolve15, reject) => {
215
215
  if (ii === pathExt.length)
216
- return resolve14(step(i + 1));
216
+ return resolve15(step(i + 1));
217
217
  const ext = pathExt[ii];
218
218
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
219
219
  if (!er && is) {
220
220
  if (opt.all)
221
221
  found.push(p + ext);
222
222
  else
223
- return resolve14(p + ext);
223
+ return resolve15(p + ext);
224
224
  }
225
- return resolve14(subStep(p, i, ii + 1));
225
+ return resolve15(subStep(p, i, ii + 1));
226
226
  });
227
227
  });
228
228
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -1529,7 +1529,7 @@ var init_kill = __esm({
1529
1529
  return spawnedPromise;
1530
1530
  }
1531
1531
  let timeoutId;
1532
- const timeoutPromise = new Promise((resolve14, reject) => {
1532
+ const timeoutPromise = new Promise((resolve15, reject) => {
1533
1533
  timeoutId = setTimeout(() => {
1534
1534
  timeoutKill(spawned, killSignal, reject);
1535
1535
  }, timeout);
@@ -2013,9 +2013,9 @@ var init_promise = __esm({
2013
2013
  Reflect.defineProperty(spawned, property, { ...descriptor, value });
2014
2014
  }
2015
2015
  };
2016
- getSpawnedPromise = (spawned) => new Promise((resolve14, reject) => {
2016
+ getSpawnedPromise = (spawned) => new Promise((resolve15, reject) => {
2017
2017
  spawned.on("exit", (exitCode, signal) => {
2018
- resolve14({ exitCode, signal });
2018
+ resolve15({ exitCode, signal });
2019
2019
  });
2020
2020
  spawned.on("error", (error) => {
2021
2021
  reject(error);
@@ -2465,9 +2465,14 @@ async function buildEntrypoints(groups, config, spinner) {
2465
2465
  const steps = [];
2466
2466
  for (let i = 0; i < groups.length; i++) {
2467
2467
  const group = groups[i];
2468
- const groupNames = [group].flat().map((e) => e.name).join(import_picocolors.default.dim(", "));
2469
- spinner.text = import_picocolors.default.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNames}`;
2470
- steps.push(await config.builder.build(group));
2468
+ const groupNames = [group].flat().map((e) => e.name);
2469
+ const groupNameColored = groupNames.join(import_picocolors.default.dim(", "));
2470
+ spinner.text = import_picocolors.default.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
2471
+ try {
2472
+ steps.push(await config.builder.build(group));
2473
+ } catch (err) {
2474
+ throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
2475
+ }
2471
2476
  }
2472
2477
  const publicAssets = await copyPublicDirectory(config);
2473
2478
  return { publicAssets, steps };
@@ -2497,11 +2502,27 @@ function every(array, predicate) {
2497
2502
  return false;
2498
2503
  return true;
2499
2504
  }
2505
+ function some(array, predicate) {
2506
+ for (let i = 0; i < array.length; i++)
2507
+ if (predicate(array[i], i))
2508
+ return true;
2509
+ return false;
2510
+ }
2500
2511
 
2501
2512
  // src/core/utils/building/detect-dev-changes.ts
2502
- function detectDevChanges(changedFiles, currentOutput) {
2503
- if (currentOutput == null)
2504
- return { type: "no-change" };
2513
+ function detectDevChanges(config, changedFiles, currentOutput) {
2514
+ const isConfigChange = some(
2515
+ changedFiles,
2516
+ (file) => file === config.userConfigMetadata.configFile
2517
+ );
2518
+ if (isConfigChange)
2519
+ return { type: "full-restart" };
2520
+ const isRunnerChange = some(
2521
+ changedFiles,
2522
+ (file) => file === config.runnerConfig.configFile
2523
+ );
2524
+ if (isRunnerChange)
2525
+ return { type: "browser-restart" };
2505
2526
  const changedSteps = new Set(
2506
2527
  changedFiles.flatMap(
2507
2528
  (changedFile) => findEffectedSteps(changedFile, currentOutput)
@@ -2533,7 +2554,7 @@ function detectDevChanges(changedFiles, currentOutput) {
2533
2554
  unchangedOutput.publicAssets.push(asset);
2534
2555
  }
2535
2556
  }
2536
- const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, ([_, file]) => file.endsWith(".html"));
2557
+ const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, (file) => file.endsWith(".html"));
2537
2558
  if (isOnlyHtmlChanges) {
2538
2559
  return {
2539
2560
  type: "html-reload",
@@ -2561,7 +2582,7 @@ function detectDevChanges(changedFiles, currentOutput) {
2561
2582
  }
2562
2583
  function findEffectedSteps(changedFile, currentOutput) {
2563
2584
  const changes = [];
2564
- const changedPath = normalizePath(changedFile[1]);
2585
+ const changedPath = normalizePath(changedFile);
2565
2586
  const isChunkEffected = (chunk) => (
2566
2587
  // If it's an HTML file with the same path, is is effected because HTML files need to be pre-rendered
2567
2588
  // fileName is normalized, relative bundle path
@@ -3912,6 +3933,9 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
3912
3933
  async listen() {
3913
3934
  await viteServer.listen(info.port);
3914
3935
  },
3936
+ async close() {
3937
+ await viteServer.close();
3938
+ },
3915
3939
  transformHtml(...args) {
3916
3940
  return viteServer.transformIndexHtml(...args);
3917
3941
  },
@@ -4247,15 +4271,15 @@ async function importEntrypointFile(path10, config) {
4247
4271
  const res = await jiti(path10);
4248
4272
  return res.default;
4249
4273
  } catch (err) {
4274
+ const filePath = (0, import_node_path8.relative)(config.root, path10);
4250
4275
  if (err instanceof ReferenceError) {
4251
4276
  const variableName = err.message.replace(" is not defined", "");
4252
- const filePath = (0, import_node_path8.relative)(config.root, path10);
4253
4277
  throw Error(
4254
4278
  `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/entrypoints.html#side-effects`,
4255
4279
  { cause: err }
4256
4280
  );
4257
4281
  } else {
4258
- throw err;
4282
+ throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
4259
4283
  }
4260
4284
  }
4261
4285
  }
@@ -4381,7 +4405,7 @@ function getChunkSortWeight(filename) {
4381
4405
  var import_picocolors4 = __toESM(require("picocolors"), 1);
4382
4406
 
4383
4407
  // package.json
4384
- var version = "0.14.5";
4408
+ var version = "0.14.7";
4385
4409
 
4386
4410
  // src/core/utils/log/printHeader.ts
4387
4411
  var import_consola2 = require("consola");
@@ -4964,6 +4988,70 @@ async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput
4964
4988
  }
4965
4989
 
4966
4990
  // src/core/utils/building/internal-build.ts
4991
+ var import_manage_path = __toESM(require("manage-path"), 1);
4992
+ var import_node_path13 = require("path");
4993
+
4994
+ // src/core/utils/validation.ts
4995
+ function validateEntrypoints(entrypoints) {
4996
+ const errors = entrypoints.flatMap((entrypoint) => {
4997
+ switch (entrypoint.type) {
4998
+ case "content-script":
4999
+ return validateContentScriptEntrypoint(entrypoint);
5000
+ default:
5001
+ return validateBaseEntrypoint(entrypoint);
5002
+ }
5003
+ });
5004
+ let errorCount = 0;
5005
+ let warningCount = 0;
5006
+ for (const err of errors) {
5007
+ if (err.type === "warning")
5008
+ warningCount++;
5009
+ else
5010
+ errorCount++;
5011
+ }
5012
+ return {
5013
+ errors,
5014
+ errorCount,
5015
+ warningCount
5016
+ };
5017
+ }
5018
+ function validateContentScriptEntrypoint(definition) {
5019
+ const errors = validateBaseEntrypoint(definition);
5020
+ if (definition.options.matches == null) {
5021
+ errors.push({
5022
+ type: "error",
5023
+ message: "`matches` is required",
5024
+ value: definition.options.matches,
5025
+ entrypoint: definition
5026
+ });
5027
+ }
5028
+ return errors;
5029
+ }
5030
+ function validateBaseEntrypoint(definition) {
5031
+ const errors = [];
5032
+ if (definition.options.exclude != null && !Array.isArray(definition.options.exclude)) {
5033
+ errors.push({
5034
+ type: "error",
5035
+ message: "`exclude` must be an array of browser names",
5036
+ value: definition.options.exclude,
5037
+ entrypoint: definition
5038
+ });
5039
+ }
5040
+ if (definition.options.include != null && !Array.isArray(definition.options.include)) {
5041
+ errors.push({
5042
+ type: "error",
5043
+ message: "`include` must be an array of browser names",
5044
+ value: definition.options.include,
5045
+ entrypoint: definition
5046
+ });
5047
+ }
5048
+ return errors;
5049
+ }
5050
+ var ValidationError = class extends Error {
5051
+ };
5052
+
5053
+ // src/core/utils/building/internal-build.ts
5054
+ var import_consola3 = __toESM(require("consola"), 1);
4967
5055
  async function internalBuild(config) {
4968
5056
  const verb = config.command === "serve" ? "Pre-rendering" : "Building";
4969
5057
  const target = `${config.browser}-mv${config.manifestVersion}`;
@@ -4977,6 +5065,15 @@ async function internalBuild(config) {
4977
5065
  await import_fs_extra12.default.ensureDir(config.outDir);
4978
5066
  const entrypoints = await findEntrypoints(config);
4979
5067
  config.logger.debug("Detected entrypoints:", entrypoints);
5068
+ const validationResults = validateEntrypoints(entrypoints);
5069
+ if (validationResults.errorCount + validationResults.warningCount > 0) {
5070
+ printValidationResults(config, validationResults);
5071
+ }
5072
+ if (validationResults.errorCount > 0) {
5073
+ throw new ValidationError(`Entrypoint validation failed`, {
5074
+ cause: validationResults
5075
+ });
5076
+ }
4980
5077
  const groups = groupEntrypoints(entrypoints);
4981
5078
  const { output, warnings } = await rebuild(
4982
5079
  config,
@@ -5009,11 +5106,35 @@ async function combineAnalysisStats(config) {
5009
5106
  absolute: true
5010
5107
  });
5011
5108
  const absolutePaths = unixFiles.map(unnormalizePath);
5109
+ const alterPath = (0, import_manage_path.default)(process.env);
5110
+ alterPath.push((0, import_node_path13.resolve)(config.root, "node_modules/wxt/node_modules/.bin"));
5012
5111
  await execaCommand2(
5013
5112
  `rollup-plugin-visualizer ${absolutePaths.join(" ")} --template ${config.analysis.template}`,
5014
5113
  { cwd: config.root, stdio: "inherit" }
5015
5114
  );
5016
5115
  }
5116
+ function printValidationResults(config, { errorCount, errors, warningCount }) {
5117
+ (errorCount > 0 ? config.logger.error : config.logger.warn)(
5118
+ `Entrypoint validation failed: ${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"}`
5119
+ );
5120
+ const cwd = process.cwd();
5121
+ const entrypointErrors = errors.reduce((map, error) => {
5122
+ const entryErrors = map.get(error.entrypoint) ?? [];
5123
+ entryErrors.push(error);
5124
+ map.set(error.entrypoint, entryErrors);
5125
+ return map;
5126
+ }, /* @__PURE__ */ new Map());
5127
+ Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors2]) => {
5128
+ import_consola3.default.log((0, import_node_path13.relative)(cwd, entrypoint.inputPath));
5129
+ console.log();
5130
+ errors2.forEach((err) => {
5131
+ const type = err.type === "error" ? import_picocolors5.default.red("ERROR") : import_picocolors5.default.yellow("WARN");
5132
+ const recieved = import_picocolors5.default.dim(`(recieved: ${JSON.stringify(err.value)})`);
5133
+ import_consola3.default.log(` - ${type} ${err.message} ${recieved}`);
5134
+ });
5135
+ console.log();
5136
+ });
5137
+ }
5017
5138
 
5018
5139
  // src/core/build.ts
5019
5140
  async function build(config) {
@@ -5022,37 +5143,37 @@ async function build(config) {
5022
5143
  }
5023
5144
 
5024
5145
  // src/core/clean.ts
5025
- var import_node_path13 = __toESM(require("path"), 1);
5146
+ var import_node_path14 = __toESM(require("path"), 1);
5026
5147
  var import_fast_glob4 = __toESM(require("fast-glob"), 1);
5027
5148
  var import_fs_extra13 = __toESM(require("fs-extra"), 1);
5028
- var import_consola3 = require("consola");
5149
+ var import_consola4 = require("consola");
5029
5150
  var import_picocolors6 = __toESM(require("picocolors"), 1);
5030
5151
  async function clean(root = process.cwd()) {
5031
- import_consola3.consola.info("Cleaning Project");
5152
+ import_consola4.consola.info("Cleaning Project");
5032
5153
  const tempDirs = [
5033
5154
  "node_modules/.vite",
5034
5155
  "node_modules/.cache",
5035
5156
  "**/.wxt",
5036
5157
  ".output/*"
5037
5158
  ];
5038
- import_consola3.consola.debug("Looking for:", tempDirs.map(import_picocolors6.default.cyan).join(", "));
5159
+ import_consola4.consola.debug("Looking for:", tempDirs.map(import_picocolors6.default.cyan).join(", "));
5039
5160
  const directories = await (0, import_fast_glob4.default)(tempDirs, {
5040
- cwd: import_node_path13.default.resolve(root),
5161
+ cwd: import_node_path14.default.resolve(root),
5041
5162
  absolute: true,
5042
5163
  onlyDirectories: true,
5043
5164
  deep: 2
5044
5165
  });
5045
5166
  if (directories.length === 0) {
5046
- import_consola3.consola.debug("No generated files found.");
5167
+ import_consola4.consola.debug("No generated files found.");
5047
5168
  return;
5048
5169
  }
5049
- import_consola3.consola.debug(
5170
+ import_consola4.consola.debug(
5050
5171
  "Found:",
5051
- directories.map((dir) => import_picocolors6.default.cyan(import_node_path13.default.relative(root, dir))).join(", ")
5172
+ directories.map((dir) => import_picocolors6.default.cyan(import_node_path14.default.relative(root, dir))).join(", ")
5052
5173
  );
5053
5174
  for (const directory of directories) {
5054
5175
  await import_fs_extra13.default.rm(directory, { force: true, recursive: true });
5055
- import_consola3.consola.debug("Deleted " + import_picocolors6.default.cyan(import_node_path13.default.relative(root, directory)));
5176
+ import_consola4.consola.debug("Deleted " + import_picocolors6.default.cyan(import_node_path14.default.relative(root, directory)));
5056
5177
  }
5057
5178
  }
5058
5179
 
@@ -5067,12 +5188,12 @@ function defineRunnerConfig(config) {
5067
5188
  }
5068
5189
 
5069
5190
  // src/core/runners/wsl.ts
5070
- var import_node_path14 = require("path");
5191
+ var import_node_path15 = require("path");
5071
5192
  function createWslRunner() {
5072
5193
  return {
5073
5194
  async openBrowser(config) {
5074
5195
  config.logger.warn(
5075
- `Cannot open browser when using WSL. Load "${(0, import_node_path14.relative)(
5196
+ `Cannot open browser when using WSL. Load "${(0, import_node_path15.relative)(
5076
5197
  process.cwd(),
5077
5198
  config.outDir
5078
5199
  )}" as an unpacked extension manually`
@@ -5088,7 +5209,7 @@ function createWebExtRunner() {
5088
5209
  let runner;
5089
5210
  return {
5090
5211
  async openBrowser(config) {
5091
- config.logger.info("Opening browser...");
5212
+ const startTime = Date.now();
5092
5213
  if (config.browser === "firefox" && config.manifestVersion === 3) {
5093
5214
  throw Error(
5094
5215
  "Dev mode does not support Firefox MV3. For alternatives, see https://github.com/wxt-dev/wxt/issues/230#issuecomment-1806881653"
@@ -5133,7 +5254,8 @@ function createWebExtRunner() {
5133
5254
  config.logger.debug("web-ext options:", options);
5134
5255
  const webExt = await import("web-ext-run");
5135
5256
  runner = await webExt.default.cmd.run(finalConfig, options);
5136
- config.logger.success("Opened!");
5257
+ const duration = Date.now() - startTime;
5258
+ config.logger.success(`Opened browser in ${formatDuration(duration)}`);
5137
5259
  },
5138
5260
  async closeBrowser() {
5139
5261
  return await runner?.exit();
@@ -5144,12 +5266,12 @@ var WARN_LOG_LEVEL = 40;
5144
5266
  var ERROR_LOG_LEVEL = 50;
5145
5267
 
5146
5268
  // src/core/runners/safari.ts
5147
- var import_node_path15 = require("path");
5269
+ var import_node_path16 = require("path");
5148
5270
  function createSafariRunner() {
5149
5271
  return {
5150
5272
  async openBrowser(config) {
5151
5273
  config.logger.warn(
5152
- `Cannot Safari using web-ext. Load "${(0, import_node_path15.relative)(
5274
+ `Cannot Safari using web-ext. Load "${(0, import_node_path16.relative)(
5153
5275
  process.cwd(),
5154
5276
  config.outDir
5155
5277
  )}" as an unpacked extension manually`
@@ -5161,12 +5283,12 @@ function createSafariRunner() {
5161
5283
  }
5162
5284
 
5163
5285
  // src/core/runners/manual.ts
5164
- var import_node_path16 = require("path");
5286
+ var import_node_path17 = require("path");
5165
5287
  function createManualRunner() {
5166
5288
  return {
5167
5289
  async openBrowser(config) {
5168
5290
  config.logger.info(
5169
- `Load "${(0, import_node_path16.relative)(
5291
+ `Load "${(0, import_node_path17.relative)(
5170
5292
  process.cwd(),
5171
5293
  config.outDir
5172
5294
  )}" as an unpacked extension manually`
@@ -5195,10 +5317,10 @@ async function createExtensionRunner(config) {
5195
5317
  }
5196
5318
 
5197
5319
  // src/core/create-server.ts
5198
- var import_consola4 = require("consola");
5320
+ var import_consola5 = require("consola");
5199
5321
  var import_async_mutex = require("async-mutex");
5200
5322
  var import_picocolors7 = __toESM(require("picocolors"), 1);
5201
- var import_node_path17 = require("path");
5323
+ var import_node_path18 = require("path");
5202
5324
  async function createServer(inlineConfig) {
5203
5325
  const port = await getPort();
5204
5326
  const hostname = "localhost";
@@ -5208,19 +5330,36 @@ async function createServer(inlineConfig) {
5208
5330
  hostname,
5209
5331
  origin
5210
5332
  };
5333
+ const buildAndOpenBrowser = async () => {
5334
+ server.currentOutput = await internalBuild(config);
5335
+ await runner.openBrowser(config);
5336
+ };
5337
+ const closeAndRecreateRunner = async () => {
5338
+ await runner.closeBrowser();
5339
+ config = await getLatestConfig();
5340
+ runner = await createExtensionRunner(config);
5341
+ };
5211
5342
  const server = {
5212
5343
  ...serverInfo,
5213
- watcher: void 0,
5214
- // Filled out later down below
5215
- ws: void 0,
5216
- // Filled out later down below
5344
+ get watcher() {
5345
+ return builderServer.watcher;
5346
+ },
5347
+ get ws() {
5348
+ return builderServer.ws;
5349
+ },
5217
5350
  currentOutput: void 0,
5218
- // Filled out later down below
5219
5351
  async start() {
5220
5352
  await builderServer.listen();
5221
5353
  config.logger.success(`Started dev server @ ${serverInfo.origin}`);
5222
- server.currentOutput = await internalBuild(config);
5223
- await runner.openBrowser(config);
5354
+ await buildAndOpenBrowser();
5355
+ },
5356
+ async stop() {
5357
+ await runner.closeBrowser();
5358
+ await builderServer.close();
5359
+ },
5360
+ async restart() {
5361
+ await closeAndRecreateRunner();
5362
+ await buildAndOpenBrowser();
5224
5363
  },
5225
5364
  transformHtml(url2, html, originalUrl) {
5226
5365
  return builderServer.transformHtml(url2, html, originalUrl);
@@ -5233,17 +5372,21 @@ async function createServer(inlineConfig) {
5233
5372
  },
5234
5373
  reloadExtension() {
5235
5374
  server.ws.send("wxt:reload-extension");
5375
+ },
5376
+ async restartBrowser() {
5377
+ await closeAndRecreateRunner();
5378
+ await runner.openBrowser(config);
5236
5379
  }
5237
5380
  };
5238
5381
  const getLatestConfig = () => getInternalConfig(inlineConfig ?? {}, "serve", server);
5239
5382
  let config = await getLatestConfig();
5240
- const [runner, builderServer] = await Promise.all([
5383
+ let [runner, builderServer] = await Promise.all([
5241
5384
  createExtensionRunner(config),
5242
5385
  config.builder.createServer(server)
5243
5386
  ]);
5244
- server.watcher = builderServer.watcher;
5245
- server.ws = builderServer.ws;
5246
5387
  server.ws.on("wxt:background-initialized", () => {
5388
+ if (server.currentOutput == null)
5389
+ return;
5247
5390
  reloadContentScripts(server.currentOutput.steps, config, server);
5248
5391
  });
5249
5392
  const reloadOnChange = createFileReloader({
@@ -5271,18 +5414,34 @@ function createFileReloader(options) {
5271
5414
  return;
5272
5415
  changeQueue.push([event, path10]);
5273
5416
  await fileChangedMutex.runExclusive(async () => {
5274
- const fileChanges = changeQueue.splice(0, changeQueue.length);
5417
+ if (server.currentOutput == null)
5418
+ return;
5419
+ const fileChanges = changeQueue.splice(0, changeQueue.length).map(([_, file]) => file);
5275
5420
  if (fileChanges.length === 0)
5276
5421
  return;
5277
- const changes = detectDevChanges(fileChanges, server.currentOutput);
5422
+ const changes = detectDevChanges(
5423
+ config,
5424
+ fileChanges,
5425
+ server.currentOutput
5426
+ );
5278
5427
  if (changes.type === "no-change")
5279
5428
  return;
5429
+ if (changes.type === "full-restart") {
5430
+ config.logger.info("Config changed, restarting server...");
5431
+ server.restart();
5432
+ return;
5433
+ }
5434
+ if (changes.type === "browser-restart") {
5435
+ config.logger.info("Runner config changed, restarting browser...");
5436
+ server.restartBrowser();
5437
+ return;
5438
+ }
5280
5439
  config.logger.info(
5281
- `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => import_picocolors7.default.dim((0, import_node_path17.relative)(config.root, file))).join(", ")}`
5440
+ `Changed: ${Array.from(new Set(fileChanges)).map((file) => import_picocolors7.default.dim((0, import_node_path18.relative)(config.root, file))).join(", ")}`
5282
5441
  );
5283
5442
  const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
5284
5443
  return import_picocolors7.default.cyan(
5285
- (0, import_node_path17.relative)(config.outDir, getEntrypointOutputFile(entry, ""))
5444
+ (0, import_node_path18.relative)(config.outDir, getEntrypointOutputFile(entry, ""))
5286
5445
  );
5287
5446
  }).join(import_picocolors7.default.dim(", "));
5288
5447
  const allEntrypoints = await findEntrypoints(config);
@@ -5305,13 +5464,15 @@ function createFileReloader(options) {
5305
5464
  reloadContentScripts(changes.changedSteps, config, server);
5306
5465
  break;
5307
5466
  }
5308
- import_consola4.consola.success(`Reloaded: ${rebuiltNames}`);
5467
+ import_consola5.consola.success(`Reloaded: ${rebuiltNames}`);
5309
5468
  });
5310
5469
  };
5311
5470
  }
5312
5471
  function reloadContentScripts(steps, config, server) {
5313
5472
  if (config.manifestVersion === 3) {
5314
5473
  steps.forEach((step) => {
5474
+ if (server.currentOutput == null)
5475
+ return;
5315
5476
  const entry = step.entrypoints;
5316
5477
  if (Array.isArray(entry) || entry.type !== "content-script")
5317
5478
  return;
@@ -5348,13 +5509,13 @@ function reloadHtmlPages(groups, server, config) {
5348
5509
 
5349
5510
  // src/core/initialize.ts
5350
5511
  var import_prompts = __toESM(require("prompts"), 1);
5351
- var import_consola5 = require("consola");
5512
+ var import_consola6 = require("consola");
5352
5513
  var import_giget = require("giget");
5353
5514
  var import_fs_extra14 = __toESM(require("fs-extra"), 1);
5354
- var import_node_path18 = __toESM(require("path"), 1);
5515
+ var import_node_path19 = __toESM(require("path"), 1);
5355
5516
  var import_picocolors8 = __toESM(require("picocolors"), 1);
5356
5517
  async function initialize(options) {
5357
- import_consola5.consola.info("Initalizing new project");
5518
+ import_consola6.consola.info("Initalizing new project");
5358
5519
  const templates = await listTemplates();
5359
5520
  const defaultTemplate = templates.find(
5360
5521
  (template) => template.name === options.template?.toLowerCase().trim()
@@ -5399,17 +5560,17 @@ async function initialize(options) {
5399
5560
  input.template ??= defaultTemplate;
5400
5561
  input.packageManager ??= options.packageManager;
5401
5562
  await cloneProject(input);
5402
- const cdPath = import_node_path18.default.relative(process.cwd(), import_node_path18.default.resolve(input.directory));
5563
+ const cdPath = import_node_path19.default.relative(process.cwd(), import_node_path19.default.resolve(input.directory));
5403
5564
  console.log();
5404
- import_consola5.consola.log(
5565
+ import_consola6.consola.log(
5405
5566
  `\u2728 WXT project created with the ${TEMPLATE_COLORS[input.template.name]?.(input.template.name) ?? input.template.name} template.`
5406
5567
  );
5407
5568
  console.log();
5408
- import_consola5.consola.log("Next steps:");
5569
+ import_consola6.consola.log("Next steps:");
5409
5570
  let step = 0;
5410
5571
  if (cdPath !== "")
5411
- import_consola5.consola.log(` ${++step}.`, import_picocolors8.default.cyan(`cd ${cdPath}`));
5412
- import_consola5.consola.log(` ${++step}.`, import_picocolors8.default.cyan(`${input.packageManager} install`));
5572
+ import_consola6.consola.log(` ${++step}.`, import_picocolors8.default.cyan(`cd ${cdPath}`));
5573
+ import_consola6.consola.log(` ${++step}.`, import_picocolors8.default.cyan(`${input.packageManager} install`));
5413
5574
  console.log();
5414
5575
  }
5415
5576
  async function listTemplates() {
@@ -5451,10 +5612,10 @@ async function cloneProject({
5451
5612
  force: true
5452
5613
  });
5453
5614
  await import_fs_extra14.default.move(
5454
- import_node_path18.default.join(directory, "_gitignore"),
5455
- import_node_path18.default.join(directory, ".gitignore")
5615
+ import_node_path19.default.join(directory, "_gitignore"),
5616
+ import_node_path19.default.join(directory, ".gitignore")
5456
5617
  ).catch(
5457
- (err) => import_consola5.consola.warn("Failed to move _gitignore to .gitignore:", err)
5618
+ (err) => import_consola6.consola.warn("Failed to move _gitignore to .gitignore:", err)
5458
5619
  );
5459
5620
  spinner.succeed();
5460
5621
  } catch (err) {
@@ -5485,7 +5646,7 @@ async function prepare(config) {
5485
5646
 
5486
5647
  // src/core/zip.ts
5487
5648
  var import_zip_dir = __toESM(require("zip-dir"), 1);
5488
- var import_node_path19 = require("path");
5649
+ var import_node_path20 = require("path");
5489
5650
  var import_fs_extra15 = __toESM(require("fs-extra"), 1);
5490
5651
  var import_minimatch2 = require("minimatch");
5491
5652
  async function zip(config) {
@@ -5495,7 +5656,7 @@ async function zip(config) {
5495
5656
  internalConfig.logger.info("Zipping extension...");
5496
5657
  const zipFiles = [];
5497
5658
  const projectName = internalConfig.zip.name ?? kebabCaseAlphanumeric(
5498
- (await getPackageJson(internalConfig))?.name || (0, import_node_path19.dirname)(process.cwd())
5659
+ (await getPackageJson(internalConfig))?.name || (0, import_node_path20.dirname)(process.cwd())
5499
5660
  );
5500
5661
  const applyTemplate = (template) => template.replaceAll("{{name}}", projectName).replaceAll("{{browser}}", internalConfig.browser).replaceAll(
5501
5662
  "{{version}}",
@@ -5503,7 +5664,7 @@ async function zip(config) {
5503
5664
  ).replaceAll("{{manifestVersion}}", `mv${internalConfig.manifestVersion}`);
5504
5665
  await import_fs_extra15.default.ensureDir(internalConfig.outBaseDir);
5505
5666
  const outZipFilename = applyTemplate(internalConfig.zip.artifactTemplate);
5506
- const outZipPath = (0, import_node_path19.resolve)(internalConfig.outBaseDir, outZipFilename);
5667
+ const outZipPath = (0, import_node_path20.resolve)(internalConfig.outBaseDir, outZipFilename);
5507
5668
  await (0, import_zip_dir.default)(internalConfig.outDir, {
5508
5669
  saveTo: outZipPath
5509
5670
  });
@@ -5512,14 +5673,14 @@ async function zip(config) {
5512
5673
  const sourcesZipFilename = applyTemplate(
5513
5674
  internalConfig.zip.sourcesTemplate
5514
5675
  );
5515
- const sourcesZipPath = (0, import_node_path19.resolve)(
5676
+ const sourcesZipPath = (0, import_node_path20.resolve)(
5516
5677
  internalConfig.outBaseDir,
5517
5678
  sourcesZipFilename
5518
5679
  );
5519
5680
  await (0, import_zip_dir.default)(internalConfig.zip.sourcesRoot, {
5520
5681
  saveTo: sourcesZipPath,
5521
5682
  filter(path10) {
5522
- const relativePath = (0, import_node_path19.relative)(internalConfig.zip.sourcesRoot, path10);
5683
+ const relativePath = (0, import_node_path20.relative)(internalConfig.zip.sourcesRoot, path10);
5523
5684
  const matchedPattern = internalConfig.zip.ignoredSources.find(
5524
5685
  (pattern) => (0, import_minimatch2.minimatch)(relativePath, pattern)
5525
5686
  );
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 './external-biT0d3qK.cjs';
2
- export { q as BackgroundDefinition, h as BackgroundEntrypoint, g as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, w as ConfigEnv, p as ContentScriptBaseDefinition, m as ContentScriptDefinition, C as ContentScriptEntrypoint, n as ContentScriptIsolatedWorldDefinition, o as ContentScriptMainWorldDefinition, j as Entrypoint, k as EntrypointGroup, t as ExcludableEntrypoint, G as GenericEntrypoint, L as Logger, l as OnContentScriptStopped, i as OptionsEntrypoint, c as OutputAsset, b as OutputChunk, O as OutputFile, s as PerBrowserOption, P as PopupEntrypoint, S as ServerInfo, T as TargetBrowser, e as TargetManifestVersion, r as UnlistedScriptDefinition, u as UserManifest, v as UserManifestFn, x as WxtBuilder, y as WxtBuilderServer, a as WxtViteConfig } from './external-biT0d3qK.cjs';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './external-mJ1bW7iy.cjs';
2
+ export { q as BackgroundDefinition, h as BackgroundEntrypoint, g as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, w as ConfigEnv, p as ContentScriptBaseDefinition, m as ContentScriptDefinition, C as ContentScriptEntrypoint, n as ContentScriptIsolatedWorldDefinition, o as ContentScriptMainWorldDefinition, j as Entrypoint, k as EntrypointGroup, t as ExcludableEntrypoint, G as GenericEntrypoint, L as Logger, l as OnContentScriptStopped, i as OptionsEntrypoint, c as OutputAsset, b as OutputChunk, O as OutputFile, s as PerBrowserOption, P as PopupEntrypoint, S as ServerInfo, T as TargetBrowser, e as TargetManifestVersion, r as UnlistedScriptDefinition, u as UserManifest, v as UserManifestFn, x as WxtBuilder, y as WxtBuilderServer, a as WxtViteConfig } from './external-mJ1bW7iy.cjs';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -62,6 +62,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
62
62
  */
63
63
  declare function zip(config?: InlineConfig): Promise<string[]>;
64
64
 
65
- var version = "0.14.5";
65
+ var version = "0.14.7";
66
66
 
67
67
  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 './external-biT0d3qK.js';
2
- export { q as BackgroundDefinition, h as BackgroundEntrypoint, g as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, w as ConfigEnv, p as ContentScriptBaseDefinition, m as ContentScriptDefinition, C as ContentScriptEntrypoint, n as ContentScriptIsolatedWorldDefinition, o as ContentScriptMainWorldDefinition, j as Entrypoint, k as EntrypointGroup, t as ExcludableEntrypoint, G as GenericEntrypoint, L as Logger, l as OnContentScriptStopped, i as OptionsEntrypoint, c as OutputAsset, b as OutputChunk, O as OutputFile, s as PerBrowserOption, P as PopupEntrypoint, S as ServerInfo, T as TargetBrowser, e as TargetManifestVersion, r as UnlistedScriptDefinition, u as UserManifest, v as UserManifestFn, x as WxtBuilder, y as WxtBuilderServer, a as WxtViteConfig } from './external-biT0d3qK.js';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './external-mJ1bW7iy.js';
2
+ export { q as BackgroundDefinition, h as BackgroundEntrypoint, g as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, w as ConfigEnv, p as ContentScriptBaseDefinition, m as ContentScriptDefinition, C as ContentScriptEntrypoint, n as ContentScriptIsolatedWorldDefinition, o as ContentScriptMainWorldDefinition, j as Entrypoint, k as EntrypointGroup, t as ExcludableEntrypoint, G as GenericEntrypoint, L as Logger, l as OnContentScriptStopped, i as OptionsEntrypoint, c as OutputAsset, b as OutputChunk, O as OutputFile, s as PerBrowserOption, P as PopupEntrypoint, S as ServerInfo, T as TargetBrowser, e as TargetManifestVersion, r as UnlistedScriptDefinition, u as UserManifest, v as UserManifestFn, x as WxtBuilder, y as WxtBuilderServer, a as WxtViteConfig } from './external-mJ1bW7iy.js';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -62,6 +62,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
62
62
  */
63
63
  declare function zip(config?: InlineConfig): Promise<string[]>;
64
64
 
65
- var version = "0.14.5";
65
+ var version = "0.14.7";
66
66
 
67
67
  export { BuildOutput, ExtensionRunnerConfig, InlineConfig, UserConfig, WxtDevServer, build, clean, createServer, defineConfig, defineRunnerConfig, initialize, prepare, version, zip };