extension-develop 3.15.1 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/0~branding.mjs +26 -0
  2. package/dist/0~dev-server.mjs +488 -0
  3. package/dist/0~rslib-runtime.mjs +40 -0
  4. package/dist/0~rspack-config.mjs +8648 -0
  5. package/dist/0~stats-handler.mjs +25 -0
  6. package/dist/0~zip.mjs +34 -0
  7. package/dist/314.mjs +35 -0
  8. package/dist/526.mjs +23 -0
  9. package/dist/946.mjs +1670 -0
  10. package/dist/962.mjs +1389 -0
  11. package/dist/ensure-hmr-for-scripts.js +12 -56
  12. package/dist/{ensure-hmr-for-scripts.cjs → ensure-hmr-for-scripts.mjs} +12 -56
  13. package/dist/feature-scripts-content-script-wrapper.js +23 -98
  14. package/dist/{feature-scripts-content-script-wrapper.cjs → feature-scripts-content-script-wrapper.mjs} +23 -98
  15. package/dist/main-world-bridge.js +0 -18
  16. package/dist/{main-world-bridge.cjs → main-world-bridge.mjs} +0 -18
  17. package/dist/minimum-chromium-file.js +0 -5
  18. package/dist/minimum-chromium-file.mjs +5 -0
  19. package/dist/minimum-firefox-file.js +0 -5
  20. package/dist/minimum-firefox-file.mjs +5 -0
  21. package/dist/minimum-script-file.js +0 -18
  22. package/dist/{minimum-script-file.cjs → minimum-script-file.mjs} +0 -18
  23. package/dist/module.mjs +3 -0
  24. package/dist/package.json +1 -1
  25. package/dist/preact-refresh-shim.mjs +7 -0
  26. package/dist/preview.mjs +2 -0
  27. package/dist/resolve-paths-loader.js +1043 -1093
  28. package/dist/resolve-paths-loader.mjs +1300 -0
  29. package/package.json +8 -8
  30. package/dist/221.cjs +0 -513
  31. package/dist/442.cjs +0 -9226
  32. package/dist/504.cjs +0 -65
  33. package/dist/787.cjs +0 -44
  34. package/dist/minimum-chromium-file.cjs +0 -10
  35. package/dist/minimum-firefox-file.cjs +0 -10
  36. package/dist/module.cjs +0 -3479
  37. package/dist/preact-refresh-shim.cjs +0 -25
  38. package/dist/preview.cjs +0 -1464
  39. package/dist/resolve-paths-loader.cjs +0 -1350
package/dist/946.mjs ADDED
@@ -0,0 +1,1670 @@
1
+ import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
2
+ import pintor from "pintor";
3
+ import { pathToFileURL } from "url";
4
+ import { createRequire } from "module";
5
+ import dotenv from "dotenv";
6
+ import { fetchExtensionFromStore } from "extension-from-store";
7
+ import path_0 from "path";
8
+ import { getSpecialFoldersData } from "browser-extension-manifest-fields";
9
+ import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
10
+ import { dirname as __rspack_dirname } from "node:path";
11
+ import * as __rspack_external_path from "path";
12
+ import * as __rspack_external_fs from "fs";
13
+ import * as __rspack_external_os from "os";
14
+ import * as __rspack_external_vm from "vm";
15
+ var package_namespaceObject = JSON.parse('{"rE":"3.16.0","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.0.1","@rspack/dev-server":"^2.0.1","@rspack/plugin-preact-refresh":"1.1.5","@rspack/plugin-react-refresh":"1.6.2","@swc/core":"^1.15.8","@swc/helpers":"^0.5.18","@vue/compiler-sfc":"3.5.26","adm-zip":"^0.5.16","browser-extension-manifest-fields":"^2.2.3","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","cross-spawn":"^7.0.6","dotenv":"^17.2.3","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.5.1","less-loader":"12.3.2","loader-utils":"^3.3.1","magic-string":"^0.30.21","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.10","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","react-refresh":"0.18.0","sass-loader":"16.0.7","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","typescript":"5.9.3","unique-names-generator":"^4.7.1","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3"}}');
16
+ const fmt = {
17
+ heading: (title)=>pintor.underline(pintor.blue(title)),
18
+ label: (key)=>pintor.gray(key.toUpperCase()),
19
+ val: (value)=>pintor.underline(value),
20
+ code: (value)=>pintor.blue(value),
21
+ bullet: (value)=>`- ${value}`,
22
+ block (title, rows) {
23
+ const head = fmt.heading(title);
24
+ const body = rows.map(([key, value])=>`${fmt.label(key)} ${value}`).join('\n');
25
+ return `${head}\n${body}`;
26
+ },
27
+ truncate (input, max = 800) {
28
+ const s = (()=>{
29
+ try {
30
+ return 'string' == typeof input ? input : JSON.stringify(input);
31
+ } catch {
32
+ return String(input);
33
+ }
34
+ })();
35
+ return s.length > max ? s.slice(0, max) + '…' : s;
36
+ }
37
+ };
38
+ function getLoggingPrefix(type) {
39
+ const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
40
+ if (isAuthor) {
41
+ const base = 'error' === type ? 'ERROR Author says' : '⏵⏵⏵ Author says';
42
+ return pintor.brightMagenta(base);
43
+ }
44
+ if ('error' === type) return pintor.red('ERROR');
45
+ if ('warn' === type) return pintor.brightYellow('⏵⏵⏵');
46
+ if ('info' === type) return pintor.gray('⏵⏵⏵');
47
+ return pintor.green('⏵⏵⏵');
48
+ }
49
+ function isPathLike(input) {
50
+ return input.includes('/') || input.includes('\\') || __rspack_external_path.isAbsolute(input);
51
+ }
52
+ function manifestNotFoundError(manifestPath) {
53
+ return `${getLoggingPrefix('error')} Manifest file not found.\n${pintor.red('Ensure the path to your extension exists and try again.')}\n${pintor.red('NOT FOUND')}\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}`;
54
+ }
55
+ function previewing(browser) {
56
+ return `${getLoggingPrefix('info')} Previewing the extension on ${capitalizedBrowserName(browser)}...`;
57
+ }
58
+ function previewSkippedNoBrowser(browser) {
59
+ return `${getLoggingPrefix('info')} Skipping browser launch for ${capitalizedBrowserName(browser)} (no-browser).`;
60
+ }
61
+ function authorInstallNotice(target) {
62
+ return `${getLoggingPrefix('warn')} Author mode: installing ${target}.`;
63
+ }
64
+ function buildWebpack(projectDir, stats, browser) {
65
+ const statsJson = stats?.toJson({
66
+ all: false,
67
+ assets: true,
68
+ time: true
69
+ });
70
+ const outputPath = 'string' == typeof stats?.compilation?.outputOptions?.path ? stats.compilation.outputOptions.path : '';
71
+ const manifestPath = outputPath ? __rspack_external_path.join(outputPath, 'manifest.json') : __rspack_external_path.join(projectDir, 'manifest.json');
72
+ const manifest = JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf8'));
73
+ const assets = statsJson?.assets;
74
+ const heading = `${getLoggingPrefix('info')} Building ${pintor.blue(manifest.name)} extension using ${capitalizedBrowserName(browser)} defaults...\n`;
75
+ const buildTime = `\nBuild completed in ${((statsJson?.time || 0) / 1000).toFixed(2)} seconds.\n`;
76
+ const buildTarget = `Build Target: ${pintor.gray(capitalizedBrowserName(browser))}\n`;
77
+ const buildStatus = `Build Status: ${stats?.hasErrors() ? pintor.red('Failed') : pintor.green('Success')}\n`;
78
+ const version = `\nVersion: ${pintor.gray(manifest.version)}\n`;
79
+ const size = `Size: ${pintor.gray(getAssetsSize(assets))}\n`;
80
+ let output = '';
81
+ output += heading;
82
+ output += getAssetsTree(assets);
83
+ output += version;
84
+ output += size;
85
+ output += buildTarget;
86
+ output += buildStatus;
87
+ output += buildTime;
88
+ return output;
89
+ }
90
+ function buildSuccess() {
91
+ return `${getLoggingPrefix('success')} Build succeeded with no warnings. Your extension is ${pintor.green('ready for deployment')}.`;
92
+ }
93
+ function getWarningMessage(warning) {
94
+ if (!warning) return '';
95
+ if ('string' == typeof warning) return warning.trim();
96
+ const candidates = [
97
+ warning.message,
98
+ warning.details,
99
+ warning.reason,
100
+ warning.description
101
+ ];
102
+ for (const candidate of candidates)if ('string' == typeof candidate && candidate.trim()) return candidate.trim();
103
+ return '';
104
+ }
105
+ function getWarningSource(warning) {
106
+ if (!warning || 'string' == typeof warning) return 'bundler';
107
+ const candidates = [
108
+ warning.name,
109
+ warning.moduleName,
110
+ warning.moduleIdentifier,
111
+ warning.originName,
112
+ warning.pluginName
113
+ ];
114
+ for (const candidate of candidates)if ('string' == typeof candidate && candidate.trim()) return candidate.trim();
115
+ return 'bundler';
116
+ }
117
+ function getWarningArtifact(warning) {
118
+ if (!warning || 'string' == typeof warning) return '';
119
+ const candidates = [
120
+ warning.file,
121
+ warning.chunkName,
122
+ warning.moduleName
123
+ ];
124
+ for (const candidate of candidates)if ('string' == typeof candidate && candidate.trim()) return candidate.trim();
125
+ return '';
126
+ }
127
+ function classifyWarning(message, source) {
128
+ const haystack = `${message} ${source}`.toLowerCase();
129
+ if (haystack.includes('performance') || haystack.includes('asset size') || haystack.includes('entrypoint size') || haystack.includes('exceeds the recommended size') || haystack.includes('hints')) return 'Performance';
130
+ if (haystack.includes('deprecat') || haystack.includes('[dep_') || haystack.includes('legacy')) return 'Deprecation';
131
+ if (haystack.includes('invalid') || haystack.includes('unknown option') || haystack.includes('configuration') || haystack.includes('schema')) return 'Configuration';
132
+ if (haystack.includes('manifest') || haystack.includes('browser') || haystack.includes('target')) return 'Compatibility';
133
+ if (haystack.includes('runtime') || haystack.includes('will fail') || haystack.includes('cannot resolve') || haystack.includes('service_worker')) return 'Runtime-risk';
134
+ return 'Warning';
135
+ }
136
+ function suggestedHintForWarning(category) {
137
+ if ('Performance' === category) return 'Inspect the largest startup bundles and split optional code paths.';
138
+ if ('Deprecation' === category) return 'Move to the supported API or plugin path before the next update.';
139
+ if ('Configuration' === category) return 'Review extension and bundler config keys, then remove or rename invalid options.';
140
+ if ('Compatibility' === category) return 'Verify browser target and manifest compatibility for this build.';
141
+ if ('Runtime-risk' === category) return 'Address this before release; it may fail or degrade at runtime.';
142
+ return 'Re-run with EXTENSION_VERBOSE=1 to inspect full warning details.';
143
+ }
144
+ function buildSuccessWithWarnings(warningCount) {
145
+ return `${getLoggingPrefix('warn')} Build succeeded with ${warningCount} warning(s). Your extension is ${pintor.green('ready for deployment')}.`;
146
+ }
147
+ function buildWarningsDetails(warnings) {
148
+ if (!Array.isArray(warnings) || 0 === warnings.length) return '';
149
+ const blocks = [];
150
+ warnings.forEach((warning, index)=>{
151
+ const message = getWarningMessage(warning);
152
+ const source = getWarningSource(warning);
153
+ const artifact = getWarningArtifact(warning);
154
+ const category = classifyWarning(message, source);
155
+ const hint = suggestedHintForWarning(category);
156
+ if (!message) return void blocks.push(`${getLoggingPrefix('warn')} Warning ${index + 1}: details were suppressed by tool output.\n${formatWarningLabelLine('Source', pintor.gray(source))}\n${formatWarningLabelLine('Hint', 'Re-run with EXTENSION_VERBOSE=1 to inspect full warning messages.')}`);
157
+ const performanceWarning = parsePerformanceWarning(warning, source, artifact);
158
+ if (performanceWarning) return void blocks.push(performanceWarning);
159
+ const oneLine = message.replace(/\s+/g, ' ').trim();
160
+ const artifactSuffix = artifact ? ` ${pintor.gray(`(${artifact})`)}` : '';
161
+ blocks.push(`${getLoggingPrefix('warn')} ${category}: ${oneLine}${artifactSuffix}\n${formatWarningLabelLine('Source', pintor.gray(source))}\n${formatWarningLabelLine('Hint', hint)}`);
162
+ });
163
+ return blocks.join('\n\n');
164
+ }
165
+ function fetchingProjectPath(owner, project) {
166
+ return fmt.block('Fetching project', [
167
+ [
168
+ 'URL',
169
+ fmt.val(`https://github.com/${owner}/${project}`)
170
+ ]
171
+ ]);
172
+ }
173
+ function downloadingProjectPath(projectName) {
174
+ const formatted = isPathLike(projectName) ? pintor.underline(projectName) : pintor.yellow(projectName);
175
+ return `${getLoggingPrefix('info')} Downloading ${formatted}...`;
176
+ }
177
+ function creatingProjectPath(projectPath) {
178
+ return `${getLoggingPrefix('info')} Creating a new browser extension...\n${pintor.gray('PATH')} ${pintor.underline(projectPath)}`;
179
+ }
180
+ function downloadedProjectFolderNotFound(cwd, candidates) {
181
+ return `${getLoggingPrefix('error')} Downloaded project folder not found.\n${pintor.gray('PATH')} ${pintor.underline(cwd)}\n${pintor.gray('Tried')} ${pintor.underline(candidates.join(', '))}`;
182
+ }
183
+ function packagingSourceFiles(zipPath) {
184
+ return `${getLoggingPrefix('info')} Packaging source files. Files in ${pintor.yellow('.gitignore')} will be excluded...\n${pintor.gray('PATH')} ${pintor.underline(zipPath)}.`;
185
+ }
186
+ function packagingDistributionFiles(zipPath) {
187
+ return `${getLoggingPrefix('info')} Packaging extension distribution files...\n${pintor.gray('PATH')} ${pintor.underline(zipPath)}`;
188
+ }
189
+ function treeWithSourceAndDistFiles(browser, name, sourceZip, destZip) {
190
+ return `📦 Package name: ${pintor.blue(`${name}`)}, Target Browser: ${capitalizedBrowserName(browser)}\n ${pintor.gray('└─')} ${pintor.underline(`${sourceZip}`)} ${pintor.gray('(source)')}\n ${pintor.gray('└─')} ${pintor.underline(`${destZip}`)} ${pintor.gray('(distribution)')}`;
191
+ }
192
+ function treeWithDistFilesbrowser(name, ext, browser, zipPath) {
193
+ return `📦 Package name: ${pintor.blue(`${name}.${ext}`)}, Target Browser: ${capitalizedBrowserName(browser)}\n ${pintor.gray('└─')} ${pintor.underline(`${zipPath}`)} ${pintor.gray('(distribution)')}`;
194
+ }
195
+ function treeWithSourceFiles(name, ext, browser, zipPath) {
196
+ return `📦 Package name: ${pintor.blue(`${name}-source.${ext}`)}, Target Browser: ${capitalizedBrowserName(browser)}\n ${pintor.gray('└─')} ${pintor.underline(`${zipPath}`)} ${pintor.gray('(source)')}`;
197
+ }
198
+ function writingTypeDefinitions(manifest) {
199
+ return `${getLoggingPrefix('info')} Writing type definitions for ${pintor.blue(manifest.name || '')}...`;
200
+ }
201
+ function writingTypeDefinitionsError(error) {
202
+ return `${getLoggingPrefix('error')} Failed to write the extension type definition.\n${pintor.red(error)}`;
203
+ }
204
+ function downloadingText(url) {
205
+ return fmt.block('Downloading extension', [
206
+ [
207
+ 'URL',
208
+ fmt.val(url)
209
+ ]
210
+ ]);
211
+ }
212
+ function unpackagingExtension(zipFilePath) {
213
+ return `${getLoggingPrefix('info')} Unpackaging browser extension...\n${pintor.gray('PATH')} ${pintor.underline(zipFilePath)}`;
214
+ }
215
+ function unpackagedSuccessfully() {
216
+ return `${getLoggingPrefix('info')} Browser extension unpackaged ${pintor.green('successfully')}.`;
217
+ }
218
+ function failedToDownloadOrExtractZIPFileError(error) {
219
+ return `${getLoggingPrefix('error')} Failed to download or extract ZIP file.\n${pintor.red(error)}`;
220
+ }
221
+ function invalidRemoteZip(url, contentType) {
222
+ return `${getLoggingPrefix('error')} Remote URL does not appear to be a ZIP archive.\n${pintor.gray('URL')} ${pintor.underline(url)}\n${pintor.gray('Content-Type')} ${pintor.underline(contentType || 'unknown')}`;
223
+ }
224
+ function capitalizedBrowserName(browser) {
225
+ const b = String(browser || '');
226
+ const cap = b.charAt(0).toUpperCase() + b.slice(1);
227
+ return pintor.yellow(`${cap}`);
228
+ }
229
+ function getFileSize(fileSizeInBytes) {
230
+ return `${(fileSizeInBytes / 1024).toFixed(2)}KB`;
231
+ }
232
+ function getAssetsSize(assets) {
233
+ let totalSize = 0;
234
+ assets?.forEach((asset)=>{
235
+ totalSize += asset.size;
236
+ });
237
+ return getFileSize(totalSize);
238
+ }
239
+ function printTree(node, prefix = '') {
240
+ let output = '';
241
+ Object.keys(node).forEach((key, index, array)=>{
242
+ const isLast = index === array.length - 1;
243
+ const connector = isLast ? '└─' : '├─';
244
+ const sizeInKB = node[key].size ? ` (${getFileSize(node[key].size)})` : '';
245
+ output += `${pintor.gray(prefix)}${pintor.gray(connector)} ${key}${pintor.gray(sizeInKB)}\n`;
246
+ if ('object' == typeof node[key] && !node[key].size) output += printTree(node[key], `${prefix}${isLast ? ' ' : pintor.gray('│ ')}`);
247
+ });
248
+ return output;
249
+ }
250
+ function getAssetsTree(assets) {
251
+ const assetTree = {};
252
+ assets?.forEach((asset)=>{
253
+ const paths = asset.name.split('/');
254
+ let currentLevel = assetTree;
255
+ paths.forEach((part, index)=>{
256
+ if (!currentLevel[part]) currentLevel[part] = {};
257
+ if (index === paths.length - 1) currentLevel[part] = {
258
+ size: asset.size
259
+ };
260
+ else currentLevel = currentLevel[part];
261
+ });
262
+ });
263
+ return `.\n${printTree(assetTree)}`;
264
+ }
265
+ function formatWarningLabelLine(label, value) {
266
+ return `${pintor.gray('│')} ${pintor.gray(`${label}:`)} ${value}`;
267
+ }
268
+ function parsePerformanceWarning(warning, source, _artifact) {
269
+ const normalized = getWarningBody(warning).replace(/\r/g, '');
270
+ const lower = normalized.toLowerCase();
271
+ const threshold = normalized.match(/\(([\d.]+\s(?:KiB|MiB|GiB|KB|MB|GB))\)/)?.[1] || '';
272
+ if (lower.includes('asset size limit')) return formatPerformanceWarningBlock({
273
+ title: 'asset size limit exceeded',
274
+ threshold,
275
+ impact: 'Large emitted files can increase package size and slow extension startup.',
276
+ source,
277
+ hint: 'Inspect the largest startup bundles and split optional code paths.'
278
+ });
279
+ if (lower.includes('entrypoint size limit')) return formatPerformanceWarningBlock({
280
+ title: 'entrypoint size limit exceeded',
281
+ threshold,
282
+ impact: 'Startup entrypoints are heavier than recommended.',
283
+ source,
284
+ hint: 'Keep startup entrypoints thin and defer non-critical code.'
285
+ });
286
+ }
287
+ function formatPerformanceWarningBlock(options) {
288
+ const lines = [
289
+ `${getLoggingPrefix('warn')} Performance: ${options.title}`
290
+ ];
291
+ if (options.threshold) lines.push(formatWarningLabelLine('Threshold', options.threshold));
292
+ lines.push(formatWarningLabelLine('Impact', options.impact));
293
+ lines.push(pintor.gray('│'));
294
+ lines.push(formatWarningLabelLine('Source', pintor.gray(options.source)));
295
+ lines.push(formatWarningLabelLine('Hint', options.hint));
296
+ return lines.join('\n');
297
+ }
298
+ function getWarningBody(warning) {
299
+ if (!warning) return '';
300
+ if ('string' == typeof warning) return warning;
301
+ return [
302
+ warning.message,
303
+ warning.details,
304
+ warning.reason,
305
+ warning.description
306
+ ].filter((value)=>'string' == typeof value && value.trim().length > 0).join('\n');
307
+ }
308
+ function isUsingExperimentalConfig(integration) {
309
+ return `${getLoggingPrefix('info')} Using ${pintor.yellow(integration)}.`;
310
+ }
311
+ function debugDirs(manifestDir, packageJsonDir) {
312
+ return `${getLoggingPrefix('info')} Directories\n${pintor.gray('MANIFEST_DIR')} ${pintor.underline(manifestDir)}\n${pintor.gray('PACKAGE_JSON_DIR')} ${pintor.underline(packageJsonDir)}`;
313
+ }
314
+ function debugBrowser(browser, chromiumBinary, geckoBinary) {
315
+ return `${getLoggingPrefix('info')} Browser Target\n${pintor.gray('BROWSER')} ${pintor.yellow(String(browser))}\n${pintor.gray('CHROMIUM_BINARY')} ${pintor.underline(String(chromiumBinary || 'auto'))}\n${pintor.gray('GECKO_BINARY')} ${pintor.underline(String(geckoBinary || 'auto'))}`;
316
+ }
317
+ function debugOutputPath(pathValue) {
318
+ return `${getLoggingPrefix('info')} Output Path\n${pintor.gray('PATH')} ${pintor.underline(pathValue)}`;
319
+ }
320
+ function debugPreviewOutput(outputPath, distPath) {
321
+ return `${getLoggingPrefix('info')} Preview Output\n${pintor.gray('OUTPUT')} ${pintor.underline(outputPath)}\n${pintor.gray('DIST')} ${pintor.underline(distPath)}`;
322
+ }
323
+ function debugContextPath(packageJsonDir) {
324
+ return `${getLoggingPrefix('info')} Context\n${pintor.gray('CONTEXT')} ${pintor.underline(packageJsonDir)}`;
325
+ }
326
+ function debugExtensionsToLoad(extensions) {
327
+ const header = `${getLoggingPrefix('info')} Extensions To Load (${extensions.length})`;
328
+ const list = extensions.map((e)=>`- ${pintor.underline(e)}`).join('\n');
329
+ return `${header}\n${list}`;
330
+ }
331
+ function noCompanionExtensionsResolved() {
332
+ return `${getLoggingPrefix('warn')} No companion extensions resolved from ${pintor.underline('extensions')} config.\n${pintor.gray('Ensure each companion extension is an unpacked extension directory containing a manifest.json (e.g., ./extensions/<name>/manifest.json).')}`;
333
+ }
334
+ function configLoadingError(configPath, error) {
335
+ return `${pintor.red('ERROR')} ${pintor.brightBlue('config load failed')}\n${fmt.label('PATH')} ${fmt.val(configPath)}\n` + pintor.red(fmt.truncate(error, 1200));
336
+ }
337
+ function buildCommandFailed(error) {
338
+ const message = (()=>{
339
+ if (error instanceof Error && error.message) return error.message;
340
+ return String(error || 'Unknown error');
341
+ })();
342
+ return `${getLoggingPrefix('error')} Build failed.\n${pintor.red(fmt.truncate(message, 1200))}`;
343
+ }
344
+ function managedDependencyConflict(duplicates, userPackageJsonPath) {
345
+ const list = duplicates.map((d)=>`- ${pintor.yellow(d)}`).join('\n');
346
+ return `${getLoggingPrefix('error')} Your project declares dependencies that are managed by ${pintor.blue('Extension.js')} and referenced in ${pintor.underline('extension.config.js')}\n${pintor.red('This can cause version conflicts and break the development/build process.')}\n\n${pintor.gray('Managed dependencies (remove these from your package.json):')}\n${list}\n\n${pintor.gray('PATH')} ${pintor.underline(userPackageJsonPath)}\nIf you need a different version, open an issue so we can consider bundling it safely.\nOperation aborted.`;
347
+ }
348
+ async function findUpLocal(filename, options) {
349
+ const root = __rspack_external_path.parse(options.cwd).root;
350
+ let currentDir = options.cwd;
351
+ while(true){
352
+ const candidate = __rspack_external_path.join(currentDir, filename);
353
+ try {
354
+ const stat = await __rspack_external_fs.promises.stat(candidate);
355
+ if (stat.isFile()) return candidate;
356
+ } catch {}
357
+ if (currentDir === root) return;
358
+ currentDir = __rspack_external_path.dirname(currentDir);
359
+ }
360
+ }
361
+ async function findNearestPackageJson(manifestPath) {
362
+ try {
363
+ const manifestDir = __rspack_external_path.dirname(manifestPath);
364
+ const packageJsonPath = await findUpLocal('package.json', {
365
+ cwd: manifestDir
366
+ });
367
+ return packageJsonPath || null;
368
+ } catch (error) {
369
+ console.warn('Failed to find package.json:', error);
370
+ return null;
371
+ }
372
+ }
373
+ function validatePackageJson(packageJsonPath) {
374
+ try {
375
+ if (!__rspack_external_fs.existsSync(packageJsonPath)) return false;
376
+ const content = __rspack_external_fs.readFileSync(packageJsonPath, 'utf-8');
377
+ JSON.parse(content);
378
+ return true;
379
+ } catch (error) {
380
+ console.warn('Invalid package.json at:', packageJsonPath, error);
381
+ return false;
382
+ }
383
+ }
384
+ const isUrl = (url)=>{
385
+ try {
386
+ new URL(url);
387
+ return true;
388
+ } catch (e) {
389
+ return false;
390
+ }
391
+ };
392
+ async function importUrlSourceFromGithub(pathOrRemoteUrl, text) {
393
+ const cwd = process.cwd();
394
+ const url = new URL(pathOrRemoteUrl);
395
+ const segments = url.pathname.split('/').filter(Boolean);
396
+ const repoName = segments.length >= 2 ? segments[1] : segments[segments.length - 1];
397
+ const treeIndex = segments.indexOf('tree');
398
+ const expectedName = -1 !== treeIndex && segments.length > treeIndex + 2 ? segments[segments.length - 1] : repoName;
399
+ const expectedPath = __rspack_external_path.resolve(cwd, expectedName);
400
+ if (__rspack_external_fs.existsSync(expectedPath)) try {
401
+ const entries = __rspack_external_fs.readdirSync(expectedPath);
402
+ if (0 === entries.length) __rspack_external_fs.rmSync(expectedPath, {
403
+ recursive: true,
404
+ force: true
405
+ });
406
+ else {
407
+ const hasManifest = (dir)=>{
408
+ const stack = [
409
+ dir
410
+ ];
411
+ while(stack.length){
412
+ const current = stack.pop();
413
+ const items = __rspack_external_fs.readdirSync(current, {
414
+ withFileTypes: true
415
+ });
416
+ for (const it of items){
417
+ if (it.isFile() && 'manifest.json' === it.name) return true;
418
+ if (it.isDirectory() && 'node_modules' !== it.name && 'dist' !== it.name && !it.name.startsWith('.')) stack.push(__rspack_external_path.join(current, it.name));
419
+ }
420
+ }
421
+ return false;
422
+ };
423
+ if (hasManifest(expectedPath)) return expectedPath;
424
+ __rspack_external_fs.rmSync(expectedPath, {
425
+ recursive: true,
426
+ force: true
427
+ });
428
+ }
429
+ } catch {}
430
+ async function tryGitClone() {
431
+ const { default: goGitIt } = await import("go-git-it");
432
+ await goGitIt(pathOrRemoteUrl, cwd, text);
433
+ }
434
+ async function tryZipFallback() {
435
+ const branch = -1 !== treeIndex && segments.length > treeIndex + 1 ? segments[treeIndex + 1] : 'main';
436
+ const owner = segments[0];
437
+ const repo = segments[1];
438
+ const subdir = -1 !== treeIndex && segments.length > treeIndex + 2 ? segments.slice(treeIndex + 2).join('/') : '';
439
+ const zipUrl = `https://codeload.github.com/${owner}/${repo}/zip/refs/heads/${branch}`;
440
+ const extractedPath = await importUrlSourceFromZip(zipUrl);
441
+ const extractedDirs = __rspack_external_fs.readdirSync(extractedPath, {
442
+ withFileTypes: true
443
+ }).filter((d)=>d.isDirectory()).map((d)=>d.name);
444
+ const repoRootDir = extractedDirs.find((d)=>d.startsWith(`${repo}-${branch}`));
445
+ const repoRoot = repoRootDir ? __rspack_external_path.join(extractedPath, repoRootDir) : extractedPath;
446
+ return subdir ? __rspack_external_path.join(repoRoot, subdir) : repoRoot;
447
+ }
448
+ try {
449
+ await tryGitClone();
450
+ } catch {
451
+ return await tryZipFallback();
452
+ }
453
+ const candidates = [];
454
+ if (-1 !== treeIndex && segments.length > treeIndex + 2) candidates.push(segments[segments.length - 1]);
455
+ candidates.push(repoName);
456
+ for (const name of candidates){
457
+ const p = __rspack_external_path.resolve(cwd, name);
458
+ if (__rspack_external_fs.existsSync(p)) return p;
459
+ }
460
+ const dirs = __rspack_external_fs.readdirSync(cwd, {
461
+ withFileTypes: true
462
+ }).filter((d)=>d.isDirectory()).map((d)=>d.name);
463
+ for (const dir of dirs){
464
+ const manifestPath = __rspack_external_path.join(cwd, dir, 'manifest.json');
465
+ if (__rspack_external_fs.existsSync(manifestPath)) return __rspack_external_path.join(cwd, dir);
466
+ }
467
+ try {
468
+ const dirs = __rspack_external_fs.readdirSync(cwd, {
469
+ withFileTypes: true
470
+ }).filter((d)=>d.isDirectory()).map((d)=>d.name);
471
+ const ghRoot = dirs.find((d)=>/-main$|-master$/.test(d));
472
+ if (ghRoot) return __rspack_external_path.join(cwd, ghRoot);
473
+ } catch {}
474
+ throw new Error(downloadedProjectFolderNotFound(cwd, candidates));
475
+ }
476
+ async function importUrlSourceFromZip(pathOrRemoteUrl) {
477
+ const cwd = process.cwd();
478
+ const { downloadAndExtractZip } = await import("./0~zip.mjs");
479
+ const extractedPath = await downloadAndExtractZip(pathOrRemoteUrl, cwd);
480
+ return extractedPath;
481
+ }
482
+ async function getProjectPath(pathOrRemoteUrl) {
483
+ if (!pathOrRemoteUrl) return process.cwd();
484
+ if (isUrl(pathOrRemoteUrl)) {
485
+ const url = new URL(pathOrRemoteUrl);
486
+ if (url.protocol.startsWith('http')) {
487
+ const pathname = url.pathname.toLowerCase();
488
+ if (pathname.endsWith('.zip')) return await importUrlSourceFromZip(pathOrRemoteUrl);
489
+ if ('https://github.com' !== url.origin) {
490
+ const urlSource = await importUrlSourceFromZip(pathOrRemoteUrl);
491
+ return urlSource;
492
+ }
493
+ const urlData = url.pathname.split('/');
494
+ const owner = urlData.slice(1, 3)[0];
495
+ const project = urlData.slice(1, 3)[1];
496
+ console.log(fetchingProjectPath(owner, project));
497
+ const projectName = __rspack_external_path.basename(url.pathname);
498
+ const urlSource = await importUrlSourceFromGithub(pathOrRemoteUrl, downloadingProjectPath(projectName));
499
+ console.log(creatingProjectPath(url.pathname));
500
+ return urlSource;
501
+ }
502
+ }
503
+ return __rspack_external_path.resolve(process.cwd(), pathOrRemoteUrl);
504
+ }
505
+ async function getProjectStructure(pathOrRemoteUrl) {
506
+ const projectPath = await getProjectPath(pathOrRemoteUrl);
507
+ const isUnderDir = (baseDir, candidatePath)=>{
508
+ const rel = __rspack_external_path.relative(baseDir, candidatePath);
509
+ return Boolean(rel && !rel.startsWith('..') && !__rspack_external_path.isAbsolute(rel));
510
+ };
511
+ const packageJsonPathFromProject = await findNearestPackageJson(__rspack_external_path.join(projectPath, 'manifest.json'));
512
+ const packageJsonDirFromProject = packageJsonPathFromProject ? __rspack_external_path.dirname(packageJsonPathFromProject) : void 0;
513
+ const rootManifestPath = __rspack_external_path.join(projectPath, 'manifest.json');
514
+ const srcManifestPath = __rspack_external_path.join(projectPath, 'src', 'manifest.json');
515
+ let manifestPath = __rspack_external_fs.existsSync(srcManifestPath) ? srcManifestPath : rootManifestPath;
516
+ if (!__rspack_external_fs.existsSync(manifestPath)) {
517
+ if (packageJsonDirFromProject) throw new Error(manifestNotFoundError(manifestPath));
518
+ const findManifest = (dir)=>{
519
+ const files = __rspack_external_fs.readdirSync(dir, {
520
+ withFileTypes: true
521
+ });
522
+ for (const file of files){
523
+ if (file.isFile() && 'manifest.json' === file.name) return __rspack_external_path.join(dir, file.name);
524
+ if (file.isDirectory() && !file.name.startsWith('.') && 'node_modules' !== file.name && 'dist' !== file.name && 'public' !== file.name) {
525
+ const found = findManifest(__rspack_external_path.join(dir, file.name));
526
+ if (found) return found;
527
+ }
528
+ }
529
+ return null;
530
+ };
531
+ const foundManifest = findManifest(projectPath);
532
+ if (foundManifest) manifestPath = foundManifest;
533
+ else throw new Error(manifestNotFoundError(manifestPath));
534
+ }
535
+ const packageJsonPath = await findNearestPackageJson(manifestPath);
536
+ const packageJsonDir = packageJsonPath ? __rspack_external_path.dirname(packageJsonPath) : void 0;
537
+ if (packageJsonDir) {
538
+ const publicRoot = __rspack_external_path.join(packageJsonDir, 'public');
539
+ if (isUnderDir(publicRoot, manifestPath)) {
540
+ const fallbackSrc = __rspack_external_path.join(packageJsonDir, 'src', 'manifest.json');
541
+ const fallbackRoot = __rspack_external_path.join(packageJsonDir, 'manifest.json');
542
+ if (__rspack_external_fs.existsSync(fallbackSrc)) manifestPath = fallbackSrc;
543
+ else if (__rspack_external_fs.existsSync(fallbackRoot)) manifestPath = fallbackRoot;
544
+ else throw new Error(manifestNotFoundError(fallbackRoot));
545
+ }
546
+ }
547
+ if (!packageJsonPath || !validatePackageJson(packageJsonPath)) return {
548
+ manifestPath
549
+ };
550
+ return {
551
+ manifestPath,
552
+ packageJsonPath
553
+ };
554
+ }
555
+ function loadCommonJsConfigWithStableDirname(absolutePath) {
556
+ const code = __rspack_external_fs.readFileSync(absolutePath, 'utf-8');
557
+ const dirname = __rspack_external_path.dirname(absolutePath);
558
+ const requireFn = createRequire(absolutePath);
559
+ const module = {
560
+ exports: {}
561
+ };
562
+ const exports = module.exports;
563
+ const wrapped = `(function (exports, require, module, __filename, __dirname) {\n${code}\n})`;
564
+ const fn = new __rspack_external_vm.Script(wrapped, {
565
+ filename: absolutePath
566
+ }).runInThisContext();
567
+ fn(exports, requireFn, module, absolutePath, dirname);
568
+ return module.exports?.default || module.exports;
569
+ }
570
+ function findNearestWorkspaceRoot(startDir) {
571
+ let current = __rspack_external_path.resolve(startDir);
572
+ while(true){
573
+ if (__rspack_external_fs.existsSync(__rspack_external_path.join(current, 'pnpm-workspace.yaml'))) return current;
574
+ const parent = __rspack_external_path.dirname(current);
575
+ if (parent === current) return;
576
+ current = parent;
577
+ }
578
+ }
579
+ function preloadEnvFilesFromDir(envDir, options) {
580
+ let loadedAny = false;
581
+ try {
582
+ const defaultsPath = __rspack_external_path.join(envDir, '.env.defaults');
583
+ if (__rspack_external_fs.existsSync(defaultsPath)) {
584
+ dotenv.config({
585
+ path: defaultsPath,
586
+ override: Boolean(options?.override),
587
+ quiet: true
588
+ });
589
+ loadedAny = true;
590
+ }
591
+ const envCandidates = [
592
+ '.env.development',
593
+ '.env.local',
594
+ '.env'
595
+ ];
596
+ for (const filename of envCandidates){
597
+ const filePath = __rspack_external_path.join(envDir, filename);
598
+ if (__rspack_external_fs.existsSync(filePath)) {
599
+ dotenv.config({
600
+ path: filePath,
601
+ override: Boolean(options?.override),
602
+ quiet: true
603
+ });
604
+ loadedAny = true;
605
+ break;
606
+ }
607
+ }
608
+ } catch {}
609
+ return {
610
+ loadedAny,
611
+ envDir
612
+ };
613
+ }
614
+ function findConfigFile(projectPath) {
615
+ const candidates = [
616
+ __rspack_external_path.join(projectPath, 'extension.config.js'),
617
+ __rspack_external_path.join(projectPath, 'extension.config.mjs'),
618
+ __rspack_external_path.join(projectPath, 'extension.config.cjs')
619
+ ];
620
+ return candidates.find((p)=>__rspack_external_fs.existsSync(p));
621
+ }
622
+ function preloadEnvFiles(projectDir) {
623
+ const local = preloadEnvFilesFromDir(projectDir);
624
+ if (local.loadedAny) return local;
625
+ const workspaceRoot = findNearestWorkspaceRoot(projectDir);
626
+ if (workspaceRoot && workspaceRoot !== projectDir) return preloadEnvFilesFromDir(workspaceRoot);
627
+ return local;
628
+ }
629
+ async function loadConfigFile(configPath) {
630
+ const absolutePath = __rspack_external_path.resolve(configPath);
631
+ const projectDir = __rspack_external_path.dirname(absolutePath);
632
+ preloadEnvFiles(projectDir);
633
+ try {
634
+ if (absolutePath.endsWith('.cjs')) {
635
+ const requireFn = createRequire(import.meta.url);
636
+ const required = requireFn(absolutePath);
637
+ return required?.default || required;
638
+ }
639
+ let esmImportPath = absolutePath;
640
+ try {
641
+ const originalContent = __rspack_external_fs.readFileSync(absolutePath, 'utf-8');
642
+ if (originalContent.includes('import.meta.env')) {
643
+ const tmpDir = __rspack_external_fs.mkdtempSync(__rspack_external_path.join(__rspack_external_os.tmpdir(), 'extension-config-esm-'));
644
+ const tmpPath = __rspack_external_path.join(tmpDir, __rspack_external_path.basename(absolutePath));
645
+ const envObjectLiteral = JSON.stringify(Object.fromEntries(Object.entries(process.env).map(([k, v])=>[
646
+ k,
647
+ v
648
+ ])), null, 0);
649
+ const shimHeader = `const __IMPORT_META_ENV__ = Object.freeze(${envObjectLiteral});\n`;
650
+ const replaced = originalContent.replace(/import\.meta\.env/g, '__IMPORT_META_ENV__');
651
+ __rspack_external_fs.writeFileSync(tmpPath, `${shimHeader}${replaced}`, 'utf-8');
652
+ esmImportPath = tmpPath;
653
+ }
654
+ } catch {}
655
+ const module = await import(pathToFileURL(esmImportPath).href);
656
+ return module.default || module;
657
+ } catch (err) {
658
+ const error = err;
659
+ try {
660
+ if (!absolutePath.endsWith('.mjs')) {
661
+ const requireFn = createRequire(import.meta.url);
662
+ let required;
663
+ try {
664
+ required = requireFn(absolutePath);
665
+ } catch (requireErr) {
666
+ const message = String(error?.message || '') + ' ' + String(requireErr?.message || '');
667
+ const looksLikeCommonJsInEsm = message.includes('require is not defined in ES module scope') || message.includes('Cannot use import statement outside a module') || message.includes('ERR_REQUIRE_ESM');
668
+ if (looksLikeCommonJsInEsm) try {
669
+ required = loadCommonJsConfigWithStableDirname(absolutePath);
670
+ } catch {
671
+ const tmpDir = __rspack_external_fs.mkdtempSync(__rspack_external_path.join(__rspack_external_os.tmpdir(), 'extension-config-'));
672
+ const tmpCjsPath = __rspack_external_path.join(tmpDir, __rspack_external_path.basename(absolutePath, __rspack_external_path.extname(absolutePath)) + '.cjs');
673
+ __rspack_external_fs.copyFileSync(absolutePath, tmpCjsPath);
674
+ required = requireFn(tmpCjsPath);
675
+ }
676
+ else throw requireErr;
677
+ }
678
+ return required?.default || required;
679
+ }
680
+ } catch {}
681
+ try {
682
+ const content = __rspack_external_fs.readFileSync(absolutePath, 'utf-8');
683
+ return JSON.parse(content);
684
+ } catch (jsonErr) {
685
+ throw new Error(`Failed to load config file: ${configPath}\nError: ${error.message || error}`);
686
+ }
687
+ }
688
+ }
689
+ async function loadCustomConfig(projectPath) {
690
+ const configPath = findConfigFile(projectPath);
691
+ if (configPath) {
692
+ if (await config_loader_isUsingExperimentalConfig(projectPath)) try {
693
+ const userConfig = await loadConfigFile(configPath);
694
+ if (userConfig && 'function' == typeof userConfig.config) return userConfig.config;
695
+ if (userConfig && userConfig.config && 'object' == typeof userConfig.config) {
696
+ const partial = userConfig.config;
697
+ return (config)=>{
698
+ const requireFn = createRequire(import.meta.url);
699
+ const { merge } = requireFn('webpack-merge');
700
+ return merge(config, partial);
701
+ };
702
+ }
703
+ } catch (err) {
704
+ const error = err;
705
+ console.error(configLoadingError(configPath, error));
706
+ throw err;
707
+ }
708
+ }
709
+ return (config)=>config;
710
+ }
711
+ async function loadCommandConfig(projectPath, command) {
712
+ const configPath = findConfigFile(projectPath);
713
+ if (configPath) {
714
+ if (await config_loader_isUsingExperimentalConfig(projectPath)) try {
715
+ const userConfig = await loadConfigFile(configPath);
716
+ const baseExtensions = userConfig && userConfig.extensions ? {
717
+ extensions: userConfig.extensions
718
+ } : {};
719
+ const baseTranspilePackages = userConfig && Array.isArray(userConfig.transpilePackages) ? {
720
+ transpilePackages: userConfig.transpilePackages
721
+ } : {};
722
+ const perCommand = userConfig && userConfig.commands && userConfig.commands[command] ? userConfig.commands[command] : {};
723
+ return {
724
+ ...baseExtensions,
725
+ ...baseTranspilePackages,
726
+ ...perCommand
727
+ };
728
+ } catch (err) {
729
+ const error = err;
730
+ console.error(configLoadingError(configPath, error));
731
+ throw err;
732
+ }
733
+ }
734
+ return {};
735
+ }
736
+ async function loadBrowserConfig(projectPath, browser = 'chrome') {
737
+ const configPath = findConfigFile(projectPath);
738
+ if (configPath) {
739
+ if (await config_loader_isUsingExperimentalConfig(projectPath)) try {
740
+ const userConfig = await loadConfigFile(configPath);
741
+ if (userConfig && userConfig.browser) {
742
+ const browsers = userConfig.browser;
743
+ if ('chromium-based' === browser) {
744
+ if (browsers['chromium-based']) return browsers['chromium-based'];
745
+ if (browsers.chromium) return browsers.chromium;
746
+ } else if ('gecko-based' === browser) {
747
+ if (browsers['gecko-based']) return browsers['gecko-based'];
748
+ if (browsers.firefox) return browsers.firefox;
749
+ } else {
750
+ const direct = browsers[browser];
751
+ if (direct) return direct;
752
+ }
753
+ }
754
+ } catch (err) {
755
+ const error = err;
756
+ console.error(configLoadingError(configPath, error));
757
+ throw err;
758
+ }
759
+ }
760
+ return {
761
+ browser: browser || 'chrome'
762
+ };
763
+ }
764
+ let userMessageDelivered = false;
765
+ async function config_loader_isUsingExperimentalConfig(projectPath) {
766
+ const configPath = findConfigFile(projectPath);
767
+ if (configPath) {
768
+ if (!userMessageDelivered) {
769
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(isUsingExperimentalConfig('extension.config.js'));
770
+ userMessageDelivered = true;
771
+ }
772
+ return true;
773
+ }
774
+ return false;
775
+ }
776
+ function assertNoManagedDependencyConflicts(userPackageJsonPath, projectPath) {
777
+ try {
778
+ const raw = __rspack_external_fs.readFileSync(userPackageJsonPath, 'utf-8');
779
+ const userPackageJson = JSON.parse(raw);
780
+ const userDeps = Array.from(new Set([
781
+ ...Object.keys(userPackageJson.dependencies || {}),
782
+ ...Object.keys(userPackageJson.devDependencies || {}),
783
+ ...Object.keys(userPackageJson.optionalDependencies || {}),
784
+ ...Object.keys(userPackageJson.peerDependencies || {})
785
+ ]));
786
+ const managedDeps = new Set([
787
+ ...Object.keys(package_namespaceObject.El || {}),
788
+ ...Object.keys(package_namespaceObject.optionalDependencies || {})
789
+ ]);
790
+ managedDeps.delete('webpack');
791
+ const userConfigJs = __rspack_external_path.join(projectPath, 'extension.config.js');
792
+ const userConfigMjs = __rspack_external_path.join(projectPath, 'extension.config.mjs');
793
+ const hasConfig = __rspack_external_fs.existsSync(userConfigJs) || __rspack_external_fs.existsSync(userConfigMjs);
794
+ if (!hasConfig) return;
795
+ const configPath = __rspack_external_fs.existsSync(userConfigJs) ? userConfigJs : userConfigMjs;
796
+ const configSource = __rspack_external_fs.readFileSync(configPath, 'utf-8');
797
+ const duplicates = userDeps.filter((d)=>managedDeps.has(d)).filter((d)=>configSource.includes(d)).sort();
798
+ if (duplicates.length > 0) {
799
+ console.error(managedDependencyConflict(duplicates, userPackageJsonPath));
800
+ process.exit(1);
801
+ }
802
+ } catch (error) {
803
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.warn(error);
804
+ }
805
+ }
806
+ function asAbsolute(p) {
807
+ return __rspack_external_path.isAbsolute(p) ? p : __rspack_external_path.resolve(p);
808
+ }
809
+ function getDirs(struct) {
810
+ const manifestDir = asAbsolute(__rspack_external_path.dirname(struct.manifestPath));
811
+ const packageJsonDir = asAbsolute(struct.packageJsonPath ? __rspack_external_path.dirname(struct.packageJsonPath) : manifestDir);
812
+ return {
813
+ manifestDir,
814
+ packageJsonDir
815
+ };
816
+ }
817
+ function getNodeModulesDir(packageJsonDir) {
818
+ return asAbsolute(__rspack_external_path.join(packageJsonDir, 'node_modules'));
819
+ }
820
+ function needsInstall(packageJsonDir) {
821
+ const nm = getNodeModulesDir(packageJsonDir);
822
+ const packageJsonPath = __rspack_external_path.join(packageJsonDir, 'package.json');
823
+ if (!__rspack_external_fs.existsSync(packageJsonPath)) return false;
824
+ try {
825
+ const raw = __rspack_external_fs.readFileSync(packageJsonPath, 'utf-8');
826
+ const packageJson = JSON.parse(raw);
827
+ const depsCount = Object.keys(packageJson?.dependencies || {}).length;
828
+ const devDepsCount = Object.keys(packageJson?.devDependencies || {}).length;
829
+ if (depsCount + devDepsCount === 0) return false;
830
+ if (!__rspack_external_fs.existsSync(nm)) return true;
831
+ const deps = Object.keys(packageJson?.dependencies || {});
832
+ const devDeps = Object.keys(packageJson?.devDependencies || {});
833
+ if (__rspack_external_fs.existsSync(__rspack_external_path.join(nm, '.pnpm'))) return false;
834
+ if (__rspack_external_fs.existsSync(__rspack_external_path.join(nm, '.modules.yaml'))) return false;
835
+ const hasInstalledDep = [
836
+ ...deps,
837
+ ...devDeps
838
+ ].some((dep)=>__rspack_external_fs.existsSync(__rspack_external_path.join(nm, dep)));
839
+ return !hasInstalledDep;
840
+ } catch {
841
+ return true;
842
+ }
843
+ }
844
+ function normalizeBrowser(browser, chromiumBinary, geckoBinary) {
845
+ const requested = String(browser || '');
846
+ if (chromiumBinary) {
847
+ if (!requested || 'chromium-based' === requested) return 'chromium-based';
848
+ if ('chromium' === requested) return 'chromium';
849
+ if ('edge' === requested) return 'edge';
850
+ if ('chrome' === requested) return 'chrome';
851
+ }
852
+ if (geckoBinary) {
853
+ if (!requested || 'gecko-based' === requested || 'firefox-based' === requested) return 'gecko-based';
854
+ if ('firefox' === requested) return 'firefox';
855
+ }
856
+ switch(requested){
857
+ case 'chrome':
858
+ return 'chrome';
859
+ case 'edge':
860
+ return 'edge';
861
+ case 'chromium':
862
+ return 'chromium';
863
+ case 'chromium-based':
864
+ return 'chromium-based';
865
+ case 'firefox':
866
+ return 'firefox';
867
+ case 'gecko-based':
868
+ case 'firefox-based':
869
+ return 'gecko-based';
870
+ default:
871
+ return browser || 'chrome';
872
+ }
873
+ }
874
+ function getDistPath(packageJsonDir, browser) {
875
+ return asAbsolute(__rspack_external_path.join(packageJsonDir, 'dist', browser));
876
+ }
877
+ function computePreviewOutputPath(struct, browser, explicitOutputPath) {
878
+ const { manifestDir, packageJsonDir } = getDirs(struct);
879
+ if (explicitOutputPath) return asAbsolute(explicitOutputPath);
880
+ if (struct.packageJsonPath) {
881
+ const distDir = getDistPath(packageJsonDir, browser);
882
+ try {
883
+ if (__rspack_external_fs.existsSync(__rspack_external_path.join(distDir, 'manifest.json'))) return distDir;
884
+ } catch {}
885
+ }
886
+ return manifestDir;
887
+ }
888
+ function devtoolsEngineFor(browser) {
889
+ switch(browser){
890
+ case 'chrome':
891
+ return 'chrome';
892
+ case 'edge':
893
+ return 'edge';
894
+ case 'chromium':
895
+ case 'chromium-based':
896
+ return 'chromium';
897
+ case 'firefox':
898
+ case 'gecko-based':
899
+ return 'firefox';
900
+ default:
901
+ return 'chrome';
902
+ }
903
+ }
904
+ function isDir(p) {
905
+ try {
906
+ return __rspack_external_fs.existsSync(p) && __rspack_external_fs.statSync(p).isDirectory();
907
+ } catch {
908
+ return false;
909
+ }
910
+ }
911
+ function isFile(p) {
912
+ try {
913
+ return __rspack_external_fs.existsSync(p) && __rspack_external_fs.statSync(p).isFile();
914
+ } catch {
915
+ return false;
916
+ }
917
+ }
918
+ function toAbs(projectRoot, p) {
919
+ return __rspack_external_path.isAbsolute(p) ? p : __rspack_external_path.resolve(projectRoot, p);
920
+ }
921
+ function isValidExtensionRoot(dir) {
922
+ if (!isDir(dir)) return false;
923
+ return isFile(__rspack_external_path.join(dir, 'manifest.json'));
924
+ }
925
+ function normalizeCompanionConfig(config) {
926
+ const explicitPaths = [];
927
+ let scanDir;
928
+ if (Array.isArray(config)) explicitPaths.push(...config.filter((p)=>'string' == typeof p));
929
+ else if (config && 'object' == typeof config) {
930
+ if (Array.isArray(config.paths)) explicitPaths.push(...config.paths.filter((p)=>'string' == typeof p));
931
+ if ('string' == typeof config.dir && config.dir.trim().length > 0) scanDir = config.dir.trim();
932
+ }
933
+ return {
934
+ dir: scanDir,
935
+ paths: explicitPaths
936
+ };
937
+ }
938
+ function resolve_config_isPathLike(value) {
939
+ if (__rspack_external_path.isAbsolute(value)) return true;
940
+ if (value.startsWith('./') || value.startsWith('../')) return true;
941
+ return value.includes('/') || value.includes('\\');
942
+ }
943
+ function isSubpathOf(parent, child) {
944
+ const rel = __rspack_external_path.relative(parent, child);
945
+ return '' !== rel && !rel.startsWith('..') && !__rspack_external_path.isAbsolute(rel);
946
+ }
947
+ function getBrowserFolder(browser) {
948
+ if ('firefox' === browser || 'gecko-based' === browser || 'firefox-based' === browser) return 'firefox';
949
+ if ('edge' === browser) return 'edge';
950
+ return 'chrome';
951
+ }
952
+ function parseChromeWebStoreId(url) {
953
+ if ('chromewebstore.google.com' !== url.hostname) return null;
954
+ const match = url.pathname.match(/\/([a-z]{32})(?:\/|$)/i);
955
+ return match ? match[1] : null;
956
+ }
957
+ function parseEdgeAddonsId(url) {
958
+ if ('microsoftedge.microsoft.com' !== url.hostname) return null;
959
+ const match = url.pathname.match(/\/([a-z]{32})(?:\/|$)/i);
960
+ return match ? match[1] : null;
961
+ }
962
+ function parseAmoSlug(url) {
963
+ if ('addons.mozilla.org' !== url.hostname) return null;
964
+ const match = url.pathname.match(/\/addon\/([^/]+)(?:\/|$)/i);
965
+ return match ? match[1] : null;
966
+ }
967
+ function parseStoreUrl(raw) {
968
+ let url;
969
+ try {
970
+ url = new URL(raw);
971
+ } catch {
972
+ return null;
973
+ }
974
+ const chromeId = parseChromeWebStoreId(url);
975
+ if (chromeId) return {
976
+ browser: 'chrome',
977
+ id: chromeId
978
+ };
979
+ const edgeId = parseEdgeAddonsId(url);
980
+ if (edgeId) return {
981
+ browser: 'edge',
982
+ id: edgeId
983
+ };
984
+ const amoSlug = parseAmoSlug(url);
985
+ if (amoSlug) return {
986
+ browser: 'firefox',
987
+ id: amoSlug
988
+ };
989
+ return null;
990
+ }
991
+ function ensurePathsUnderExtensions(projectRoot, paths) {
992
+ const extensionsRoot = __rspack_external_path.resolve(projectRoot, 'extensions');
993
+ return paths.map((p)=>{
994
+ const abs = toAbs(projectRoot, p);
995
+ if (abs !== extensionsRoot && !isSubpathOf(extensionsRoot, abs) && __rspack_external_path.resolve(abs) !== extensionsRoot) throw new Error(`Companion extensions must be inside ${extensionsRoot}.\nInvalid path: ${abs}`);
996
+ return abs;
997
+ });
998
+ }
999
+ function findExtensionRoots(dir, maxDepth = 3) {
1000
+ const found = [];
1001
+ function walk(current, depth) {
1002
+ if (depth > maxDepth) return;
1003
+ if (!isDir(current)) return;
1004
+ if (isValidExtensionRoot(current)) return void found.push(current);
1005
+ let entries = [];
1006
+ try {
1007
+ entries = __rspack_external_fs.readdirSync(current, {
1008
+ withFileTypes: true
1009
+ });
1010
+ } catch {
1011
+ return;
1012
+ }
1013
+ for (const ent of entries)if (ent.isDirectory()) {
1014
+ if (!ent.name.startsWith('.')) walk(__rspack_external_path.join(current, ent.name), depth + 1);
1015
+ }
1016
+ }
1017
+ walk(dir, 0);
1018
+ return found;
1019
+ }
1020
+ async function runExtensionFromStore(url, outDir) {
1021
+ const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
1022
+ await fetchExtensionFromStore(url, {
1023
+ outDir,
1024
+ extract: true,
1025
+ logger: isAuthor ? {
1026
+ onInfo: (message)=>console.log(message),
1027
+ onWarn: (message)=>console.warn(message),
1028
+ onError: (message, error)=>console.error(message, error)
1029
+ } : void 0
1030
+ });
1031
+ }
1032
+ async function resolveStoreExtensionToPath(opts) {
1033
+ const { projectRoot, storeUrl, browser, id } = opts;
1034
+ const extensionsRoot = __rspack_external_path.resolve(projectRoot, 'extensions');
1035
+ const targetRoot = __rspack_external_path.join(extensionsRoot, browser, id);
1036
+ const manifestPath = __rspack_external_path.join(targetRoot, 'manifest.json');
1037
+ if (isFile(manifestPath)) return targetRoot;
1038
+ await runExtensionFromStore(storeUrl, __rspack_external_path.join(extensionsRoot, browser));
1039
+ const candidates = findExtensionRoots(__rspack_external_path.join(extensionsRoot, browser));
1040
+ let selected;
1041
+ if (1 === candidates.length) selected = candidates[0];
1042
+ else if (candidates.length > 1) {
1043
+ const directMatch = candidates.find((c)=>__rspack_external_path.basename(c) === id);
1044
+ const versionedMatch = candidates.find((c)=>__rspack_external_path.basename(c).startsWith(`${id}@`));
1045
+ if (directMatch) selected = directMatch;
1046
+ else if (versionedMatch) selected = versionedMatch;
1047
+ }
1048
+ if (!selected) throw new Error(`Could not locate an unpacked extension from ${storeUrl}.`);
1049
+ __rspack_external_fs.mkdirSync(__rspack_external_path.dirname(targetRoot), {
1050
+ recursive: true
1051
+ });
1052
+ if (__rspack_external_path.basename(selected).startsWith(`${id}@`)) __rspack_external_fs.renameSync(selected, targetRoot);
1053
+ return targetRoot;
1054
+ }
1055
+ async function resolveCompanionExtensionsConfig(opts) {
1056
+ const { projectRoot, browser, config } = opts;
1057
+ if (!config) return;
1058
+ const normalized = normalizeCompanionConfig(config);
1059
+ const runtimeBrowser = getBrowserFolder(browser);
1060
+ const resolvedPaths = [];
1061
+ const localPaths = [];
1062
+ for (const entry of normalized.paths){
1063
+ const parsedStore = parseStoreUrl(entry);
1064
+ if (parsedStore) {
1065
+ if (parsedStore.browser !== runtimeBrowser) continue;
1066
+ const resolvedPath = await resolveStoreExtensionToPath({
1067
+ projectRoot,
1068
+ storeUrl: entry,
1069
+ browser: parsedStore.browser,
1070
+ id: parsedStore.id
1071
+ });
1072
+ resolvedPaths.push(resolvedPath);
1073
+ continue;
1074
+ }
1075
+ if (resolve_config_isPathLike(entry)) localPaths.push(entry);
1076
+ }
1077
+ if (localPaths.length > 0) {
1078
+ const absLocalPaths = ensurePathsUnderExtensions(projectRoot, localPaths);
1079
+ resolvedPaths.push(...absLocalPaths);
1080
+ }
1081
+ const output = {};
1082
+ if ('string' == typeof normalized.dir) {
1083
+ const absDir = toAbs(projectRoot, normalized.dir);
1084
+ const extensionsRoot = __rspack_external_path.resolve(projectRoot, 'extensions');
1085
+ if (absDir !== extensionsRoot && !isSubpathOf(extensionsRoot, absDir)) throw new Error(`extensions.dir must be inside ${extensionsRoot}.\nInvalid dir: ${absDir}`);
1086
+ output.dir = normalized.dir;
1087
+ }
1088
+ if (resolvedPaths.length > 0) output.paths = resolvedPaths;
1089
+ return output;
1090
+ }
1091
+ function isUnderPublicDir(entry, projectRoot, publicDir) {
1092
+ if (!entry) return false;
1093
+ const normalizedEntry = String(entry);
1094
+ const candidate = path_0.isAbsolute(normalizedEntry) ? normalizedEntry : path_0.join(projectRoot, normalizedEntry);
1095
+ const rel = path_0.relative(publicDir, candidate);
1096
+ return Boolean(rel && !rel.startsWith('..') && !path_0.isAbsolute(rel));
1097
+ }
1098
+ function filterPublicEntrypoints(list, projectRoot, publicDir) {
1099
+ const next = {};
1100
+ for (const [key, value] of Object.entries(list || {})){
1101
+ if (Array.isArray(value)) {
1102
+ const filtered = value.filter((entry)=>!isUnderPublicDir(String(entry), projectRoot, publicDir));
1103
+ if (filtered.length > 0) next[key] = filtered;
1104
+ continue;
1105
+ }
1106
+ if ('string' == typeof value) {
1107
+ if (!isUnderPublicDir(value, projectRoot, publicDir)) next[key] = value;
1108
+ continue;
1109
+ }
1110
+ }
1111
+ return next;
1112
+ }
1113
+ function getSpecialFoldersDataForCompiler(compiler) {
1114
+ const projectRoot = compiler.options.context || '';
1115
+ const publicDir = path_0.join(projectRoot, 'public');
1116
+ const data = getSpecialFoldersData({
1117
+ manifestPath: path_0.join(projectRoot, 'package.json')
1118
+ });
1119
+ return finalizeSpecialFoldersData(data, projectRoot, publicDir);
1120
+ }
1121
+ function getSpecialFoldersDataForProjectRoot(projectRoot) {
1122
+ const publicDir = path_0.join(projectRoot, 'public');
1123
+ const data = getSpecialFoldersData({
1124
+ manifestPath: path_0.join(projectRoot, 'package.json')
1125
+ });
1126
+ return finalizeSpecialFoldersData(data, projectRoot, publicDir);
1127
+ }
1128
+ function finalizeSpecialFoldersData(data, projectRoot, publicDir) {
1129
+ return {
1130
+ ...data,
1131
+ pages: filterPublicEntrypoints(data.pages, projectRoot, publicDir),
1132
+ scripts: filterPublicEntrypoints(data.scripts, projectRoot, publicDir),
1133
+ extensions: {
1134
+ dir: './extensions'
1135
+ }
1136
+ };
1137
+ }
1138
+ function sanitize(obj) {
1139
+ return Object.fromEntries(Object.entries(obj || {}).filter(([, value])=>void 0 !== value));
1140
+ }
1141
+ function nowISO() {
1142
+ return new Date().toISOString();
1143
+ }
1144
+ function createRunId() {
1145
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
1146
+ }
1147
+ function plugin_playwright_ensureDirSync(dirPath) {
1148
+ try {
1149
+ __rspack_external_fs.mkdirSync(dirPath, {
1150
+ recursive: true
1151
+ });
1152
+ } catch {}
1153
+ }
1154
+ function writeJsonAtomic(filePath, value) {
1155
+ try {
1156
+ const tmpPath = `${filePath}.tmp-${process.pid}`;
1157
+ __rspack_external_fs.writeFileSync(tmpPath, JSON.stringify(value, null, 2) + '\n', 'utf-8');
1158
+ __rspack_external_fs.renameSync(tmpPath, filePath);
1159
+ } catch {}
1160
+ }
1161
+ function getPlaywrightMetadataDir(packageJsonDir, browser) {
1162
+ return asAbsolute(__rspack_external_path.join(packageJsonDir, 'dist', 'extension-js', browser));
1163
+ }
1164
+ function createPlaywrightMetadataWriter(options) {
1165
+ const metadataDir = getPlaywrightMetadataDir(options.packageJsonDir, options.browser);
1166
+ const readyPath = asAbsolute(__rspack_external_path.join(metadataDir, 'ready.json'));
1167
+ const eventsPath = asAbsolute(__rspack_external_path.join(metadataDir, 'events.ndjson'));
1168
+ const base = {
1169
+ command: options.command,
1170
+ browser: options.browser,
1171
+ runId: createRunId(),
1172
+ startedAt: nowISO(),
1173
+ distPath: options.distPath,
1174
+ manifestPath: options.manifestPath,
1175
+ port: (()=>{
1176
+ if ('number' == typeof options.port && Number.isFinite(options.port)) return options.port;
1177
+ if ('string' == typeof options.port) {
1178
+ const parsed = parseInt(options.port, 10);
1179
+ return Number.isFinite(parsed) ? parsed : null;
1180
+ }
1181
+ return null;
1182
+ })()
1183
+ };
1184
+ function writeReady(status, extra) {
1185
+ plugin_playwright_ensureDirSync(metadataDir);
1186
+ const payload = {
1187
+ ...base,
1188
+ status,
1189
+ pid: process.pid,
1190
+ ts: nowISO(),
1191
+ compiledAt: extra?.compiledAt ?? null,
1192
+ errors: Array.isArray(extra?.errors) ? extra.errors : []
1193
+ };
1194
+ if (extra?.code) payload.code = extra.code;
1195
+ if (extra?.message) payload.message = extra.message;
1196
+ writeJsonAtomic(readyPath, payload);
1197
+ }
1198
+ function appendEvent(event) {
1199
+ plugin_playwright_ensureDirSync(metadataDir);
1200
+ try {
1201
+ __rspack_external_fs.appendFileSync(eventsPath, `${JSON.stringify(event)}\n`, 'utf-8');
1202
+ } catch {}
1203
+ }
1204
+ return {
1205
+ metadataDir,
1206
+ readyPath,
1207
+ eventsPath,
1208
+ writeStarting () {
1209
+ writeReady('starting');
1210
+ },
1211
+ writeReady (compiledAt) {
1212
+ writeReady('ready', {
1213
+ compiledAt: compiledAt || nowISO()
1214
+ });
1215
+ },
1216
+ writeError (code, message, errors) {
1217
+ writeReady('error', {
1218
+ code,
1219
+ message,
1220
+ errors: Array.isArray(errors) ? errors : [],
1221
+ compiledAt: null
1222
+ });
1223
+ },
1224
+ appendEvent
1225
+ };
1226
+ }
1227
+ class PlaywrightPlugin {
1228
+ static name = 'plugin-playwright';
1229
+ writer;
1230
+ command;
1231
+ browser;
1232
+ constructor(options){
1233
+ this.browser = String(options.browser || 'chromium');
1234
+ this.command = options.command || ('development' === options.mode ? 'dev' : 'start');
1235
+ this.writer = createPlaywrightMetadataWriter({
1236
+ packageJsonDir: options.packageJsonDir,
1237
+ browser: this.browser,
1238
+ command: this.command,
1239
+ distPath: options.outputPath,
1240
+ manifestPath: options.manifestPath,
1241
+ port: options.port
1242
+ });
1243
+ }
1244
+ apply(compiler) {
1245
+ this.writer.writeStarting();
1246
+ compiler.hooks.compile.tap(PlaywrightPlugin.name, ()=>{
1247
+ this.writer.appendEvent({
1248
+ type: 'compile_start',
1249
+ ts: nowISO(),
1250
+ command: this.command,
1251
+ browser: this.browser
1252
+ });
1253
+ });
1254
+ compiler.hooks.done.tap(PlaywrightPlugin.name, (stats)=>{
1255
+ const durationMs = Number((stats?.compilation?.endTime || 0) - (stats?.compilation?.startTime || 0));
1256
+ const hasErrors = Boolean(stats?.hasErrors?.());
1257
+ const errorsCount = Number(Array.isArray(stats?.toJson?.({
1258
+ all: false,
1259
+ errors: true
1260
+ })?.errors) ? stats.toJson({
1261
+ all: false,
1262
+ errors: true
1263
+ }).errors.length : 0);
1264
+ if (hasErrors) {
1265
+ this.writer.appendEvent({
1266
+ type: 'compile_error',
1267
+ ts: nowISO(),
1268
+ command: this.command,
1269
+ browser: this.browser,
1270
+ durationMs: Number.isFinite(durationMs) ? durationMs : void 0,
1271
+ errorCount: Number.isFinite(errorsCount) ? errorsCount : 1
1272
+ });
1273
+ this.writer.writeError('compile_error', 'Compilation failed', [
1274
+ `errors: ${String(errorsCount || 1)}`
1275
+ ]);
1276
+ return;
1277
+ }
1278
+ this.writer.appendEvent({
1279
+ type: 'compile_success',
1280
+ ts: nowISO(),
1281
+ command: this.command,
1282
+ browser: this.browser,
1283
+ durationMs: Number.isFinite(durationMs) ? durationMs : void 0,
1284
+ errorCount: 0
1285
+ });
1286
+ this.writer.writeReady(nowISO());
1287
+ });
1288
+ compiler.hooks.failed.tap(PlaywrightPlugin.name, (error)=>{
1289
+ this.writer.appendEvent({
1290
+ type: 'compile_error',
1291
+ ts: nowISO(),
1292
+ command: this.command,
1293
+ browser: this.browser,
1294
+ errorCount: 1
1295
+ });
1296
+ this.writer.writeError('compile_failed', error instanceof Error ? error.message : String(error));
1297
+ });
1298
+ compiler.hooks.watchClose.tap(PlaywrightPlugin.name, ()=>{
1299
+ this.writer.appendEvent({
1300
+ type: 'shutdown',
1301
+ ts: nowISO(),
1302
+ command: this.command,
1303
+ browser: this.browser
1304
+ });
1305
+ });
1306
+ }
1307
+ }
1308
+ function resolveCompanionExtensionDirs(opts) {
1309
+ const { projectRoot, config } = opts;
1310
+ const normalized = normalizeCompanionConfig(config);
1311
+ const explicitPaths = normalized.paths;
1312
+ const scanDir = normalized.dir;
1313
+ const found = [];
1314
+ for (const p of explicitPaths){
1315
+ const abs = toAbs(projectRoot, p);
1316
+ if (isValidExtensionRoot(abs)) found.push(abs);
1317
+ }
1318
+ if (scanDir) {
1319
+ const absScan = toAbs(projectRoot, scanDir);
1320
+ if (isDir(absScan)) {
1321
+ let entries = [];
1322
+ try {
1323
+ entries = __rspack_external_fs.readdirSync(absScan, {
1324
+ withFileTypes: true
1325
+ });
1326
+ } catch {
1327
+ entries = [];
1328
+ }
1329
+ const scanOneLevel = (rootDir)=>{
1330
+ let dirEntries = [];
1331
+ try {
1332
+ dirEntries = __rspack_external_fs.readdirSync(rootDir, {
1333
+ withFileTypes: true
1334
+ });
1335
+ } catch {
1336
+ dirEntries = [];
1337
+ }
1338
+ for (const ent of dirEntries){
1339
+ if (!ent.isDirectory()) continue;
1340
+ if (ent.name.startsWith('.')) continue;
1341
+ const candidate = __rspack_external_path.join(rootDir, ent.name);
1342
+ if (isValidExtensionRoot(candidate)) found.push(candidate);
1343
+ }
1344
+ };
1345
+ scanOneLevel(absScan);
1346
+ if ('extensions' === __rspack_external_path.basename(absScan)) for (const ent of entries){
1347
+ if (!ent.isDirectory()) continue;
1348
+ if (ent.name.startsWith('.')) continue;
1349
+ const browserDir = __rspack_external_path.join(absScan, ent.name);
1350
+ scanOneLevel(browserDir);
1351
+ }
1352
+ }
1353
+ }
1354
+ const unique = [];
1355
+ const seen = new Set();
1356
+ for (const p of found)if (!seen.has(p)) {
1357
+ seen.add(p);
1358
+ unique.push(p);
1359
+ }
1360
+ return unique;
1361
+ }
1362
+ function hasNewTabOverride(extensionDir) {
1363
+ const manifestPath = __rspack_external_path.join(extensionDir, 'manifest.json');
1364
+ if (!__rspack_external_fs.existsSync(manifestPath)) return false;
1365
+ try {
1366
+ const raw = __rspack_external_fs.readFileSync(manifestPath, 'utf-8');
1367
+ const manifest = JSON.parse(raw);
1368
+ const newtab = manifest?.chrome_url_overrides?.newtab;
1369
+ return 'string' == typeof newtab && newtab.trim().length > 0;
1370
+ } catch {
1371
+ return false;
1372
+ }
1373
+ }
1374
+ function resolveBuiltInExtensionForBrowser(input) {
1375
+ const engine = devtoolsEngineFor(input.browser);
1376
+ const packageRelativeCandidates = [
1377
+ __rspack_external_path.join('dist', input.packageName, engine)
1378
+ ];
1379
+ const normalizedBaseDir = __rspack_external_path.normalize(input.baseDir);
1380
+ const parentName = __rspack_external_path.basename(__rspack_external_path.dirname(normalizedBaseDir));
1381
+ const baseName = __rspack_external_path.basename(normalizedBaseDir);
1382
+ if ('programs' === parentName && 'develop' === baseName) packageRelativeCandidates.push(__rspack_external_path.join('..', '..', 'extensions', input.packageName, 'dist', engine));
1383
+ for (const rel of packageRelativeCandidates){
1384
+ const candidate = __rspack_external_path.resolve(input.baseDir, rel);
1385
+ if (__rspack_external_fs.existsSync(candidate)) return candidate;
1386
+ }
1387
+ }
1388
+ const RESERVED_BUILT_IN_NAMES = new Set([
1389
+ 'extension-js-devtools',
1390
+ 'extension-js-theme'
1391
+ ]);
1392
+ function isReservedBuiltInPath(extensionPath) {
1393
+ const base = __rspack_external_path.basename(__rspack_external_path.normalize(extensionPath));
1394
+ if (RESERVED_BUILT_IN_NAMES.has(base)) return true;
1395
+ const segments = __rspack_external_path.normalize(extensionPath).split(__rspack_external_path.sep);
1396
+ return segments.some((segment)=>RESERVED_BUILT_IN_NAMES.has(segment));
1397
+ }
1398
+ function dedupeByResolvedPath(paths) {
1399
+ const seen = new Set();
1400
+ const result = [];
1401
+ for (const entry of paths){
1402
+ const resolved = __rspack_external_path.resolve(entry);
1403
+ if (!seen.has(resolved)) {
1404
+ seen.add(resolved);
1405
+ result.push(entry);
1406
+ }
1407
+ }
1408
+ return result;
1409
+ }
1410
+ function computeExtensionsToLoad(baseDir, mode, browser, userExtensionOutputPath, extraExtensionDirs = [], userManifestPath) {
1411
+ const list = [];
1412
+ try {
1413
+ const devtoolsForBrowser = resolveBuiltInExtensionForBrowser({
1414
+ baseDir,
1415
+ packageName: 'extension-js-devtools',
1416
+ browser
1417
+ });
1418
+ const themeForBrowser = resolveBuiltInExtensionForBrowser({
1419
+ baseDir,
1420
+ packageName: 'extension-js-theme',
1421
+ browser
1422
+ });
1423
+ const userHasNewTabOverride = hasNewTabOverride(userExtensionOutputPath) || ('string' == typeof userManifestPath ? hasNewTabOverride(__rspack_external_path.dirname(userManifestPath)) : false);
1424
+ const devtoolsHasNewTabOverride = devtoolsForBrowser ? hasNewTabOverride(devtoolsForBrowser) : false;
1425
+ const shouldSkipDevtoolsForNtpConflict = userHasNewTabOverride && devtoolsHasNewTabOverride;
1426
+ if (devtoolsForBrowser && !shouldSkipDevtoolsForNtpConflict) list.push(devtoolsForBrowser);
1427
+ if (themeForBrowser) list.push(themeForBrowser);
1428
+ } catch {}
1429
+ for (const p of extraExtensionDirs)if (!isReservedBuiltInPath(p)) list.push(p);
1430
+ list.push(userExtensionOutputPath);
1431
+ return dedupeByResolvedPath(list);
1432
+ }
1433
+ function getDarkModeDefaults(browser) {
1434
+ if ('chrome' === browser || 'edge' === browser || 'chromium' === browser || 'chromium-based' === browser) return {
1435
+ browserFlags: [
1436
+ '--force-dark-mode',
1437
+ '--enable-features=WebUIDarkMode'
1438
+ ],
1439
+ preferences: {}
1440
+ };
1441
+ if ('firefox' === browser || 'gecko-based' === browser || 'firefox-based' === browser) return {
1442
+ browserFlags: [],
1443
+ preferences: {
1444
+ 'ui.systemUsesDarkTheme': 1,
1445
+ 'layout.css.prefers-color-scheme.content-override': 2,
1446
+ 'devtools.theme': 'dark'
1447
+ }
1448
+ };
1449
+ return {
1450
+ browserFlags: [],
1451
+ preferences: {}
1452
+ };
1453
+ }
1454
+ function withDarkMode(config) {
1455
+ const defaults = getDarkModeDefaults(config.browser);
1456
+ const existingFlags = Array.isArray(config.browserFlags) ? [
1457
+ ...config.browserFlags
1458
+ ] : [];
1459
+ const nextFlags = [
1460
+ ...existingFlags
1461
+ ];
1462
+ for (const flag of defaults.browserFlags || [])if (!nextFlags.some((f)=>String(f).trim() === flag)) nextFlags.push(flag);
1463
+ const nextPreferences = {
1464
+ ...config.preferences || {},
1465
+ ...Object.fromEntries(Object.entries(defaults.preferences || {}).filter(([k])=>!(k in (config.preferences || {}))))
1466
+ };
1467
+ return {
1468
+ ...config,
1469
+ browserFlags: nextFlags,
1470
+ preferences: nextPreferences
1471
+ };
1472
+ }
1473
+ const cjsRequire = createRequire(import.meta.url);
1474
+ function messages_getLoggingPrefix(type) {
1475
+ const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
1476
+ if (isAuthor) {
1477
+ const base = 'error' === type ? 'ERROR Author says' : '⏵⏵⏵ Author says';
1478
+ return pintor.brightMagenta(base);
1479
+ }
1480
+ if ('error' === type) return pintor.red('ERROR');
1481
+ if ('warn' === type) return pintor.brightYellow('⏵⏵⏵');
1482
+ if ('info' === type) return pintor.gray('⏵⏵⏵');
1483
+ return pintor.green('⏵⏵⏵');
1484
+ }
1485
+ function messages_ready(mode, browser) {
1486
+ const key = String(browser || '').toLowerCase();
1487
+ const extensionOutput = 'firefox' === key || 'gecko-based' === key || 'firefox-based' === key || 'edge' === key ? 'Add-on' : 'Extension';
1488
+ const cap = 'firefox' === key || 'gecko-based' === key || 'firefox-based' === key ? 'Firefox' : String(browser || '').charAt(0).toUpperCase() + String(browser || '').slice(1);
1489
+ const pretty = pintor.green('ready for ' + mode);
1490
+ return `${messages_getLoggingPrefix('info')} ${cap} ${extensionOutput} ${pretty}.`;
1491
+ }
1492
+ function readJsonRecord(filePath) {
1493
+ try {
1494
+ return JSON.parse(__rspack_external_fs.readFileSync(filePath, 'utf8'));
1495
+ } catch {
1496
+ return null;
1497
+ }
1498
+ }
1499
+ function capitalizeToken(value) {
1500
+ return value.split('-').filter(Boolean).map((token)=>token.charAt(0).toUpperCase() + token.slice(1)).join('-');
1501
+ }
1502
+ function getExtensionVersion() {
1503
+ return process.env.EXTENSION_DEVELOP_VERSION || process.env.EXTENSION_CLI_VERSION || (()=>{
1504
+ try {
1505
+ return cjsRequire('../package.json').version;
1506
+ } catch {
1507
+ return 'unknown';
1508
+ }
1509
+ })();
1510
+ }
1511
+ function browserRunnerDisabled(args) {
1512
+ const manifest = readJsonRecord(args.manifestPath);
1513
+ const ready = readJsonRecord(args.readyPath);
1514
+ const browserLabel = capitalizeToken(String(args.browser || 'unknown'));
1515
+ const runId = String(ready?.runId || '').trim();
1516
+ const pid = Number.isInteger(ready?.pid) ? String(ready?.pid) : '';
1517
+ const runLabel = runId ? `${pintor.gray(runId)}${pid ? ` · ${pintor.gray(`PID ${pid}`)}` : ''}` : pid ? pintor.gray(`PID ${pid}`) : pintor.gray('n/a');
1518
+ const extensionName = String(manifest?.name || 'Extension');
1519
+ const extensionVersion = String(manifest?.version || '').trim();
1520
+ const extensionLabel = extensionVersion ? `${extensionName} ${extensionVersion}` : extensionName;
1521
+ const extensionJsVersion = getExtensionVersion();
1522
+ return [
1523
+ ` 🧩 ${pintor.brightBlue('Extension.js')} ${pintor.gray(extensionJsVersion)}`,
1524
+ ` Browser ${pintor.gray(args.browserModeLabel || `${browserLabel} (build-only mode)`)}`,
1525
+ ` Extension ${pintor.gray(extensionLabel)}`,
1526
+ ` Run ID ${runLabel}`
1527
+ ].join('\n');
1528
+ }
1529
+ function portInUse(requestedPort, newPort) {
1530
+ return `Port: Requested port ${pintor.brightBlue(requestedPort.toString())} is in use; using ${pintor.brightBlue(newPort.toString())} instead.`;
1531
+ }
1532
+ function extensionJsRunnerError(error) {
1533
+ return `Extension.js Runner Error:\n${pintor.red(String(error))}`;
1534
+ }
1535
+ function autoExitModeEnabled(ms) {
1536
+ return `Auto-exit enabled. Will exit after ${pintor.brightBlue(ms.toString())} ms if idle.`;
1537
+ }
1538
+ function autoExitTriggered(ms) {
1539
+ return `Auto-exit triggered after ${pintor.brightBlue(ms.toString())} ms. Cleaning up...`;
1540
+ }
1541
+ function autoExitForceKill(ms) {
1542
+ return `Force-killing process after ${pintor.brightBlue(ms.toString())} ms to ensure exit.`;
1543
+ }
1544
+ function devServerStartTimeout(ms) {
1545
+ return [
1546
+ `Dev server startup is taking longer than expected (${pintor.brightBlue(ms.toString())} ms).`,
1547
+ "The bundler may have encountered an error before emitting the first build.",
1548
+ `If nothing else prints, try setting ${pintor.brightBlue('EXTENSION_VERBOSE=1')} for more logs.`
1549
+ ].join('\n');
1550
+ }
1551
+ function bundlerFatalError(error) {
1552
+ const text = error instanceof Error ? error.stack || error.message : String(error);
1553
+ return `Build failed to start:\n${pintor.red(text)}`;
1554
+ }
1555
+ function bundlerRecompiling() {
1556
+ return "Recompiling due to file changes…";
1557
+ }
1558
+ function noEntrypointsDetected(port) {
1559
+ return [
1560
+ "No entrypoints or assets were produced by the initial compilation.",
1561
+ `The dev server is running on 127.0.0.1:${pintor.brightBlue(port.toString())}, but nothing is being built.`,
1562
+ "Possible causes:",
1563
+ " • Empty or missing entry configuration.",
1564
+ " • Extension-related plugins are disabled (entries not derived from manifest).",
1565
+ " • All sources are ignored or excluded.",
1566
+ `Try enabling verbose logs with ${pintor.brightBlue('EXTENSION_VERBOSE=1')} or review your extension config.`
1567
+ ].join('\n');
1568
+ }
1569
+ function spacerLine() {
1570
+ return ' ';
1571
+ }
1572
+ var command_preview_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
1573
+ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher) {
1574
+ const projectStructure = await getProjectStructure(pathOrRemoteUrl);
1575
+ const debug = 'true' === process.env.EXTENSION_AUTHOR_MODE;
1576
+ const { manifestDir, packageJsonDir } = getDirs(projectStructure);
1577
+ if (projectStructure.packageJsonPath) assertNoManagedDependencyConflicts(projectStructure.packageJsonPath, packageJsonDir);
1578
+ const browser = normalizeBrowser(previewOptions.browser || 'chrome', previewOptions.chromiumBinary, previewOptions.geckoBinary || previewOptions.firefoxBinary);
1579
+ const outputPath = computePreviewOutputPath(projectStructure, browser, previewOptions.outputPath);
1580
+ const distPath = getDistPath(packageJsonDir, browser);
1581
+ const metadataCommand = 'start' === previewOptions.metadataCommand ? 'start' : 'preview';
1582
+ const metadata = createPlaywrightMetadataWriter({
1583
+ packageJsonDir,
1584
+ browser: String(browser),
1585
+ command: metadataCommand,
1586
+ distPath,
1587
+ manifestPath: projectStructure.manifestPath,
1588
+ port: 'number' == typeof previewOptions.port ? previewOptions.port : 'string' == typeof previewOptions.port ? parseInt(previewOptions.port, 10) : null
1589
+ });
1590
+ metadata.writeStarting();
1591
+ if (debug) {
1592
+ console.log(debugDirs(manifestDir, packageJsonDir));
1593
+ console.log(debugBrowser(browser, previewOptions.chromiumBinary, previewOptions.geckoBinary || previewOptions.firefoxBinary));
1594
+ console.log(debugPreviewOutput(outputPath, distPath));
1595
+ }
1596
+ const manifestAtOutput = __rspack_external_path.join(outputPath, 'manifest.json');
1597
+ if (!__rspack_external_fs.existsSync(manifestAtOutput)) {
1598
+ metadata.writeError('preview_manifest_missing', `Expected manifest at ${manifestAtOutput}`);
1599
+ throw new Error(`Preview is run-only and does not compile.\nExpected an unpacked extension at:\n ${manifestAtOutput}\n\nRun \`extension build\` or \`extension dev\` first, or pass --output-path to an existing unpacked extension directory.`);
1600
+ }
1601
+ const commandConfig = await loadCommandConfig(packageJsonDir, metadataCommand);
1602
+ const browserConfig = await loadBrowserConfig(packageJsonDir, browser);
1603
+ console.log(previewing(browser));
1604
+ if (previewOptions.noBrowser) {
1605
+ console.log(previewSkippedNoBrowser(browser));
1606
+ metadata.writeReady();
1607
+ console.log(spacerLine());
1608
+ const browserLabel = String(browser || 'unknown');
1609
+ console.log(browserRunnerDisabled({
1610
+ browser: browserLabel,
1611
+ manifestPath: projectStructure.manifestPath,
1612
+ readyPath: metadata.readyPath,
1613
+ browserModeLabel: `${browserLabel.charAt(0).toUpperCase() + browserLabel.slice(1)} (no-browser mode)`
1614
+ }));
1615
+ return;
1616
+ }
1617
+ const safeBrowserConfig = sanitize(browserConfig);
1618
+ const safeCommandConfig = sanitize(commandConfig);
1619
+ const safePreviewOptions = sanitize(previewOptions);
1620
+ const specialFoldersData = getSpecialFoldersDataForProjectRoot(packageJsonDir);
1621
+ const mergedExtensionsConfig = safePreviewOptions.extensions ?? safeCommandConfig.extensions ?? safeBrowserConfig.extensions ?? specialFoldersData.extensions;
1622
+ const resolvedExtensionsConfig = await resolveCompanionExtensionsConfig({
1623
+ projectRoot: packageJsonDir,
1624
+ browser,
1625
+ config: mergedExtensionsConfig
1626
+ });
1627
+ const mergedGeckoBinary = safePreviewOptions.geckoBinary || safePreviewOptions.firefoxBinary || safeCommandConfig.geckoBinary || safeCommandConfig.firefoxBinary || safeBrowserConfig.geckoBinary || safeBrowserConfig.firefoxBinary;
1628
+ const mergedChromiumBinary = safePreviewOptions.chromiumBinary || safeCommandConfig.chromiumBinary || safeBrowserConfig.chromiumBinary;
1629
+ const merged = {
1630
+ ...safeBrowserConfig,
1631
+ ...safeCommandConfig,
1632
+ ...safePreviewOptions,
1633
+ extensions: resolvedExtensionsConfig,
1634
+ chromiumBinary: mergedChromiumBinary,
1635
+ geckoBinary: mergedGeckoBinary
1636
+ };
1637
+ const darkDefaults = withDarkMode({
1638
+ browser,
1639
+ browserFlags: merged.browserFlags,
1640
+ preferences: merged.preferences
1641
+ });
1642
+ const companionUnpackedExtensionDirs = resolveCompanionExtensionDirs({
1643
+ projectRoot: packageJsonDir,
1644
+ config: merged.extensions
1645
+ });
1646
+ const unpackedExtensionDirsToLoad = computeExtensionsToLoad(__rspack_external_path.resolve(command_preview_dirname, '..'), 'production', browser, outputPath, companionUnpackedExtensionDirs, projectStructure.manifestPath);
1647
+ const resolvedOpts = {
1648
+ browser,
1649
+ outPath: outputPath,
1650
+ contextDir: packageJsonDir,
1651
+ readyPath: metadata.readyPath,
1652
+ extensionsToLoad: unpackedExtensionDirsToLoad,
1653
+ noOpen: merged.noOpen,
1654
+ profile: merged.profile,
1655
+ persistProfile: merged.persistProfile,
1656
+ preferences: darkDefaults.preferences,
1657
+ browserFlags: darkDefaults.browserFlags,
1658
+ excludeBrowserFlags: merged.excludeBrowserFlags,
1659
+ startingUrl: merged.startingUrl,
1660
+ chromiumBinary: merged.chromiumBinary,
1661
+ geckoBinary: merged.geckoBinary,
1662
+ instanceId: merged.instanceId,
1663
+ port: merged.port,
1664
+ dryRun: merged.dryRun
1665
+ };
1666
+ if (!browserLauncher) throw new Error("extensionPreview requires a browserLauncher callback. The browser launch code has moved to programs/extension/browsers/.");
1667
+ await browserLauncher(resolvedOpts);
1668
+ metadata.writeReady();
1669
+ }
1670
+ export { PlaywrightPlugin, asAbsolute, assertNoManagedDependencyConflicts, authorInstallNotice, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserRunnerDisabled, buildCommandFailed, buildSuccess, buildSuccessWithWarnings, buildWarningsDetails, buildWebpack, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, debugBrowser, debugContextPath, debugDirs, debugExtensionsToLoad, debugOutputPath, devServerStartTimeout, downloadingText, extensionJsRunnerError, extensionPreview, failedToDownloadOrExtractZIPFileError, getDirs, getDistPath, getProjectStructure, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, invalidRemoteZip, loadBrowserConfig, loadCommandConfig, loadCustomConfig, messages_ready, needsInstall, noCompanionExtensionsResolved, noEntrypointsDetected, normalizeBrowser, package_namespaceObject, packagingDistributionFiles, packagingSourceFiles, portInUse, resolveCompanionExtensionsConfig, sanitize, spacerLine, treeWithDistFilesbrowser, treeWithSourceAndDistFiles, treeWithSourceFiles, unpackagedSuccessfully, unpackagingExtension, writingTypeDefinitions, writingTypeDefinitionsError };