extension-develop 3.17.0 → 3.18.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.
- package/dist/0~dev-server.mjs +660 -59
- package/dist/0~rspack-config.mjs +867 -881
- package/dist/0~zip.mjs +39 -10
- package/dist/45.mjs +39 -0
- package/dist/946.mjs +142 -36
- package/dist/962.mjs +299 -250
- package/dist/bridge.mjs +228 -0
- package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -2
- package/dist/extension-js-devtools/chrome/scripts/logger-client.js +1 -1
- package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -2
- package/dist/extension-js-devtools/chromium/scripts/logger-client.js +1 -1
- package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/edge/pages/welcome.js +2 -2
- package/dist/extension-js-devtools/edge/scripts/logger-client.js +1 -1
- package/dist/extension-js-devtools/extension-js/chrome/events.ndjson +2 -0
- package/dist/extension-js-devtools/extension-js/chrome/ready.json +16 -0
- package/dist/extension-js-devtools/extension-js/chromium/events.ndjson +2 -0
- package/dist/extension-js-devtools/extension-js/chromium/ready.json +16 -0
- package/dist/extension-js-devtools/extension-js/edge/events.ndjson +2 -0
- package/dist/extension-js-devtools/extension-js/edge/ready.json +16 -0
- package/dist/extension-js-devtools/extension-js/firefox/events.ndjson +2 -0
- package/dist/extension-js-devtools/extension-js/firefox/ready.json +16 -0
- package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
- package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
- package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -2
- package/dist/extension-js-devtools/firefox/scripts/logger-client.js +1 -1
- package/dist/extension-js-theme/extension-js/chrome/events.ndjson +2 -0
- package/dist/extension-js-theme/extension-js/chrome/ready.json +16 -0
- package/dist/extension-js-theme/extension-js/chromium/events.ndjson +2 -0
- package/dist/extension-js-theme/extension-js/chromium/ready.json +16 -0
- package/dist/extension-js-theme/extension-js/edge/events.ndjson +2 -0
- package/dist/extension-js-theme/extension-js/edge/ready.json +16 -0
- package/dist/extension-js-theme/extension-js/firefox/events.ndjson +4 -0
- package/dist/extension-js-theme/extension-js/firefox/ready.json +16 -0
- package/dist/feature-scripts-content-script-wrapper.js +19 -2
- package/dist/feature-scripts-content-script-wrapper.mjs +19 -2
- package/package.json +14 -5
- package/runtime/process-shim.cjs +49 -0
package/dist/962.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
2
|
import { createRequire } from "module";
|
|
3
3
|
import { execFileSync, spawn, spawnSync as external_child_process_spawnSync } from "child_process";
|
|
4
|
-
import { EventEmitter } from "node:events";
|
|
5
4
|
import pintor from "pintor";
|
|
5
|
+
import { EventEmitter } from "node:events";
|
|
6
6
|
import { package_namespaceObject, buildSuccessWithWarnings, buildWarningsDetails, loadCommandConfig, needsInstall, getDirs, buildCommandFailed, sanitize, writingTypeDefinitions, buildWebpack, assertNoManagedDependencyConflicts, debugDirs, debugBrowser, normalizeBrowser, debugOutputPath, loadCustomConfig, buildSuccess, writingTypeDefinitionsError, getDistPath, getProjectStructure, loadBrowserConfig, authorInstallNotice, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./946.mjs";
|
|
7
7
|
import { getCanonicalContentScriptEntryName } from "./526.mjs";
|
|
8
8
|
import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
|
|
@@ -426,112 +426,6 @@ async function ensureDevelopArtifacts() {
|
|
|
426
426
|
stdio
|
|
427
427
|
});
|
|
428
428
|
}
|
|
429
|
-
async function extensionBuild(pathOrRemoteUrl, buildOptions) {
|
|
430
|
-
const projectStructure = await getProjectStructure(pathOrRemoteUrl);
|
|
431
|
-
const isVitest = 'true' === process.env.VITEST;
|
|
432
|
-
const shouldExitOnError = (buildOptions?.exitOnError ?? true) && !isVitest;
|
|
433
|
-
const browser = normalizeBrowser(buildOptions?.browser || 'chrome', buildOptions?.chromiumBinary, buildOptions?.geckoBinary || buildOptions?.firefoxBinary);
|
|
434
|
-
const { manifestDir, packageJsonDir } = getDirs(projectStructure);
|
|
435
|
-
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
436
|
-
try {
|
|
437
|
-
await ensureDevelopArtifacts();
|
|
438
|
-
if (buildOptions?.install !== false) await ensureUserProjectDependencies(packageJsonDir);
|
|
439
|
-
const [{ rspack }, { merge }, { handleStatsErrors }, { default: webpackConfig }] = await Promise.all([
|
|
440
|
-
import("@rspack/core"),
|
|
441
|
-
import("webpack-merge"),
|
|
442
|
-
import("./0~stats-handler.mjs"),
|
|
443
|
-
import("./0~rspack-config.mjs").then((m)=>m.rspack_config_namespaceObject)
|
|
444
|
-
]);
|
|
445
|
-
const debug = isAuthor;
|
|
446
|
-
if (projectStructure.packageJsonPath) assertNoManagedDependencyConflicts(projectStructure.packageJsonPath, manifestDir);
|
|
447
|
-
const commandConfig = await loadCommandConfig(packageJsonDir, 'build');
|
|
448
|
-
const specialFoldersData = getSpecialFoldersDataForProjectRoot(packageJsonDir);
|
|
449
|
-
const distPath = getDistPath(packageJsonDir, browser);
|
|
450
|
-
try {
|
|
451
|
-
__rspack_external_fs.rmSync(distPath, {
|
|
452
|
-
recursive: true,
|
|
453
|
-
force: true
|
|
454
|
-
});
|
|
455
|
-
} catch {}
|
|
456
|
-
if (debug) {
|
|
457
|
-
console.log(debugDirs(manifestDir, packageJsonDir));
|
|
458
|
-
console.log(debugBrowser(browser, buildOptions?.chromiumBinary, buildOptions?.geckoBinary || buildOptions?.firefoxBinary));
|
|
459
|
-
console.log(debugOutputPath(distPath));
|
|
460
|
-
}
|
|
461
|
-
const mergedExtensionsConfig = buildOptions?.extensions ?? commandConfig.extensions ?? specialFoldersData.extensions;
|
|
462
|
-
const resolvedExtensionsConfig = await resolveCompanionExtensionsConfig({
|
|
463
|
-
projectRoot: packageJsonDir,
|
|
464
|
-
browser,
|
|
465
|
-
config: mergedExtensionsConfig
|
|
466
|
-
});
|
|
467
|
-
const resolvedMode = buildOptions?.mode === 'development' || buildOptions?.mode === 'none' || buildOptions?.mode === 'production' ? buildOptions.mode : 'production';
|
|
468
|
-
if ('development' === resolvedMode || 'production' === resolvedMode) process.env.NODE_ENV = resolvedMode;
|
|
469
|
-
const baseConfig = webpackConfig(projectStructure, {
|
|
470
|
-
...commandConfig,
|
|
471
|
-
...buildOptions,
|
|
472
|
-
extensions: resolvedExtensionsConfig,
|
|
473
|
-
browser,
|
|
474
|
-
mode: resolvedMode,
|
|
475
|
-
output: {
|
|
476
|
-
clean: true,
|
|
477
|
-
path: distPath
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
const allPluginsButBrowserRunners = baseConfig.plugins?.filter((plugin)=>plugin?.constructor.name !== 'plugin-browsers');
|
|
481
|
-
const userExtensionConfig = await loadCustomConfig(packageJsonDir);
|
|
482
|
-
const userConfig = userExtensionConfig({
|
|
483
|
-
...baseConfig,
|
|
484
|
-
plugins: allPluginsButBrowserRunners
|
|
485
|
-
});
|
|
486
|
-
const compilerConfig = merge(userConfig);
|
|
487
|
-
compilerConfig.stats = false;
|
|
488
|
-
const compiler = rspack(compilerConfig);
|
|
489
|
-
let summary = {
|
|
490
|
-
browser,
|
|
491
|
-
total_assets: 0,
|
|
492
|
-
total_bytes: 0,
|
|
493
|
-
largest_asset_bytes: 0,
|
|
494
|
-
warnings_count: 0,
|
|
495
|
-
errors_count: 0
|
|
496
|
-
};
|
|
497
|
-
await new Promise((resolve, reject)=>{
|
|
498
|
-
compiler.run(async (err, stats)=>{
|
|
499
|
-
if (err) {
|
|
500
|
-
console.error(err.stack || err);
|
|
501
|
-
return reject(err);
|
|
502
|
-
}
|
|
503
|
-
if (!stats || 'function' != typeof stats.hasErrors) return reject(new Error('Build failed: bundler returned invalid stats output (no reliable compilation result).'));
|
|
504
|
-
if (!buildOptions?.silent && stats) console.log(buildWebpack(manifestDir, stats, browser));
|
|
505
|
-
if (stats.hasErrors()) {
|
|
506
|
-
handleStatsErrors(stats);
|
|
507
|
-
if (!shouldExitOnError) return reject(new Error('Build failed with errors'));
|
|
508
|
-
process.exit(1);
|
|
509
|
-
} else {
|
|
510
|
-
const info = stats?.toJson({
|
|
511
|
-
all: false,
|
|
512
|
-
assets: true,
|
|
513
|
-
warnings: true,
|
|
514
|
-
errors: true
|
|
515
|
-
});
|
|
516
|
-
summary = getBuildSummary(browser, info);
|
|
517
|
-
if (summary.warnings_count > 0) {
|
|
518
|
-
console.log(buildSuccessWithWarnings(summary.warnings_count));
|
|
519
|
-
const warningDetails = buildWarningsDetails(info?.warnings || []);
|
|
520
|
-
if (warningDetails) console.log(`\n${warningDetails}`);
|
|
521
|
-
} else console.log(buildSuccess());
|
|
522
|
-
resolve();
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
return summary;
|
|
527
|
-
} catch (error) {
|
|
528
|
-
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
529
|
-
if (isAuthor) console.error(error);
|
|
530
|
-
else console.error(buildCommandFailed(error));
|
|
531
|
-
if (!shouldExitOnError) throw error;
|
|
532
|
-
process.exit(1);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
429
|
async function generateExtensionTypes(manifestDir, packageJsonDir) {
|
|
536
430
|
const extensionEnvFile = __rspack_external_path.join(packageJsonDir, 'extension-env.d.ts');
|
|
537
431
|
const typePath = 'extension';
|
|
@@ -562,131 +456,6 @@ async function generateExtensionTypes(manifestDir, packageJsonDir) {
|
|
|
562
456
|
}
|
|
563
457
|
}
|
|
564
458
|
}
|
|
565
|
-
class BuildEmitter extends EventEmitter {
|
|
566
|
-
constructor(){
|
|
567
|
-
super();
|
|
568
|
-
this.on('error', ()=>{});
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
class BrowsersPlugin {
|
|
572
|
-
options;
|
|
573
|
-
static name = 'plugin-browsers';
|
|
574
|
-
emitter = new BuildEmitter();
|
|
575
|
-
extensionsToLoad = [];
|
|
576
|
-
isFirstCompile = true;
|
|
577
|
-
controller;
|
|
578
|
-
constructor(options){
|
|
579
|
-
this.options = options;
|
|
580
|
-
}
|
|
581
|
-
apply(compiler) {
|
|
582
|
-
let pendingReloadReason;
|
|
583
|
-
let pendingChangedSources = [];
|
|
584
|
-
compiler.hooks.watchRun.tap(BrowsersPlugin.name, ()=>{
|
|
585
|
-
pendingReloadReason = void 0;
|
|
586
|
-
pendingChangedSources = [];
|
|
587
|
-
const modifiedFiles = compiler.modifiedFiles;
|
|
588
|
-
if (!modifiedFiles || 0 === modifiedFiles.size) return;
|
|
589
|
-
const contextDir = compiler.options.context || '';
|
|
590
|
-
for (const file of modifiedFiles){
|
|
591
|
-
const normalized = __rspack_external_path.relative(contextDir, file).replace(/\\/g, '/');
|
|
592
|
-
pendingChangedSources.push(normalized);
|
|
593
|
-
if (normalized.includes('manifest.json')) pendingReloadReason = 'full';
|
|
594
|
-
else if (normalized.includes('_locales/')) pendingReloadReason = 'full';
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
compiler.hooks.done.tapPromise(BrowsersPlugin.name, async (stats)=>{
|
|
598
|
-
const compilation = stats.compilation;
|
|
599
|
-
const hasErrors = compilation.errors && compilation.errors.length > 0;
|
|
600
|
-
if (hasErrors) return void this.emitter.emit('error', {
|
|
601
|
-
errors: compilation.errors.map((e)=>'string' == typeof e ? e : e.message || String(e))
|
|
602
|
-
});
|
|
603
|
-
const outputPath = String(compilation.options?.output?.path || '');
|
|
604
|
-
const contextDir = String(compilation.options?.context || '');
|
|
605
|
-
let reloadInstruction;
|
|
606
|
-
if (!this.isFirstCompile && pendingReloadReason) reloadInstruction = {
|
|
607
|
-
type: pendingReloadReason,
|
|
608
|
-
changedAssets: pendingChangedSources
|
|
609
|
-
};
|
|
610
|
-
else if (!this.isFirstCompile && pendingChangedSources.length > 0) {
|
|
611
|
-
const isServiceWorkerSource = (rel)=>/(^|\/)background(\.|\/)/i.test(rel) || /service[-_.]?worker/i.test(rel);
|
|
612
|
-
const hasServiceWorkerChange = pendingChangedSources.some(isServiceWorkerSource);
|
|
613
|
-
if (hasServiceWorkerChange) reloadInstruction = {
|
|
614
|
-
type: 'service-worker',
|
|
615
|
-
changedAssets: pendingChangedSources
|
|
616
|
-
};
|
|
617
|
-
else {
|
|
618
|
-
const contentScriptCount = readContentScriptCount(compilation, outputPath);
|
|
619
|
-
if (contentScriptCount > 0) {
|
|
620
|
-
const entries = [];
|
|
621
|
-
for(let i = 0; i < contentScriptCount; i++)entries.push(getCanonicalContentScriptEntryName(i));
|
|
622
|
-
reloadInstruction = {
|
|
623
|
-
type: "content-scripts",
|
|
624
|
-
changedContentScriptEntries: entries,
|
|
625
|
-
changedAssets: pendingChangedSources
|
|
626
|
-
};
|
|
627
|
-
} else reloadInstruction = void 0;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
const wasFirstCompile = this.isFirstCompile;
|
|
631
|
-
this.isFirstCompile = false;
|
|
632
|
-
if (wasFirstCompile) try {
|
|
633
|
-
this.controller = await this.options.launcher({
|
|
634
|
-
...this.options.browserOptions,
|
|
635
|
-
outputPath,
|
|
636
|
-
contextDir,
|
|
637
|
-
extensionsToLoad: this.extensionsToLoad
|
|
638
|
-
});
|
|
639
|
-
const logLevel = this.options.browserOptions.logLevel || 'off';
|
|
640
|
-
if ('off' !== logLevel && this.controller) await this.controller.enableUnifiedLogging({
|
|
641
|
-
level: logLevel,
|
|
642
|
-
contexts: this.options.browserOptions.logContexts,
|
|
643
|
-
format: this.options.browserOptions.logFormat,
|
|
644
|
-
timestamps: this.options.browserOptions.logTimestamps,
|
|
645
|
-
color: this.options.browserOptions.logColor,
|
|
646
|
-
urlFilter: this.options.browserOptions.logUrl,
|
|
647
|
-
tabFilter: this.options.browserOptions.logTab
|
|
648
|
-
});
|
|
649
|
-
} catch (error) {
|
|
650
|
-
this.emitter.emit('error', {
|
|
651
|
-
errors: [
|
|
652
|
-
error instanceof Error ? error.message : String(error)
|
|
653
|
-
]
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
else if (this.controller && reloadInstruction) {
|
|
657
|
-
if ('true' !== process.env.EXTENSION_NO_RELOAD) try {
|
|
658
|
-
await this.controller.reload(reloadInstruction);
|
|
659
|
-
} catch {}
|
|
660
|
-
}
|
|
661
|
-
this.emitter.emit('compiled', {
|
|
662
|
-
outputPath,
|
|
663
|
-
contextDir,
|
|
664
|
-
isFirstCompile: wasFirstCompile,
|
|
665
|
-
reloadInstruction,
|
|
666
|
-
extensionsToLoad: wasFirstCompile ? this.extensionsToLoad : void 0
|
|
667
|
-
});
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
function readContentScriptCount(compilation, outputPath) {
|
|
672
|
-
try {
|
|
673
|
-
const asset = compilation.getAsset?.('manifest.json');
|
|
674
|
-
if (asset?.source) {
|
|
675
|
-
const manifest = JSON.parse(String(asset.source.source()));
|
|
676
|
-
const list = manifest?.content_scripts;
|
|
677
|
-
if (Array.isArray(list)) return list.length;
|
|
678
|
-
}
|
|
679
|
-
} catch {}
|
|
680
|
-
try {
|
|
681
|
-
const manifestPath = __rspack_external_path.join(outputPath, 'manifest.json');
|
|
682
|
-
if (__rspack_external_fs.existsSync(manifestPath)) {
|
|
683
|
-
const manifest = JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf8'));
|
|
684
|
-
const list = manifest?.content_scripts;
|
|
685
|
-
if (Array.isArray(list)) return list.length;
|
|
686
|
-
}
|
|
687
|
-
} catch {}
|
|
688
|
-
return 0;
|
|
689
|
-
}
|
|
690
459
|
function isUsingIntegration(name) {
|
|
691
460
|
return `${pintor.gray('⏵⏵⏵')} Using ${pintor.brightBlue(name)}...`;
|
|
692
461
|
}
|
|
@@ -1245,26 +1014,30 @@ function hasTypeScriptSourceFiles(projectPath) {
|
|
|
1245
1014
|
return false;
|
|
1246
1015
|
}
|
|
1247
1016
|
}
|
|
1248
|
-
function
|
|
1017
|
+
function hasTypeScriptDependency(projectPath) {
|
|
1249
1018
|
const packageJsonDirectory = findNearestPackageJsonDirectory(projectPath);
|
|
1019
|
+
if (!packageJsonDirectory) return false;
|
|
1020
|
+
const packageJson = parseJsonSafe(__rspack_external_fs.readFileSync(__rspack_external_path.join(packageJsonDirectory, 'package.json'), 'utf8'));
|
|
1021
|
+
return !!(packageJson?.devDependencies?.typescript || packageJson?.dependencies?.typescript);
|
|
1022
|
+
}
|
|
1023
|
+
function isUsingTypeScript(projectPath) {
|
|
1024
|
+
const tsConfigFilePath = getUserTypeScriptConfigFile(projectPath);
|
|
1025
|
+
if (!tsConfigFilePath) return false;
|
|
1026
|
+
return hasTypeScriptDependency(projectPath) || hasTypeScriptSourceFiles(projectPath);
|
|
1027
|
+
}
|
|
1028
|
+
function ensureTypeScriptConfig(projectPath) {
|
|
1029
|
+
if (hasShownUserMessage) return;
|
|
1250
1030
|
const tsConfigFilePath = getUserTypeScriptConfigFile(projectPath);
|
|
1251
|
-
const
|
|
1252
|
-
const TypeScriptAsDevDep = packageJson?.devDependencies?.typescript;
|
|
1253
|
-
const TypeScriptAsDep = packageJson?.dependencies?.typescript;
|
|
1031
|
+
const hasDep = hasTypeScriptDependency(projectPath);
|
|
1254
1032
|
const hasTsFiles = hasTypeScriptSourceFiles(projectPath);
|
|
1255
|
-
if (
|
|
1256
|
-
if (
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
} else {
|
|
1262
|
-
console.log(creatingTSConfig());
|
|
1263
|
-
writeTsConfig(projectPath);
|
|
1264
|
-
}
|
|
1265
|
-
hasShownUserMessage = true;
|
|
1033
|
+
if (hasDep || hasTsFiles) if (tsConfigFilePath) {
|
|
1034
|
+
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('TypeScript')}`);
|
|
1035
|
+
} else if (hasTsFiles) throw new Error('[Extension.js] Missing tsconfig.json next to package.json. Create one to use TypeScript.');
|
|
1036
|
+
else {
|
|
1037
|
+
console.log(creatingTSConfig());
|
|
1038
|
+
writeTsConfig(projectPath);
|
|
1266
1039
|
}
|
|
1267
|
-
|
|
1040
|
+
hasShownUserMessage = true;
|
|
1268
1041
|
}
|
|
1269
1042
|
function defaultTypeScriptConfig(projectPath, _opts) {
|
|
1270
1043
|
return {
|
|
@@ -1305,6 +1078,278 @@ function writeTsConfig(projectPath) {
|
|
|
1305
1078
|
mode: 'development'
|
|
1306
1079
|
}), null, 2));
|
|
1307
1080
|
}
|
|
1081
|
+
async function extensionBuild(pathOrRemoteUrl, buildOptions) {
|
|
1082
|
+
const projectStructure = await getProjectStructure(pathOrRemoteUrl);
|
|
1083
|
+
const isVitest = 'true' === process.env.VITEST;
|
|
1084
|
+
const shouldExitOnError = (buildOptions?.exitOnError ?? true) && !isVitest;
|
|
1085
|
+
const browser = normalizeBrowser(buildOptions?.browser || 'chrome', buildOptions?.chromiumBinary, buildOptions?.geckoBinary || buildOptions?.firefoxBinary);
|
|
1086
|
+
const { manifestDir, packageJsonDir } = getDirs(projectStructure);
|
|
1087
|
+
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
1088
|
+
try {
|
|
1089
|
+
await ensureDevelopArtifacts();
|
|
1090
|
+
if (buildOptions?.install !== false) await ensureUserProjectDependencies(packageJsonDir);
|
|
1091
|
+
ensureTypeScriptConfig(manifestDir);
|
|
1092
|
+
if (isUsingTypeScript(manifestDir)) await generateExtensionTypes(manifestDir, packageJsonDir);
|
|
1093
|
+
const [{ rspack }, { merge }, { handleStatsErrors }, { default: webpackConfig }] = await Promise.all([
|
|
1094
|
+
import("@rspack/core"),
|
|
1095
|
+
import("webpack-merge"),
|
|
1096
|
+
import("./0~stats-handler.mjs"),
|
|
1097
|
+
import("./0~rspack-config.mjs").then((m)=>m.rspack_config_namespaceObject)
|
|
1098
|
+
]);
|
|
1099
|
+
const debug = isAuthor;
|
|
1100
|
+
if (projectStructure.packageJsonPath) assertNoManagedDependencyConflicts(projectStructure.packageJsonPath, manifestDir);
|
|
1101
|
+
const commandConfig = await loadCommandConfig(packageJsonDir, 'build');
|
|
1102
|
+
const specialFoldersData = getSpecialFoldersDataForProjectRoot(packageJsonDir);
|
|
1103
|
+
const distPath = getDistPath(packageJsonDir, browser);
|
|
1104
|
+
try {
|
|
1105
|
+
__rspack_external_fs.rmSync(distPath, {
|
|
1106
|
+
recursive: true,
|
|
1107
|
+
force: true
|
|
1108
|
+
});
|
|
1109
|
+
} catch {}
|
|
1110
|
+
if (debug) {
|
|
1111
|
+
console.log(debugDirs(manifestDir, packageJsonDir));
|
|
1112
|
+
console.log(debugBrowser(browser, buildOptions?.chromiumBinary, buildOptions?.geckoBinary || buildOptions?.firefoxBinary));
|
|
1113
|
+
console.log(debugOutputPath(distPath));
|
|
1114
|
+
}
|
|
1115
|
+
const mergedExtensionsConfig = buildOptions?.extensions ?? commandConfig.extensions ?? specialFoldersData.extensions;
|
|
1116
|
+
const resolvedExtensionsConfig = await resolveCompanionExtensionsConfig({
|
|
1117
|
+
projectRoot: packageJsonDir,
|
|
1118
|
+
browser,
|
|
1119
|
+
config: mergedExtensionsConfig
|
|
1120
|
+
});
|
|
1121
|
+
const resolvedMode = buildOptions?.mode === 'development' || buildOptions?.mode === 'none' || buildOptions?.mode === 'production' ? buildOptions.mode : 'production';
|
|
1122
|
+
if ('development' === resolvedMode || 'production' === resolvedMode) process.env.NODE_ENV = resolvedMode;
|
|
1123
|
+
const baseConfig = webpackConfig(projectStructure, {
|
|
1124
|
+
...commandConfig,
|
|
1125
|
+
...buildOptions,
|
|
1126
|
+
extensions: resolvedExtensionsConfig,
|
|
1127
|
+
browser,
|
|
1128
|
+
mode: resolvedMode,
|
|
1129
|
+
output: {
|
|
1130
|
+
clean: true,
|
|
1131
|
+
path: distPath
|
|
1132
|
+
}
|
|
1133
|
+
});
|
|
1134
|
+
const allPluginsButBrowserRunners = baseConfig.plugins?.filter((plugin)=>plugin?.constructor.name !== 'plugin-browsers');
|
|
1135
|
+
const userExtensionConfig = await loadCustomConfig(packageJsonDir);
|
|
1136
|
+
const userConfig = userExtensionConfig({
|
|
1137
|
+
...baseConfig,
|
|
1138
|
+
plugins: allPluginsButBrowserRunners
|
|
1139
|
+
});
|
|
1140
|
+
const compilerConfig = merge(userConfig);
|
|
1141
|
+
compilerConfig.stats = false;
|
|
1142
|
+
const compiler = rspack(compilerConfig);
|
|
1143
|
+
let summary = {
|
|
1144
|
+
browser,
|
|
1145
|
+
total_assets: 0,
|
|
1146
|
+
total_bytes: 0,
|
|
1147
|
+
largest_asset_bytes: 0,
|
|
1148
|
+
warnings_count: 0,
|
|
1149
|
+
errors_count: 0
|
|
1150
|
+
};
|
|
1151
|
+
await new Promise((resolve, reject)=>{
|
|
1152
|
+
compiler.run(async (err, stats)=>{
|
|
1153
|
+
if (err) {
|
|
1154
|
+
console.error(err.stack || err);
|
|
1155
|
+
return reject(err);
|
|
1156
|
+
}
|
|
1157
|
+
if (!stats || 'function' != typeof stats.hasErrors) return reject(new Error('Build failed: bundler returned invalid stats output (no reliable compilation result).'));
|
|
1158
|
+
if (!buildOptions?.silent && stats) console.log(buildWebpack(manifestDir, stats, browser));
|
|
1159
|
+
if (stats.hasErrors()) {
|
|
1160
|
+
handleStatsErrors(stats);
|
|
1161
|
+
if (!shouldExitOnError) return reject(new Error('Build failed with errors'));
|
|
1162
|
+
process.exit(1);
|
|
1163
|
+
} else {
|
|
1164
|
+
const info = stats?.toJson({
|
|
1165
|
+
all: false,
|
|
1166
|
+
assets: true,
|
|
1167
|
+
warnings: true,
|
|
1168
|
+
errors: true
|
|
1169
|
+
});
|
|
1170
|
+
summary = getBuildSummary(browser, info);
|
|
1171
|
+
if (summary.warnings_count > 0) {
|
|
1172
|
+
console.log(buildSuccessWithWarnings(summary.warnings_count));
|
|
1173
|
+
const warningDetails = buildWarningsDetails(info?.warnings || []);
|
|
1174
|
+
if (warningDetails) console.log(`\n${warningDetails}`);
|
|
1175
|
+
} else console.log(buildSuccess());
|
|
1176
|
+
resolve();
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
});
|
|
1180
|
+
if (('safari' === browser || 'webkit-based' === browser) && buildOptions?.safariPackager) await buildOptions.safariPackager(distPath, 'full');
|
|
1181
|
+
return summary;
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
1184
|
+
if (isAuthor) console.error(error);
|
|
1185
|
+
else console.error(buildCommandFailed(error));
|
|
1186
|
+
if (!shouldExitOnError) throw error;
|
|
1187
|
+
process.exit(1);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
class BuildEmitter extends EventEmitter {
|
|
1191
|
+
constructor(){
|
|
1192
|
+
super();
|
|
1193
|
+
this.on('error', ()=>{});
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
class BrowsersPlugin {
|
|
1197
|
+
options;
|
|
1198
|
+
static name = 'plugin-browsers';
|
|
1199
|
+
emitter = new BuildEmitter();
|
|
1200
|
+
extensionsToLoad = [];
|
|
1201
|
+
isFirstCompile = true;
|
|
1202
|
+
controller;
|
|
1203
|
+
constructor(options){
|
|
1204
|
+
this.options = options;
|
|
1205
|
+
}
|
|
1206
|
+
apply(compiler) {
|
|
1207
|
+
let pendingReloadReason;
|
|
1208
|
+
let pendingChangedSources = [];
|
|
1209
|
+
compiler.hooks.watchRun.tap(BrowsersPlugin.name, ()=>{
|
|
1210
|
+
pendingReloadReason = void 0;
|
|
1211
|
+
pendingChangedSources = [];
|
|
1212
|
+
const modifiedFiles = compiler.modifiedFiles;
|
|
1213
|
+
if (!modifiedFiles || 0 === modifiedFiles.size) return;
|
|
1214
|
+
const contextDir = compiler.options.context || '';
|
|
1215
|
+
for (const file of modifiedFiles){
|
|
1216
|
+
const normalized = __rspack_external_path.relative(contextDir, file).replace(/\\/g, '/');
|
|
1217
|
+
pendingChangedSources.push(normalized);
|
|
1218
|
+
if (normalized.includes('manifest.json')) pendingReloadReason = 'full';
|
|
1219
|
+
else if (normalized.includes('_locales/')) pendingReloadReason = 'full';
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
compiler.hooks.done.tapPromise(BrowsersPlugin.name, async (stats)=>{
|
|
1223
|
+
const compilation = stats.compilation;
|
|
1224
|
+
const hasErrors = compilation.errors && compilation.errors.length > 0;
|
|
1225
|
+
if (hasErrors) return void this.emitter.emit('error', {
|
|
1226
|
+
errors: compilation.errors.map((e)=>'string' == typeof e ? e : e.message || String(e))
|
|
1227
|
+
});
|
|
1228
|
+
const outputPath = String(compilation.options?.output?.path || '');
|
|
1229
|
+
const contextDir = String(compilation.options?.context || '');
|
|
1230
|
+
let reloadInstruction;
|
|
1231
|
+
if (!this.isFirstCompile && pendingReloadReason) reloadInstruction = {
|
|
1232
|
+
type: pendingReloadReason,
|
|
1233
|
+
changedAssets: pendingChangedSources
|
|
1234
|
+
};
|
|
1235
|
+
else if (!this.isFirstCompile && pendingChangedSources.length > 0) {
|
|
1236
|
+
const isServiceWorkerSource = (rel)=>/(^|\/)background(\.|\/)/i.test(rel) || /service[-_.]?worker/i.test(rel);
|
|
1237
|
+
const hasServiceWorkerChange = pendingChangedSources.some(isServiceWorkerSource);
|
|
1238
|
+
if (hasServiceWorkerChange) reloadInstruction = {
|
|
1239
|
+
type: 'service-worker',
|
|
1240
|
+
changedAssets: pendingChangedSources
|
|
1241
|
+
};
|
|
1242
|
+
else {
|
|
1243
|
+
const contentScriptCount = readContentScriptCount(compilation, outputPath);
|
|
1244
|
+
if (contentScriptCount > 0) {
|
|
1245
|
+
const entries = [];
|
|
1246
|
+
for(let i = 0; i < contentScriptCount; i++)entries.push(getCanonicalContentScriptEntryName(i));
|
|
1247
|
+
reloadInstruction = {
|
|
1248
|
+
type: "content-scripts",
|
|
1249
|
+
changedContentScriptEntries: entries,
|
|
1250
|
+
changedAssets: pendingChangedSources
|
|
1251
|
+
};
|
|
1252
|
+
} else reloadInstruction = void 0;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
const wasFirstCompile = this.isFirstCompile;
|
|
1256
|
+
this.isFirstCompile = false;
|
|
1257
|
+
if (wasFirstCompile) try {
|
|
1258
|
+
this.controller = await this.options.launcher({
|
|
1259
|
+
...this.options.browserOptions,
|
|
1260
|
+
outputPath,
|
|
1261
|
+
contextDir,
|
|
1262
|
+
extensionsToLoad: this.extensionsToLoad
|
|
1263
|
+
});
|
|
1264
|
+
const logLevel = this.options.browserOptions.logLevel || 'off';
|
|
1265
|
+
if ('off' !== logLevel && this.controller) await this.controller.enableUnifiedLogging({
|
|
1266
|
+
level: logLevel,
|
|
1267
|
+
contexts: this.options.browserOptions.logContexts,
|
|
1268
|
+
format: this.options.browserOptions.logFormat,
|
|
1269
|
+
timestamps: this.options.browserOptions.logTimestamps,
|
|
1270
|
+
color: this.options.browserOptions.logColor,
|
|
1271
|
+
urlFilter: this.options.browserOptions.logUrl,
|
|
1272
|
+
tabFilter: this.options.browserOptions.logTab
|
|
1273
|
+
});
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
this.emitter.emit('error', {
|
|
1276
|
+
errors: [
|
|
1277
|
+
error instanceof Error ? error.message : String(error)
|
|
1278
|
+
]
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
else if (this.controller && reloadInstruction) {
|
|
1282
|
+
if ('true' !== process.env.EXTENSION_NO_RELOAD) try {
|
|
1283
|
+
await this.controller.reload(reloadInstruction);
|
|
1284
|
+
} catch {}
|
|
1285
|
+
}
|
|
1286
|
+
this.emitter.emit('compiled', {
|
|
1287
|
+
outputPath,
|
|
1288
|
+
contextDir,
|
|
1289
|
+
isFirstCompile: wasFirstCompile,
|
|
1290
|
+
reloadInstruction,
|
|
1291
|
+
extensionsToLoad: wasFirstCompile ? this.extensionsToLoad : void 0
|
|
1292
|
+
});
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
function readContentScriptCount(compilation, outputPath) {
|
|
1297
|
+
try {
|
|
1298
|
+
const asset = compilation.getAsset?.('manifest.json');
|
|
1299
|
+
if (asset?.source) {
|
|
1300
|
+
const manifest = JSON.parse(String(asset.source.source()));
|
|
1301
|
+
const list = manifest?.content_scripts;
|
|
1302
|
+
if (Array.isArray(list)) return list.length;
|
|
1303
|
+
}
|
|
1304
|
+
} catch {}
|
|
1305
|
+
try {
|
|
1306
|
+
const manifestPath = __rspack_external_path.join(outputPath, 'manifest.json');
|
|
1307
|
+
if (__rspack_external_fs.existsSync(manifestPath)) {
|
|
1308
|
+
const manifest = JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf8'));
|
|
1309
|
+
const list = manifest?.content_scripts;
|
|
1310
|
+
if (Array.isArray(list)) return list.length;
|
|
1311
|
+
}
|
|
1312
|
+
} catch {}
|
|
1313
|
+
return 0;
|
|
1314
|
+
}
|
|
1315
|
+
class SafariDevPlugin {
|
|
1316
|
+
packager;
|
|
1317
|
+
static name = 'safari-dev';
|
|
1318
|
+
emitter = new BuildEmitter();
|
|
1319
|
+
extensionsToLoad = [];
|
|
1320
|
+
firstRun = true;
|
|
1321
|
+
constructor(packager){
|
|
1322
|
+
this.packager = packager;
|
|
1323
|
+
}
|
|
1324
|
+
apply(compiler) {
|
|
1325
|
+
compiler.hooks.done.tapPromise(SafariDevPlugin.name, async (stats)=>{
|
|
1326
|
+
const compilation = stats.compilation;
|
|
1327
|
+
const hasErrors = compilation.errors && compilation.errors.length > 0;
|
|
1328
|
+
if (hasErrors) return void this.emitter.emit('error', {
|
|
1329
|
+
errors: compilation.errors.map((e)=>'string' == typeof e ? e : e.message || String(e))
|
|
1330
|
+
});
|
|
1331
|
+
const outputPath = String(compilation.options?.output?.path || '');
|
|
1332
|
+
const contextDir = String(compilation.options?.context || '');
|
|
1333
|
+
const wasFirstRun = this.firstRun;
|
|
1334
|
+
try {
|
|
1335
|
+
await this.packager(outputPath, wasFirstRun ? 'full' : 'resync');
|
|
1336
|
+
} catch (error) {
|
|
1337
|
+
this.emitter.emit('error', {
|
|
1338
|
+
errors: [
|
|
1339
|
+
error instanceof Error ? error.message : String(error)
|
|
1340
|
+
]
|
|
1341
|
+
});
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
this.firstRun = false;
|
|
1345
|
+
this.emitter.emit('compiled', {
|
|
1346
|
+
outputPath,
|
|
1347
|
+
contextDir,
|
|
1348
|
+
isFirstCompile: wasFirstRun
|
|
1349
|
+
});
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1308
1353
|
async function extensionDev(pathOrRemoteUrl, devOptions) {
|
|
1309
1354
|
let browsersPlugin;
|
|
1310
1355
|
let emitter = new BuildEmitter();
|
|
@@ -1315,6 +1360,7 @@ async function extensionDev(pathOrRemoteUrl, devOptions) {
|
|
|
1315
1360
|
const { manifestDir, packageJsonDir } = getDirs(projectStructure);
|
|
1316
1361
|
await ensureDevelopArtifacts();
|
|
1317
1362
|
if (false !== devOptions.install) await ensureUserProjectDependencies(packageJsonDir);
|
|
1363
|
+
ensureTypeScriptConfig(manifestDir);
|
|
1318
1364
|
if (isUsingTypeScript(manifestDir)) await generateExtensionTypes(manifestDir, packageJsonDir);
|
|
1319
1365
|
if (projectStructure.packageJsonPath) assertNoManagedDependencyConflicts(projectStructure.packageJsonPath, manifestDir);
|
|
1320
1366
|
const browser = normalizeBrowser(devOptions.browser || 'chrome', devOptions.chromiumBinary, devOptions.geckoBinary || devOptions.firefoxBinary);
|
|
@@ -1330,7 +1376,10 @@ async function extensionDev(pathOrRemoteUrl, devOptions) {
|
|
|
1330
1376
|
...sanitize(commandConfig),
|
|
1331
1377
|
...sanitize(devOptions)
|
|
1332
1378
|
};
|
|
1333
|
-
if (devOptions.
|
|
1379
|
+
if (('safari' === browser || 'webkit-based' === browser) && !devOptions.noBrowser && devOptions.safariPackager) {
|
|
1380
|
+
browsersPlugin = new SafariDevPlugin(devOptions.safariPackager);
|
|
1381
|
+
emitter = browsersPlugin.emitter;
|
|
1382
|
+
} else if (devOptions.launcher && !devOptions.noBrowser) {
|
|
1334
1383
|
browsersPlugin = new BrowsersPlugin({
|
|
1335
1384
|
launcher: devOptions.launcher,
|
|
1336
1385
|
browserOptions: {
|
|
@@ -1386,4 +1435,4 @@ async function extensionDev(pathOrRemoteUrl, devOptions) {
|
|
|
1386
1435
|
process.exit(1);
|
|
1387
1436
|
}
|
|
1388
1437
|
}
|
|
1389
|
-
export { BuildEmitter, ensureOptionalContractModuleLoaded, extensionBuild, extensionDev, getUserTypeScriptConfigFile, hasDependency, isUsingCustomLoader, isUsingIntegration, isUsingTypeScript, jsFrameworksConfigsDetected, jsFrameworksHmrSummary, jsFrameworksIntegrationsEnabled, loadOptionalContractModuleWithoutInstall, optional_deps_resolver_ensureOptionalContractPackageResolved, parseJsonSafe, resolveDevelopDistFile, resolveDevelopInstallRoot, resolveOptionalContractPackageWithoutInstall, resolveOptionalDependencySync };
|
|
1438
|
+
export { BuildEmitter, ensureOptionalContractModuleLoaded, ensureTypeScriptConfig, extensionBuild, extensionDev, getUserTypeScriptConfigFile, hasDependency, isUsingCustomLoader, isUsingIntegration, isUsingTypeScript, jsFrameworksConfigsDetected, jsFrameworksHmrSummary, jsFrameworksIntegrationsEnabled, loadOptionalContractModuleWithoutInstall, optional_deps_resolver_ensureOptionalContractPackageResolved, parseJsonSafe, resolveDevelopDistFile, resolveDevelopInstallRoot, resolveOptionalContractPackageWithoutInstall, resolveOptionalDependencySync };
|