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.
Files changed (43) hide show
  1. package/dist/0~dev-server.mjs +660 -59
  2. package/dist/0~rspack-config.mjs +867 -881
  3. package/dist/0~zip.mjs +39 -10
  4. package/dist/45.mjs +39 -0
  5. package/dist/946.mjs +142 -36
  6. package/dist/962.mjs +299 -250
  7. package/dist/bridge.mjs +228 -0
  8. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  9. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
  10. package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -2
  11. package/dist/extension-js-devtools/chrome/scripts/logger-client.js +1 -1
  12. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  13. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
  14. package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -2
  15. package/dist/extension-js-devtools/chromium/scripts/logger-client.js +1 -1
  16. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  17. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
  18. package/dist/extension-js-devtools/edge/pages/welcome.js +2 -2
  19. package/dist/extension-js-devtools/edge/scripts/logger-client.js +1 -1
  20. package/dist/extension-js-devtools/extension-js/chrome/events.ndjson +2 -0
  21. package/dist/extension-js-devtools/extension-js/chrome/ready.json +16 -0
  22. package/dist/extension-js-devtools/extension-js/chromium/events.ndjson +2 -0
  23. package/dist/extension-js-devtools/extension-js/chromium/ready.json +16 -0
  24. package/dist/extension-js-devtools/extension-js/edge/events.ndjson +2 -0
  25. package/dist/extension-js-devtools/extension-js/edge/ready.json +16 -0
  26. package/dist/extension-js-devtools/extension-js/firefox/events.ndjson +2 -0
  27. package/dist/extension-js-devtools/extension-js/firefox/ready.json +16 -0
  28. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  29. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
  30. package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -2
  31. package/dist/extension-js-devtools/firefox/scripts/logger-client.js +1 -1
  32. package/dist/extension-js-theme/extension-js/chrome/events.ndjson +2 -0
  33. package/dist/extension-js-theme/extension-js/chrome/ready.json +16 -0
  34. package/dist/extension-js-theme/extension-js/chromium/events.ndjson +2 -0
  35. package/dist/extension-js-theme/extension-js/chromium/ready.json +16 -0
  36. package/dist/extension-js-theme/extension-js/edge/events.ndjson +2 -0
  37. package/dist/extension-js-theme/extension-js/edge/ready.json +16 -0
  38. package/dist/extension-js-theme/extension-js/firefox/events.ndjson +4 -0
  39. package/dist/extension-js-theme/extension-js/firefox/ready.json +16 -0
  40. package/dist/feature-scripts-content-script-wrapper.js +19 -2
  41. package/dist/feature-scripts-content-script-wrapper.mjs +19 -2
  42. package/package.json +14 -5
  43. 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 isUsingTypeScript(projectPath) {
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 packageJson = packageJsonDirectory ? parseJsonSafe(__rspack_external_fs.readFileSync(__rspack_external_path.join(packageJsonDirectory, 'package.json'), 'utf8')) : void 0;
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 (!hasShownUserMessage) {
1256
- if (TypeScriptAsDevDep || TypeScriptAsDep || hasTsFiles) if (tsConfigFilePath) {
1257
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('TypeScript')}`);
1258
- } else if (hasTsFiles) {
1259
- const errorMessage = '[Extension.js] Missing tsconfig.json next to package.json. Create one to use TypeScript.';
1260
- throw new Error(errorMessage);
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
- return !!tsConfigFilePath && !!(TypeScriptAsDevDep || TypeScriptAsDep || hasTsFiles);
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.launcher && !devOptions.noBrowser) {
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 };