wxt 0.20.27 → 0.21.1
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 +0 -1
- package/dist/cli/cli-utils.mjs +2 -2
- package/dist/core/builders/vite/index.mjs +85 -46
- package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +1 -1
- package/dist/core/builders/vite/plugins/index.mjs +0 -1
- package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +1 -1
- package/dist/core/clean.d.mts +0 -11
- package/dist/core/clean.mjs +9 -2
- package/dist/core/create-server.mjs +12 -11
- package/dist/core/define-web-ext-config.d.mts +1 -3
- package/dist/core/define-web-ext-config.mjs +1 -7
- package/dist/core/generate-wxt-dir.mjs +27 -25
- package/dist/core/index.d.mts +3 -2
- package/dist/core/index.mjs +1 -0
- package/dist/core/initialize.mjs +5 -5
- package/dist/core/resolve-config.mjs +40 -24
- package/dist/core/runners/web-ext.mjs +6 -5
- package/dist/core/utils/building/detect-dev-changes.mjs +17 -7
- package/dist/core/utils/building/internal-build.mjs +1 -1
- package/dist/core/utils/create-file-reloader.mjs +82 -27
- package/dist/core/utils/entrypoints.d.mts +10 -0
- package/dist/core/utils/index.d.mts +2 -0
- package/dist/core/utils/index.mjs +1 -0
- package/dist/core/utils/time.mjs +1 -10
- package/dist/core/utils/transform.mjs +1 -1
- package/dist/core/zip.mjs +15 -11
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +3 -2
- package/dist/testing/wxt-vitest-plugin.mjs +0 -2
- package/dist/types.d.mts +102 -41
- package/dist/utils/app-config.d.mts +1 -0
- package/dist/utils/app-config.mjs +2 -0
- package/dist/utils/content-script-ui/shadow-root.mjs +1 -1
- package/dist/version.mjs +1 -1
- package/dist/virtual/mock-browser.d.mts +1 -1
- package/dist/virtual/mock-browser.mjs +1 -1
- package/package.json +22 -20
- package/dist/core/builders/vite/plugins/download.mjs +0 -30
- package/dist/core/runners/index.mjs +0 -15
- package/dist/core/utils/network.mjs +0 -36
- package/dist/core/utils/picomatch-multiple.mjs +0 -24
- package/dist/core/utils/wsl.mjs +0 -8
- package/dist/testing/index.d.mts +0 -3
- package/dist/testing/index.mjs +0 -3
|
@@ -5,15 +5,19 @@ 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 { createSafariRunner } from "./runners/safari.mjs";
|
|
9
|
+
import { createWslRunner } from "./runners/wsl.mjs";
|
|
10
|
+
import { createManualRunner } from "./runners/manual.mjs";
|
|
8
11
|
import { pathExists } from "./utils/fs.mjs";
|
|
9
12
|
import { glob } from "tinyglobby";
|
|
10
13
|
import path from "node:path";
|
|
11
|
-
import consola, { LogLevels } from "consola";
|
|
12
14
|
import { loadConfig } from "c12";
|
|
13
15
|
import { resolve as resolve$1 } from "import-meta-resolve";
|
|
16
|
+
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";
|
|
20
|
+
import isWsl from "is-wsl";
|
|
17
21
|
//#region src/core/resolve-config.ts
|
|
18
22
|
/**
|
|
19
23
|
* Given an inline config, discover the config file if necessary, merge the
|
|
@@ -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
|
-
|
|
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
|
|
79
|
-
defaults: userConfig.webExt
|
|
81
|
+
overrides: inlineConfig.webExt,
|
|
82
|
+
defaults: userConfig.webExt
|
|
80
83
|
});
|
|
81
84
|
const alias = Object.fromEntries(Object.entries({
|
|
82
85
|
...mergedConfig.alias,
|
|
@@ -87,10 +90,9 @@ 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
|
-
|
|
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 ??
|
|
95
|
+
const origin = mergedConfig.dev?.server?.origin ?? "localhost";
|
|
94
96
|
const strictPort = mergedConfig.dev?.server?.strictPort ?? false;
|
|
95
97
|
if (port == null || !isFinite(port)) port = await getPort({
|
|
96
98
|
host,
|
|
@@ -139,7 +141,8 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
139
141
|
publicDir,
|
|
140
142
|
wxtModuleDir,
|
|
141
143
|
root,
|
|
142
|
-
|
|
144
|
+
webExt,
|
|
145
|
+
runner: command === "serve" ? await resolveRunner(browser, logger, mergedConfig) : createManualRunner(),
|
|
143
146
|
srcDir,
|
|
144
147
|
typesDir,
|
|
145
148
|
wxtDir,
|
|
@@ -149,6 +152,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
149
152
|
alias,
|
|
150
153
|
experimental: defu(mergedConfig.experimental, {}),
|
|
151
154
|
suppressWarnings: mergedConfig.suppressWarnings ?? {},
|
|
155
|
+
watchOptions: mergedConfig.watchOptions ?? {},
|
|
152
156
|
dev: {
|
|
153
157
|
server: devServerConfig,
|
|
154
158
|
reloadCommand
|
|
@@ -187,10 +191,10 @@ function resolveZipConfig(root, browser, outBaseDir, mergedConfig) {
|
|
|
187
191
|
const downloadedPackagesDir = path.resolve(root, ".wxt/local_modules");
|
|
188
192
|
return {
|
|
189
193
|
name: void 0,
|
|
190
|
-
sourcesTemplate: "{{name}}-{{
|
|
191
|
-
artifactTemplate: "{{name}}-{{
|
|
194
|
+
sourcesTemplate: "{{name}}-{{packageVersion}}-sources{{modeSuffix}}.zip",
|
|
195
|
+
artifactTemplate: "{{name}}-{{packageVersion}}-{{browser}}{{modeSuffix}}.zip",
|
|
192
196
|
sourcesRoot: root,
|
|
193
|
-
includeSources: [],
|
|
197
|
+
includeSources: mergedConfig.zip?.includeSources ?? ["**/*"],
|
|
194
198
|
compressionLevel: 9,
|
|
195
199
|
...mergedConfig.zip,
|
|
196
200
|
zipSources: mergedConfig.zip?.zipSources ?? ["firefox", "opera"].includes(browser),
|
|
@@ -198,12 +202,12 @@ function resolveZipConfig(root, browser, outBaseDir, mergedConfig) {
|
|
|
198
202
|
excludeSources: [
|
|
199
203
|
"**/node_modules",
|
|
200
204
|
"**/web-ext.config.ts",
|
|
201
|
-
"**/.*",
|
|
202
205
|
"**/__tests__/**",
|
|
203
206
|
"**/*.+(test|spec).?(c|m)+(j|t)s?(x)",
|
|
204
207
|
`${path.relative(root, outBaseDir)}/**`,
|
|
205
208
|
...mergedConfig.zip?.excludeSources ?? []
|
|
206
209
|
],
|
|
210
|
+
dotSources: mergedConfig.zip?.dotSources ?? false,
|
|
207
211
|
downloadPackages: mergedConfig.zip?.downloadPackages ?? [],
|
|
208
212
|
downloadedPackagesDir
|
|
209
213
|
};
|
|
@@ -224,7 +228,7 @@ function resolveAnalysisConfig(root, mergedConfig) {
|
|
|
224
228
|
}
|
|
225
229
|
async function getUnimportOptions(wxtDir, srcDir, logger, config) {
|
|
226
230
|
const disabled = config.imports === false;
|
|
227
|
-
const eslintrc = await getUnimportEslintOptions(wxtDir, config.imports);
|
|
231
|
+
const eslintrc = await getUnimportEslintOptions(logger, wxtDir, config.imports);
|
|
228
232
|
const invalidExports = ["options"];
|
|
229
233
|
const defineImportsAndTypes = (imports, typeImports) => [...imports, ...typeImports.map((name) => ({
|
|
230
234
|
name,
|
|
@@ -233,7 +237,7 @@ async function getUnimportOptions(wxtDir, srcDir, logger, config) {
|
|
|
233
237
|
const defaultOptions = {
|
|
234
238
|
imports: [{
|
|
235
239
|
name: "fakeBrowser",
|
|
236
|
-
from: "wxt/testing"
|
|
240
|
+
from: "wxt/testing/fake-browser"
|
|
237
241
|
}],
|
|
238
242
|
presets: [
|
|
239
243
|
{
|
|
@@ -337,26 +341,26 @@ async function getUnimportOptions(wxtDir, srcDir, logger, config) {
|
|
|
337
341
|
};
|
|
338
342
|
return defu(config.imports ?? {}, defaultOptions);
|
|
339
343
|
}
|
|
340
|
-
async function getUnimportEslintOptions(wxtDir, options) {
|
|
344
|
+
async function getUnimportEslintOptions(logger, wxtDir, options) {
|
|
341
345
|
const inlineEnabled = options === false ? false : options?.eslintrc?.enabled ?? "auto";
|
|
346
|
+
const version = await getEslintVersion();
|
|
347
|
+
const major = parseInt(version[0]);
|
|
342
348
|
let enabled;
|
|
343
349
|
switch (inlineEnabled) {
|
|
344
350
|
case "auto":
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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;
|
|
349
356
|
else if (major >= 9) enabled = 9;
|
|
350
357
|
else enabled = false;
|
|
351
358
|
break;
|
|
352
|
-
case true:
|
|
353
|
-
enabled = 8;
|
|
354
|
-
break;
|
|
355
359
|
default: enabled = inlineEnabled;
|
|
356
360
|
}
|
|
357
361
|
return {
|
|
358
362
|
enabled,
|
|
359
|
-
filePath: path.resolve(wxtDir, enabled ===
|
|
363
|
+
filePath: path.resolve(wxtDir, enabled === 8 ? "eslintrc-auto-import.json" : "eslint-auto-imports.mjs"),
|
|
360
364
|
globalsPropValue: true
|
|
361
365
|
};
|
|
362
366
|
}
|
|
@@ -423,5 +427,17 @@ async function resolveWxtUserModules(root, modulesDir, modules = []) {
|
|
|
423
427
|
}));
|
|
424
428
|
return [...npmModules, ...localModules];
|
|
425
429
|
}
|
|
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
|
+
}
|
|
426
442
|
//#endregion
|
|
427
443
|
export { resolveConfig };
|
|
@@ -1,6 +1,8 @@
|
|
|
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
|
+
import webExt from "web-ext";
|
|
5
|
+
import { consoleStream } from "web-ext/util/logger";
|
|
4
6
|
//#region src/core/runners/web-ext.ts
|
|
5
7
|
/** Create an `ExtensionRunner` backed by `web-ext`. */
|
|
6
8
|
function createWebExtRunner() {
|
|
@@ -11,12 +13,11 @@ function createWebExtRunner() {
|
|
|
11
13
|
},
|
|
12
14
|
async openBrowser() {
|
|
13
15
|
const startTime = Date.now();
|
|
14
|
-
|
|
15
|
-
webExtLogger.consoleStream.write = ({ level, msg, name }) => {
|
|
16
|
+
consoleStream.write = ({ level, msg, name }) => {
|
|
16
17
|
if (level >= ERROR_LOG_LEVEL) wxt.logger.error(name, msg);
|
|
17
18
|
if (level >= WARN_LOG_LEVEL) wxt.logger.warn(msg);
|
|
18
19
|
};
|
|
19
|
-
const wxtUserConfig = wxt.config.
|
|
20
|
+
const wxtUserConfig = wxt.config.webExt.config;
|
|
20
21
|
const finalConfig = {
|
|
21
22
|
browserConsole: wxtUserConfig?.openConsole,
|
|
22
23
|
devtools: wxtUserConfig?.openDevtools,
|
|
@@ -43,7 +44,7 @@ function createWebExtRunner() {
|
|
|
43
44
|
const options = { shouldExitProgram: false };
|
|
44
45
|
wxt.logger.debug("web-ext config:", finalConfig);
|
|
45
46
|
wxt.logger.debug("web-ext options:", options);
|
|
46
|
-
runner = await
|
|
47
|
+
runner = await webExt.cmd.run(finalConfig, options);
|
|
47
48
|
const duration = Date.now() - startTime;
|
|
48
49
|
wxt.logger.success(`Opened browser in ${formatDuration(duration)}`);
|
|
49
50
|
},
|
|
@@ -36,11 +36,12 @@ import { wxt } from "../../wxt.mjs";
|
|
|
36
36
|
* - .env (environment variable changed could effect build)
|
|
37
37
|
*/
|
|
38
38
|
function detectDevChanges(changedFiles, currentOutput) {
|
|
39
|
-
|
|
40
|
-
if (some(
|
|
41
|
-
if (some(
|
|
42
|
-
|
|
43
|
-
|
|
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 {
|
|
44
45
|
type: "extension-reload",
|
|
45
46
|
rebuildGroups: [],
|
|
46
47
|
cachedOutput: currentOutput
|
|
@@ -58,7 +59,7 @@ function detectDevChanges(changedFiles, currentOutput) {
|
|
|
58
59
|
};
|
|
59
60
|
for (const step of currentOutput.steps) if (changedSteps.has(step)) changedOutput.steps.push(step);
|
|
60
61
|
else unchangedOutput.steps.push(step);
|
|
61
|
-
if (
|
|
62
|
+
if (relevantChangedFiles.length > 0 && every(relevantChangedFiles, (file) => file.endsWith(".html"))) return {
|
|
62
63
|
type: "html-reload",
|
|
63
64
|
cachedOutput: unchangedOutput,
|
|
64
65
|
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
@@ -75,6 +76,15 @@ function detectDevChanges(changedFiles, currentOutput) {
|
|
|
75
76
|
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
76
77
|
};
|
|
77
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
|
+
}
|
|
78
88
|
/**
|
|
79
89
|
* For a single change, return all the step of the build output that were
|
|
80
90
|
* effected by it.
|
|
@@ -93,4 +103,4 @@ function findEffectedSteps(changedFile, currentOutput) {
|
|
|
93
103
|
return changes;
|
|
94
104
|
}
|
|
95
105
|
//#endregion
|
|
96
|
-
export { detectDevChanges };
|
|
106
|
+
export { detectDevChanges, getRelevantDevChangedFiles };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { unnormalizePath } from "../paths.mjs";
|
|
2
|
-
import { formatDuration } from "../time.mjs";
|
|
3
2
|
import { wxt } from "../../wxt.mjs";
|
|
4
3
|
import { findEntrypoints } from "./find-entrypoints.mjs";
|
|
5
4
|
import { groupEntrypoints } from "./group-entrypoints.mjs";
|
|
5
|
+
import { formatDuration } from "../time.mjs";
|
|
6
6
|
import { printBuildSummary } from "../log/printBuildSummary.mjs";
|
|
7
7
|
import "../log/index.mjs";
|
|
8
8
|
import { rebuild } from "./rebuild.mjs";
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { normalizePath } from "./paths.mjs";
|
|
1
2
|
import { getEntrypointBundlePath, isHtmlEntrypoint } from "./entrypoints.mjs";
|
|
3
|
+
import { filterTruthy, toArray } from "./arrays.mjs";
|
|
2
4
|
import { wxt } from "../wxt.mjs";
|
|
3
|
-
import { detectDevChanges } from "./building/detect-dev-changes.mjs";
|
|
5
|
+
import { detectDevChanges, getRelevantDevChangedFiles } from "./building/detect-dev-changes.mjs";
|
|
4
6
|
import { findEntrypoints } from "./building/find-entrypoints.mjs";
|
|
7
|
+
import { groupEntrypoints } from "./building/group-entrypoints.mjs";
|
|
5
8
|
import { getContentScriptJs, mapWxtOptionsToRegisteredContentScript } from "./content-scripts.mjs";
|
|
6
9
|
import { getContentScriptCssFiles, getContentScriptsCssMap } from "./manifest.mjs";
|
|
7
10
|
import { rebuild } from "./building/rebuild.mjs";
|
|
@@ -9,7 +12,6 @@ import "./building/index.mjs";
|
|
|
9
12
|
import { isBabelSyntaxError, logBabelSyntaxError } from "./syntax-errors.mjs";
|
|
10
13
|
import { relative } from "node:path";
|
|
11
14
|
import { styleText } from "node:util";
|
|
12
|
-
import { debounce } from "perfect-debounce";
|
|
13
15
|
import { Mutex } from "async-mutex";
|
|
14
16
|
//#region src/core/utils/create-file-reloader.ts
|
|
15
17
|
/**
|
|
@@ -19,15 +21,23 @@ import { Mutex } from "async-mutex";
|
|
|
19
21
|
function createFileReloader(server) {
|
|
20
22
|
const fileChangedMutex = new Mutex();
|
|
21
23
|
const changeQueue = [];
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
let processLoop;
|
|
25
|
+
const processQueue = async () => {
|
|
24
26
|
await fileChangedMutex.runExclusive(async () => {
|
|
25
|
-
if (server.currentOutput == null) return;
|
|
26
27
|
const fileChanges = changeQueue.splice(0, changeQueue.length).map(([_, file]) => file);
|
|
27
28
|
if (fileChanges.length === 0) return;
|
|
29
|
+
if (server.currentOutput == null) return;
|
|
30
|
+
const normalizedFileChanges = fileChanges.map(normalizePath);
|
|
31
|
+
const relevantFileChanges = getRelevantDevChangedFiles(fileChanges, server.currentOutput);
|
|
32
|
+
const normalizedEntrypointsDir = normalizePath(wxt.config.entrypointsDir);
|
|
33
|
+
const hasEntrypointDirChange = normalizedFileChanges.some((file) => file === normalizedEntrypointsDir || file.startsWith(`${normalizedEntrypointsDir}/`));
|
|
34
|
+
if (relevantFileChanges.length === 0 && !hasEntrypointDirChange) return;
|
|
28
35
|
await wxt.reloadConfig();
|
|
29
|
-
const
|
|
30
|
-
|
|
36
|
+
const allEntrypoints = await findEntrypoints();
|
|
37
|
+
const allEntrypointGroups = groupEntrypoints(allEntrypoints);
|
|
38
|
+
const newEntrypointGroups = getNewEntrypointGroups(normalizedFileChanges, allEntrypointGroups, server.currentOutput);
|
|
39
|
+
if (relevantFileChanges.length === 0 && newEntrypointGroups.length === 0) return;
|
|
40
|
+
const changes = detectDevChanges(relevantFileChanges, server.currentOutput);
|
|
31
41
|
if (changes.type === "full-restart") {
|
|
32
42
|
wxt.logger.info("Config changed, restarting server...");
|
|
33
43
|
server.restart();
|
|
@@ -38,25 +48,24 @@ function createFileReloader(server) {
|
|
|
38
48
|
server.restartBrowser();
|
|
39
49
|
return;
|
|
40
50
|
}
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
const hasNewEntrypoints = newEntrypointGroups.length > 0;
|
|
52
|
+
if (changes.type === "no-change" && !hasNewEntrypoints) return;
|
|
53
|
+
const changedFilesToLog = Array.from(new Set([...relevantFileChanges, ...newEntrypointGroups.flatMap((group) => toArray(group)).map((entry) => entry.inputPath)]));
|
|
54
|
+
wxt.logger.info(`Changed: ${changedFilesToLog.map((file) => styleText("dim", relative(wxt.config.root, file))).join(", ")}`);
|
|
55
|
+
const rebuildGroups = changes.type === "no-change" ? newEntrypointGroups : mergeEntrypointGroups(getLatestRebuildGroups(changes.rebuildGroups, allEntrypointGroups), newEntrypointGroups);
|
|
43
56
|
try {
|
|
44
|
-
const { output: newOutput } = await rebuild(allEntrypoints,
|
|
57
|
+
const { output: newOutput } = await rebuild(allEntrypoints, rebuildGroups, changes.type === "no-change" ? server.currentOutput : changes.cachedOutput);
|
|
45
58
|
server.currentOutput = newOutput;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
reloadContentScripts(changes.changedSteps, server);
|
|
57
|
-
const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
|
|
58
|
-
wxt.logger.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
|
|
59
|
-
break;
|
|
59
|
+
if (hasNewEntrypoints || changes.type === "extension-reload") {
|
|
60
|
+
server.reloadExtension();
|
|
61
|
+
wxt.logger.success(`Reloaded extension`);
|
|
62
|
+
} else if (changes.type === "html-reload") {
|
|
63
|
+
const { reloadedNames } = reloadHtmlPages(rebuildGroups, server);
|
|
64
|
+
wxt.logger.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
|
|
65
|
+
} else if (changes.type === "content-script-reload") {
|
|
66
|
+
reloadContentScripts(changes.changedSteps, server);
|
|
67
|
+
const rebuiltNames = rebuildGroups.flat().map((entry) => entry.name);
|
|
68
|
+
wxt.logger.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
|
|
60
69
|
}
|
|
61
70
|
} catch {}
|
|
62
71
|
}).catch((error) => {
|
|
@@ -64,11 +73,57 @@ function createFileReloader(server) {
|
|
|
64
73
|
logBabelSyntaxError(error);
|
|
65
74
|
});
|
|
66
75
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
const waitForDebounceWindow = async () => {
|
|
77
|
+
await new Promise((resolve) => {
|
|
78
|
+
setTimeout(resolve, wxt.config.dev.server.watchDebounce);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const queueWorker = async () => {
|
|
82
|
+
while (true) {
|
|
83
|
+
await processQueue();
|
|
84
|
+
await waitForDebounceWindow();
|
|
85
|
+
if (changeQueue.length === 0) break;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
return async (event, path) => {
|
|
89
|
+
changeQueue.push([event, path]);
|
|
90
|
+
processLoop ??= queueWorker().finally(() => {
|
|
91
|
+
processLoop = void 0;
|
|
92
|
+
});
|
|
93
|
+
await processLoop;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function getNewEntrypointGroups(normalizedFileChanges, allEntrypointGroups, currentOutput) {
|
|
97
|
+
const changedFiles = new Set(normalizedFileChanges);
|
|
98
|
+
const builtEntrypointPaths = new Set(currentOutput.steps.flatMap((step) => toArray(step.entrypoints).map((entry) => normalizePath(entry.inputPath))));
|
|
99
|
+
return allEntrypointGroups.filter((group) => {
|
|
100
|
+
const groupEntrypoints = toArray(group);
|
|
101
|
+
const hasNewEntrypoint = groupEntrypoints.some((entry) => !builtEntrypointPaths.has(normalizePath(entry.inputPath)));
|
|
102
|
+
const changedEntrypoint = groupEntrypoints.some((entry) => changedFiles.has(normalizePath(entry.inputPath)));
|
|
103
|
+
return hasNewEntrypoint && changedEntrypoint;
|
|
70
104
|
});
|
|
71
105
|
}
|
|
106
|
+
function getLatestRebuildGroups(rebuildGroups, allEntrypointGroups) {
|
|
107
|
+
const groupByEntrypointPath = /* @__PURE__ */ new Map();
|
|
108
|
+
allEntrypointGroups.forEach((group) => {
|
|
109
|
+
toArray(group).forEach((entry) => {
|
|
110
|
+
groupByEntrypointPath.set(normalizePath(entry.inputPath), group);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
return mergeEntrypointGroups(rebuildGroups.flatMap((group) => {
|
|
114
|
+
return filterTruthy(toArray(group).map((entry) => groupByEntrypointPath.get(normalizePath(entry.inputPath))));
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
function mergeEntrypointGroups(...groups) {
|
|
118
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
119
|
+
groups.flat().forEach((group) => {
|
|
120
|
+
deduped.set(getEntrypointGroupKey(group), group);
|
|
121
|
+
});
|
|
122
|
+
return [...deduped.values()];
|
|
123
|
+
}
|
|
124
|
+
function getEntrypointGroupKey(group) {
|
|
125
|
+
return toArray(group).map((entry) => normalizePath(entry.inputPath)).sort().join("|");
|
|
126
|
+
}
|
|
72
127
|
/**
|
|
73
128
|
* From the server, tell the client to reload content scripts from the provided
|
|
74
129
|
* build step outputs.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Entrypoint } from "../../types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/utils/entrypoints.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Return's the entrypoint's output path relative to the output directory. Used
|
|
6
|
+
* for paths in the manifest and rollup's bundle.
|
|
7
|
+
*/
|
|
8
|
+
declare function getEntrypointBundlePath(entrypoint: Entrypoint, outDir: string, ext: string): string;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { getEntrypointBundlePath };
|
package/dist/core/utils/time.mjs
CHANGED
|
@@ -5,14 +5,5 @@ function formatDuration(duration) {
|
|
|
5
5
|
if (duration < 6e4) return `${(duration / 1e3).toFixed(1)} s`;
|
|
6
6
|
return `${(duration / 1e3).toFixed(0)} s`;
|
|
7
7
|
}
|
|
8
|
-
/** Add a timeout to a promise. */
|
|
9
|
-
function withTimeout(promise, duration) {
|
|
10
|
-
return new Promise((res, rej) => {
|
|
11
|
-
const timeout = setTimeout(() => {
|
|
12
|
-
rej(`Promise timed out after ${duration}ms`);
|
|
13
|
-
}, duration);
|
|
14
|
-
promise.then(res).catch(rej).finally(() => clearTimeout(timeout));
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
8
|
//#endregion
|
|
18
|
-
export { formatDuration
|
|
9
|
+
export { formatDuration };
|
|
@@ -28,7 +28,7 @@ function removeMainFunctionCode(code) {
|
|
|
28
28
|
function emptyMainFunction(mod) {
|
|
29
29
|
if (mod.exports?.default?.$type === "function-call") {
|
|
30
30
|
if (mod.exports.default.$ast?.arguments?.[0]?.body) delete mod.exports.default.$ast.arguments[0];
|
|
31
|
-
else if (mod.exports.default.$ast?.arguments?.[0]?.properties) mod.exports.default.$ast.arguments[0].properties = mod.exports.default.$ast.arguments[0].properties.filter((prop) => prop.key
|
|
31
|
+
else if (mod.exports.default.$ast?.arguments?.[0]?.properties) mod.exports.default.$ast.arguments[0].properties = mod.exports.default.$ast.arguments[0].properties.filter((prop) => prop.key?.name !== "main");
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
function removeUnusedTopLevelVariables(mod) {
|
package/dist/core/zip.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { normalizePath } from "./utils/paths.mjs";
|
|
2
2
|
import "./utils/index.mjs";
|
|
3
3
|
import { safeFilename } from "./utils/strings.mjs";
|
|
4
|
-
import { formatDuration } from "./utils/time.mjs";
|
|
5
4
|
import { registerWxt, wxt } from "./wxt.mjs";
|
|
6
5
|
import { findEntrypoints } from "./utils/building/find-entrypoints.mjs";
|
|
6
|
+
import { formatDuration } from "./utils/time.mjs";
|
|
7
7
|
import { printFileList } from "./utils/log/printFileList.mjs";
|
|
8
8
|
import "./utils/log/index.mjs";
|
|
9
9
|
import { getPackageJson } from "./utils/package.mjs";
|
|
10
10
|
import { internalBuild } from "./utils/building/internal-build.mjs";
|
|
11
11
|
import "./utils/building/index.mjs";
|
|
12
|
-
import { picomatchMultiple } from "./utils/picomatch-multiple.mjs";
|
|
13
12
|
import { mkdir, readFile } from "node:fs/promises";
|
|
14
13
|
import { glob } from "tinyglobby";
|
|
15
14
|
import path from "node:path";
|
|
@@ -31,7 +30,11 @@ async function zip(config) {
|
|
|
31
30
|
const zipFiles = [];
|
|
32
31
|
const packageJson = await getPackageJson();
|
|
33
32
|
const projectName = wxt.config.zip.name ?? safeFilename(packageJson?.name || path.basename(process.cwd()));
|
|
34
|
-
const
|
|
33
|
+
const modeSuffix = {
|
|
34
|
+
production: "",
|
|
35
|
+
development: "-dev"
|
|
36
|
+
}[wxt.config.mode] ?? `-${wxt.config.mode}`;
|
|
37
|
+
const applyTemplate = (template) => template.replaceAll("{{name}}", projectName).replaceAll("{{browser}}", wxt.config.browser).replaceAll("{{version}}", output.manifest.version).replaceAll("{{versionName}}", output.manifest.version_name ?? output.manifest.version).replaceAll("{{packageVersion}}", packageJson?.version).replaceAll("{{modeSuffix}}", modeSuffix).replaceAll("{{mode}}", wxt.config.mode).replaceAll("{{manifestVersion}}", `mv${wxt.config.manifestVersion}`);
|
|
35
38
|
await mkdir(wxt.config.outBaseDir, { recursive: true });
|
|
36
39
|
await wxt.hooks.callHook("zip:extension:start", wxt);
|
|
37
40
|
const outZipFilename = applyTemplate(wxt.config.zip.artifactTemplate);
|
|
@@ -46,16 +49,18 @@ async function zip(config) {
|
|
|
46
49
|
const { overrides, files: downloadedPackages } = await downloadPrivatePackages();
|
|
47
50
|
const sourcesZipFilename = applyTemplate(wxt.config.zip.sourcesTemplate);
|
|
48
51
|
const sourcesZipPath = path.resolve(wxt.config.outBaseDir, sourcesZipFilename);
|
|
49
|
-
await zipDir(wxt.config.zip.sourcesRoot, sourcesZipPath, {
|
|
52
|
+
const files = await zipDir(wxt.config.zip.sourcesRoot, sourcesZipPath, {
|
|
50
53
|
include: wxt.config.zip.includeSources,
|
|
51
54
|
exclude: excludeSources,
|
|
52
55
|
transform(absolutePath, zipPath, content) {
|
|
53
56
|
if (zipPath.endsWith("package.json")) return addOverridesToPackageJson(absolutePath, content, overrides);
|
|
54
57
|
},
|
|
55
|
-
additionalFiles: downloadedPackages
|
|
58
|
+
additionalFiles: downloadedPackages,
|
|
59
|
+
dot: wxt.config.zip.dotSources
|
|
56
60
|
});
|
|
57
61
|
zipFiles.push(sourcesZipPath);
|
|
58
62
|
await wxt.hooks.callHook("zip:sources:done", wxt, sourcesZipPath);
|
|
63
|
+
await printFileList(wxt.logger.info, `Sources included in \`${sourcesZipFilename}\``, wxt.config.zip.sourcesRoot, files);
|
|
59
64
|
}
|
|
60
65
|
await printFileList(wxt.logger.success, `Zipped extension in ${formatDuration(Date.now() - start)}`, wxt.config.outBaseDir, zipFiles);
|
|
61
66
|
await wxt.hooks.callHook("zip:done", wxt, zipFiles);
|
|
@@ -63,14 +68,12 @@ async function zip(config) {
|
|
|
63
68
|
}
|
|
64
69
|
async function zipDir(directory, outputPath, options) {
|
|
65
70
|
const archive = new JSZip();
|
|
66
|
-
const filesToZip = [...
|
|
71
|
+
const filesToZip = [...await glob(options?.include ?? ["**/*"], {
|
|
67
72
|
cwd: directory,
|
|
68
|
-
ignore: [
|
|
73
|
+
ignore: options?.exclude ?? [],
|
|
69
74
|
onlyFiles: true,
|
|
70
|
-
|
|
71
|
-
})).
|
|
72
|
-
return picomatchMultiple(relativePath, options?.include) || !picomatchMultiple(relativePath, options?.exclude);
|
|
73
|
-
}), ...(options?.additionalFiles ?? []).map((file) => path.relative(directory, file))];
|
|
75
|
+
dot: options?.dot
|
|
76
|
+
}), ...(options?.additionalFiles ?? []).map((file) => path.relative(directory, file))].sort();
|
|
74
77
|
for (const file of filesToZip) {
|
|
75
78
|
const absolutePath = path.resolve(directory, file);
|
|
76
79
|
if (file.endsWith(".json")) {
|
|
@@ -89,6 +92,7 @@ async function zipDir(directory, outputPath, options) {
|
|
|
89
92
|
compressionOptions: { level: wxt.config.zip.compressionLevel }
|
|
90
93
|
}
|
|
91
94
|
}).pipe(createWriteStream(outputPath)).on("error", reject).on("close", resolve));
|
|
95
|
+
return filesToZip;
|
|
92
96
|
}
|
|
93
97
|
async function downloadPrivatePackages() {
|
|
94
98
|
const overrides = {};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner,
|
|
1
|
+
import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, FirefoxDataCollectionPermissions, FirefoxDataCollectionType, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, PrepareTsconfigs, PublicPathEntry, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig } from "./types.mjs";
|
|
2
2
|
import { build } from "./core/build.mjs";
|
|
3
3
|
import { clean } from "./core/clean.mjs";
|
|
4
4
|
import { defineConfig } from "./core/define-config.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { defineWebExtConfig } from "./core/define-web-ext-config.mjs";
|
|
6
6
|
import { createServer } from "./core/create-server.mjs";
|
|
7
7
|
import { initialize } from "./core/initialize.mjs";
|
|
8
8
|
import { prepare } from "./core/prepare.mjs";
|
|
9
9
|
import { zip } from "./core/zip.mjs";
|
|
10
10
|
import { normalizePath } from "./core/utils/paths.mjs";
|
|
11
|
+
import { getEntrypointBundlePath } from "./core/utils/entrypoints.mjs";
|
|
11
12
|
import { version } from "./version.mjs";
|
|
12
|
-
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner,
|
|
13
|
+
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, FirefoxDataCollectionPermissions, FirefoxDataCollectionType, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, PrepareTsconfigs, PublicPathEntry, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig, build, clean, createServer, defineConfig, defineWebExtConfig, getEntrypointBundlePath, initialize, normalizePath, prepare, version, zip };
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { normalizePath } from "./core/utils/paths.mjs";
|
|
2
|
+
import { getEntrypointBundlePath } from "./core/utils/entrypoints.mjs";
|
|
2
3
|
import { version } from "./version.mjs";
|
|
3
4
|
import { build } from "./core/build.mjs";
|
|
4
5
|
import { clean } from "./core/clean.mjs";
|
|
5
6
|
import { defineConfig } from "./core/define-config.mjs";
|
|
6
|
-
import {
|
|
7
|
+
import { defineWebExtConfig } from "./core/define-web-ext-config.mjs";
|
|
7
8
|
import { createServer } from "./core/create-server.mjs";
|
|
8
9
|
import { initialize } from "./core/initialize.mjs";
|
|
9
10
|
import { prepare } from "./core/prepare.mjs";
|
|
10
11
|
import { zip } from "./core/zip.mjs";
|
|
11
12
|
import "./core/index.mjs";
|
|
12
|
-
export { build, clean, createServer, defineConfig,
|
|
13
|
+
export { build, clean, createServer, defineConfig, defineWebExtConfig, getEntrypointBundlePath, initialize, normalizePath, prepare, version, zip };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { download } from "../core/builders/vite/plugins/download.mjs";
|
|
2
1
|
import { tsconfigPaths } from "../core/builders/vite/plugins/tsconfigPaths.mjs";
|
|
3
2
|
import { globals } from "../core/builders/vite/plugins/globals.mjs";
|
|
4
3
|
import { extensionApiMock } from "../core/builders/vite/plugins/extensionApiMock.mjs";
|
|
@@ -28,7 +27,6 @@ async function WxtVitest(inlineConfig) {
|
|
|
28
27
|
await registerWxt("serve", inlineConfig ?? {});
|
|
29
28
|
const plugins = [
|
|
30
29
|
globals(wxt.config),
|
|
31
|
-
download(wxt.config),
|
|
32
30
|
tsconfigPaths(wxt.config),
|
|
33
31
|
resolveAppConfig(wxt.config),
|
|
34
32
|
extensionApiMock(wxt.config)
|