extension 4.0.32 → 4.0.34

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/cli.cjs CHANGED
@@ -169,7 +169,9 @@ var __webpack_modules__ = {
169
169
  async function printProdBannerOnce(opts) {
170
170
  const k = keyFor(opts.browser, opts.outPath);
171
171
  if (printedKeys.has(k) || (0, _helpers_messaging__rspack_import_3.VR)(baseKeyFor(opts.browser, opts.outPath))) return true;
172
- const browserLabel = (0, _helpers_messaging__rspack_import_3.A6)(String(opts.browser || 'unknown'), _messages__rspack_import_5.GK(String(opts.browser || ''), opts.browserVersionLine));
172
+ const browserLabel = (0, _helpers_messaging__rspack_import_3.A6)(String(opts.browser || 'unknown'), _messages__rspack_import_5.GK(String(opts.browser || ''), opts.browserVersionLine, {
173
+ pinned: 'pinned' === opts.binaryProvenance
174
+ }));
173
175
  try {
174
176
  const manifestPath = node_path__rspack_import_2.join(opts.outPath, 'manifest.json');
175
177
  const manifest = JSON.parse(node_fs__rspack_import_1.readFileSync(manifestPath, 'utf-8'));
@@ -454,9 +456,10 @@ var __webpack_modules__ = {
454
456
  function capitalizedBrowserName(browser) {
455
457
  return `${browser.charAt(0).toUpperCase() + browser.slice(1)}`;
456
458
  }
457
- function resolveBrowserVersionLine(browser, pinnedLine) {
459
+ function resolveBrowserVersionLine(browser, pinnedLine, opts) {
458
460
  const pinned = String(pinnedLine || '').trim();
459
461
  if (pinned) return pinned;
462
+ if (opts?.pinned) return '';
460
463
  try {
461
464
  if ('chromium' === browser || 'chromium-based' === browser) {
462
465
  const p = chromium_location__rspack_import_5_default()();
@@ -817,7 +820,9 @@ var __webpack_modules__ = {
817
820
  return 'unknown';
818
821
  }
819
822
  })();
820
- const baseBrowserLabel = (0, _helpers_messaging__rspack_import_9.A6)(String(browser || 'unknown'), resolveBrowserVersionLine(browser, browserVersionLine));
823
+ const baseBrowserLabel = (0, _helpers_messaging__rspack_import_9.A6)(String(browser || 'unknown'), resolveBrowserVersionLine(browser, browserVersionLine, {
824
+ pinned: opts?.binaryProvenance === 'pinned'
825
+ }));
821
826
  const provenanceNote = binaryProvenanceNote(opts?.binaryProvenance);
822
827
  const browserLabel = provenanceNote ? `${baseBrowserLabel} ${provenanceNote}` : baseBrowserLabel;
823
828
  const binaryRowValue = provenanceNote ? collapseHomeDirInCardValue(String(opts?.binaryPath || '').trim()) : '';
@@ -1083,24 +1088,57 @@ var __webpack_modules__ = {
1083
1088
  if (node_fs__rspack_import_0.existsSync(chromeNested)) scanRoots.push(chromeNested);
1084
1089
  }
1085
1090
  const versionDirPattern = /^(mac|mac_arm|win32|win64|linux)/i;
1086
- const candidateFiles = [];
1091
+ const versionDirs = [];
1087
1092
  for (const root of scanRoots)try {
1088
1093
  const entries = node_fs__rspack_import_0.readdirSync(root, {
1089
1094
  withFileTypes: true
1090
1095
  });
1091
- const versionDirs = entries.filter((entry)=>entry.isDirectory() && versionDirPattern.test(entry.name)).map((entry)=>node_path__rspack_import_1.join(root, entry.name));
1092
- for (const dir of versionDirs)candidateFiles.push(...buildCandidates(dir, browser));
1093
- } catch {}
1094
- for (const candidate of candidateFiles)try {
1095
- if (candidate && node_fs__rspack_import_0.existsSync(candidate)) return candidate;
1096
+ for (const entry of entries)if (entry.isDirectory() && versionDirPattern.test(entry.name)) versionDirs.push(node_path__rspack_import_1.join(root, entry.name));
1096
1097
  } catch {}
1098
+ versionDirs.sort(compareManagedBuildDirsNewestFirst);
1097
1099
  const names = executableNamesFor(browser);
1100
+ for (const dir of versionDirs){
1101
+ for (const candidate of buildCandidates(dir, browser))if (isUsableBinaryPath(candidate)) return candidate;
1102
+ const found = findExecutableUnder(dir, names, 6);
1103
+ if (found) return found;
1104
+ }
1098
1105
  for (const root of scanRoots){
1099
1106
  const found = findExecutableUnder(root, names, 6);
1100
1107
  if (found) return found;
1101
1108
  }
1102
1109
  return null;
1103
1110
  }
1111
+ const MANAGED_BUILD_DIR_PREFIX = /^(?:mac_arm|mac-arm|mac|win64|win32|linux64|linux)[-_]/i;
1112
+ function parseManagedBuildId(dirName) {
1113
+ const name = String(dirName || '');
1114
+ const buildId = name.replace(MANAGED_BUILD_DIR_PREFIX, '');
1115
+ return buildId.split(/[^\d]+/).filter(Boolean).map((part)=>Number(part)).filter((part)=>Number.isFinite(part));
1116
+ }
1117
+ function compareManagedBuildDirNames(a, b) {
1118
+ const partsA = parseManagedBuildId(a);
1119
+ const partsB = parseManagedBuildId(b);
1120
+ const length = Math.max(partsA.length, partsB.length);
1121
+ for(let i = 0; i < length; i++){
1122
+ const na = partsA[i] ?? 0;
1123
+ const nb = partsB[i] ?? 0;
1124
+ if (na !== nb) return na - nb;
1125
+ }
1126
+ return String(a).localeCompare(String(b));
1127
+ }
1128
+ function compareManagedBuildDirsNewestFirst(a, b) {
1129
+ const byBuild = compareManagedBuildDirNames(node_path__rspack_import_1.basename(b), node_path__rspack_import_1.basename(a));
1130
+ if (0 !== byBuild) return byBuild;
1131
+ let timeA = 0;
1132
+ let timeB = 0;
1133
+ try {
1134
+ timeA = node_fs__rspack_import_0.statSync(a).mtimeMs;
1135
+ } catch {}
1136
+ try {
1137
+ timeB = node_fs__rspack_import_0.statSync(b).mtimeMs;
1138
+ } catch {}
1139
+ if (timeA !== timeB) return timeB - timeA;
1140
+ return node_path__rspack_import_1.basename(b).localeCompare(node_path__rspack_import_1.basename(a));
1141
+ }
1104
1142
  function resolveChromiumFamilyFallback(compilation, requested = 'chromium') {
1105
1143
  const candidates = 'chrome' === requested ? [
1106
1144
  'chromium',
@@ -1134,6 +1172,13 @@ var __webpack_modules__ = {
1134
1172
  else out.push(node_path__rspack_import_1.join(dir, 'firefox'));
1135
1173
  return out;
1136
1174
  }
1175
+ function isUsableBinaryPath(candidate) {
1176
+ try {
1177
+ return Boolean(candidate) && node_fs__rspack_import_0.statSync(candidate).isFile();
1178
+ } catch {
1179
+ return false;
1180
+ }
1181
+ }
1137
1182
  function executableNamesFor(browser) {
1138
1183
  if ('chrome' === browser) return 'win32' === process.platform ? [
1139
1184
  'chrome.exe'
@@ -1152,6 +1197,7 @@ var __webpack_modules__ = {
1152
1197
  if ('edge' === browser) return 'win32' === process.platform ? [
1153
1198
  'msedge.exe'
1154
1199
  ] : [
1200
+ 'Microsoft Edge',
1155
1201
  'msedge',
1156
1202
  'microsoft-edge'
1157
1203
  ];
@@ -1545,6 +1591,9 @@ var __webpack_modules__ = {
1545
1591
  var node_net__rspack_import_1 = __webpack_require__("node:net");
1546
1592
  var node_os__rspack_import_2 = __webpack_require__("node:os");
1547
1593
  var node_path__rspack_import_3 = __webpack_require__("node:path");
1594
+ var chrome_location2__rspack_import_4 = __webpack_require__("chrome-location2");
1595
+ var chromium_location__rspack_import_5 = __webpack_require__("chromium-location");
1596
+ var edge_location__rspack_import_6 = __webpack_require__("edge-location");
1548
1597
  __webpack_require__("./browsers/browsers-lib/constants.ts");
1549
1598
  const MANAGED_EPHEMERAL_PROFILE_MARKER = '.extension-js-managed-profile';
1550
1599
  function shortInstanceId(instanceId) {
@@ -1563,8 +1612,12 @@ var __webpack_modules__ = {
1563
1612
  const finalPort = 'number' == typeof parsed && Number.isFinite(parsed) && parsed > 0 ? parsed : devServerPort;
1564
1613
  return 'number' == typeof finalPort && finalPort > 0 ? finalPort + 100 : defaultPort;
1565
1614
  }
1566
- function filterBrowserFlags(defaultFlags, excludeFlags = []) {
1567
- return defaultFlags.filter((flag)=>!excludeFlags.some((excludeFlag)=>flag === excludeFlag));
1615
+ function filterBrowserFlags(flags, excludeFlags = []) {
1616
+ return flags.filter((flag)=>!excludeFlags.some((excludeFlag)=>{
1617
+ if (!excludeFlag) return false;
1618
+ if (flag === excludeFlag) return true;
1619
+ return flag.startsWith(`${excludeFlag}=`) || flag.startsWith(`${excludeFlag},`);
1620
+ }));
1568
1621
  }
1569
1622
  function chooseChromiumBinaryPreferringStable(opts) {
1570
1623
  const managed = opts.managedSnapshotBinary;
@@ -1607,6 +1660,28 @@ var __webpack_modules__ = {
1607
1660
  const underManagedRoot = relative.length > 0 && !relative.startsWith('..') && !node_path__rspack_import_3.isAbsolute(relative);
1608
1661
  return underManagedRoot ? 'managed' : 'system';
1609
1662
  }
1663
+ function probeChromiumBinaryVersion(bin, browser) {
1664
+ const target = String(browser || '');
1665
+ const probes = [];
1666
+ if ('edge' === target) probes.push(()=>(0, edge_location__rspack_import_6.getEdgeVersion)(bin, {
1667
+ allowExec: true
1668
+ }));
1669
+ if ('chromium' === target || 'chromium-based' === target) probes.push(()=>(0, chromium_location__rspack_import_5.getChromiumVersion)(bin, {
1670
+ allowExec: true
1671
+ }));
1672
+ probes.push(()=>(0, chrome_location2__rspack_import_4.getChromeVersion)(bin, {
1673
+ allowExec: true
1674
+ }), ()=>(0, chromium_location__rspack_import_5.getChromiumVersion)(bin, {
1675
+ allowExec: true
1676
+ }), ()=>(0, edge_location__rspack_import_6.getEdgeVersion)(bin, {
1677
+ allowExec: true
1678
+ }));
1679
+ for (const probe of probes)try {
1680
+ const line = probe();
1681
+ if (line && String(line).trim()) return String(line).trim();
1682
+ } catch {}
1683
+ return '';
1684
+ }
1610
1685
  function parseEnvBrowserFlags(raw) {
1611
1686
  return String(raw || '').split(/\s+/).map((flag)=>flag.trim()).filter(Boolean);
1612
1687
  }
@@ -1789,7 +1864,8 @@ var __webpack_modules__ = {
1789
1864
  ci: ()=>isProfileLockedError,
1790
1865
  jl: ()=>deriveDebugPortWithInstance,
1791
1866
  ov: ()=>filterBrowserFlags,
1792
- sW: ()=>removeManagedEphemeralProfile
1867
+ sW: ()=>removeManagedEphemeralProfile,
1868
+ yO: ()=>probeChromiumBinaryVersion
1793
1869
  });
1794
1870
  },
1795
1871
  "./browsers/browsers-lib/wsl-support.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -2529,7 +2605,7 @@ var __webpack_modules__ = {
2529
2605
  '--remote-debugging-pipe'
2530
2606
  ] : [],
2531
2607
  ...filteredFlags,
2532
- ...configOptions.browserFlags || [],
2608
+ ...(0, shared_utils.ov)(configOptions.browserFlags || [], excludeFlags),
2533
2609
  ...(0, shared_utils.W0)(process.env.EXTENSION_BROWSER_FLAGS)
2534
2610
  ];
2535
2611
  if ((0, shared_utils.ZO)() && !baseFlags.some((flag)=>flag.startsWith('--headless'))) baseFlags.push('--headless=new');
@@ -2798,7 +2874,16 @@ var __webpack_modules__ = {
2798
2874
  });
2799
2875
  }
2800
2876
  async launchChromium(compilation, opts) {
2801
- if (this.options?.dryRun || process.env.VITEST || process.env.VITEST_WORKER_ID) return void logChromiumDryRun('chromium-mock-binary', []);
2877
+ if (this.options?.chromiumBinary) {
2878
+ const requested = String(this.options.chromiumBinary);
2879
+ const normalizedEarly = (0, wsl_support.f7)(requested);
2880
+ if (!normalizedEarly || !external_node_fs_.existsSync(normalizedEarly)) {
2881
+ (0, messaging.Gg)(messages.Sp(requested));
2882
+ if (process.env.VITEST || process.env.VITEST_WORKER_ID) throw new Error(`Invalid --chromium-binary path: ${requested}`);
2883
+ process.exit(1);
2884
+ }
2885
+ }
2886
+ if (this.options?.dryRun || process.env.VITEST || process.env.VITEST_WORKER_ID) return void logChromiumDryRun(this.options?.chromiumBinary ? (0, wsl_support.f7)(String(this.options.chromiumBinary)) : 'chromium-mock-binary', []);
2802
2887
  const browser = this.options?.browser;
2803
2888
  let browserBinaryLocation = null;
2804
2889
  let printedGuidance = false;
@@ -2858,8 +2943,18 @@ var __webpack_modules__ = {
2858
2943
  this.printEnhancedPuppeteerInstallHint(compilation, raw, browserName);
2859
2944
  printedGuidance = true;
2860
2945
  };
2861
- browserBinaryLocation = resolveManagedBinary();
2862
- if ('chromium' === browser && browserBinaryLocation) {
2946
+ const requestedPin = this.options?.chromiumBinary != null ? String(this.options.chromiumBinary) : '';
2947
+ if (requestedPin) {
2948
+ const normalized = normalizePath(requestedPin);
2949
+ if (!normalized || !isUsableBinary(normalized)) {
2950
+ (0, messaging.Gg)(messages.Sp(requestedPin));
2951
+ if (process.env.VITEST || process.env.VITEST_WORKER_ID) throw new Error(`Invalid --chromium-binary path: ${requestedPin}`);
2952
+ process.exit(1);
2953
+ }
2954
+ browserBinaryLocation = normalized;
2955
+ binaryPinnedByFlag = true;
2956
+ } else browserBinaryLocation = resolveManagedBinary();
2957
+ if ('chromium' === browser && browserBinaryLocation && !binaryPinnedByFlag) {
2863
2958
  let systemBinary = null;
2864
2959
  try {
2865
2960
  const env = {
@@ -2885,7 +2980,7 @@ var __webpack_modules__ = {
2885
2980
  }
2886
2981
  }
2887
2982
  let skipDetection = Boolean(browserBinaryLocation);
2888
- if (!browserBinaryLocation && (0, wsl_support.EV)()) {
2983
+ if (!binaryPinnedByFlag && !browserBinaryLocation && (0, wsl_support.EV)()) {
2889
2984
  const linuxFallback = resolveWslLinuxBinary(browser);
2890
2985
  if (linuxFallback) {
2891
2986
  browserBinaryLocation = linuxFallback;
@@ -2898,16 +2993,8 @@ var __webpack_modules__ = {
2898
2993
  }
2899
2994
  }
2900
2995
  }
2901
- browserBinaryLocation = preferRealChromeBinary(browserBinaryLocation);
2902
- const getBrowserVersionLine = (bin)=>{
2903
- try {
2904
- if ('edge' === browser) return (0, external_edge_location_.getEdgeVersion)(bin) || '';
2905
- if ('chromium' === browser || 'chromium-based' === browser) return (0, external_chromium_location_.getChromiumVersion)(bin) || '';
2906
- return (0, external_chrome_location2_.getChromeVersion)(bin) || '';
2907
- } catch {
2908
- return '';
2909
- }
2910
- };
2996
+ if (!binaryPinnedByFlag) browserBinaryLocation = preferRealChromeBinary(browserBinaryLocation);
2997
+ const getBrowserVersionLine = (bin)=>shared_utils.yO(bin, String(browser || ''));
2911
2998
  const looksOfficialChromeBinaryPath = (bin)=>{
2912
2999
  const p = String(bin || '');
2913
3000
  if (!p) return false;
@@ -2962,7 +3049,7 @@ var __webpack_modules__ = {
2962
3049
  return null;
2963
3050
  }
2964
3051
  };
2965
- switch(browser){
3052
+ if (!binaryPinnedByFlag) switch(browser){
2966
3053
  case 'chrome':
2967
3054
  if (isAuthorMode) (0, messaging._w)(messages.Gq(browser));
2968
3055
  if (!skipDetection) browserBinaryLocation = resolveChromeLikeBinary();
@@ -2984,15 +3071,6 @@ var __webpack_modules__ = {
2984
3071
  break;
2985
3072
  case 'chromium':
2986
3073
  if (isAuthorMode) (0, messaging._w)(messages.Gq(browser));
2987
- if (this.options?.chromiumBinary) {
2988
- const normalized = normalizePath(String(this.options.chromiumBinary));
2989
- if (!normalized || !external_node_fs_.existsSync(normalized)) {
2990
- (0, messaging.Gg)(messages.Sp(String(this.options.chromiumBinary)));
2991
- process.exit(1);
2992
- }
2993
- browserBinaryLocation = normalized;
2994
- binaryPinnedByFlag = true;
2995
- }
2996
3074
  if (!browserBinaryLocation && !skipDetection) try {
2997
3075
  const env = managedEnvFor('chromium');
2998
3076
  const p = external_chromium_location_default()({
@@ -3046,36 +3124,20 @@ var __webpack_modules__ = {
3046
3124
  }
3047
3125
  break;
3048
3126
  case 'chromium-based':
3049
- browserBinaryLocation = this.options?.chromiumBinary || null;
3050
- if (this.options?.chromiumBinary) {
3051
- const normalized = normalizePath(String(this.options.chromiumBinary));
3052
- if (!normalized || !external_node_fs_.existsSync(normalized)) {
3053
- (0, messaging.Gg)(messages.Sp(String(this.options.chromiumBinary)));
3054
- process.exit(1);
3055
- }
3056
- browserBinaryLocation = normalized;
3057
- binaryPinnedByFlag = true;
3058
- } else {
3059
- (0, messaging.Gg)(messages.ne());
3060
- process.exit(1);
3061
- }
3062
- if (!browserBinaryLocation && !skipDetection) try {
3063
- const env = managedEnvFor('chromium');
3064
- const p = external_chromium_location_default()({
3065
- env
3066
- });
3067
- const normalized = normalizePath(p || null);
3068
- if (normalized && 'string' == typeof normalized) {
3069
- if (external_node_fs_.existsSync(normalized)) browserBinaryLocation = normalized;
3070
- }
3071
- } catch {}
3072
- if (!browserBinaryLocation) browserBinaryLocation = resolveWslFallback();
3127
+ (0, messaging.Gg)(messages.ne());
3128
+ if (process.env.VITEST || process.env.VITEST_WORKER_ID) throw new Error('chromium-based requires --chromium-binary');
3129
+ process.exit(1);
3073
3130
  break;
3074
3131
  default:
3075
3132
  browserBinaryLocation = resolveChromeLikeBinary();
3076
3133
  break;
3077
3134
  }
3078
3135
  if (!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) {
3136
+ if (binaryPinnedByFlag) {
3137
+ (0, messaging.Gg)(messages.Sp(requestedPin));
3138
+ if (process.env.VITEST || process.env.VITEST_WORKER_ID) throw new Error(`Invalid --chromium-binary path: ${requestedPin}`);
3139
+ process.exit(1);
3140
+ }
3079
3141
  browserBinaryLocation = browserBinaryLocation || resolveManagedBinary();
3080
3142
  if (!browserBinaryLocation) browserBinaryLocation = resolveWslFallback();
3081
3143
  if ((!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) && ('chrome' === browser || 'chromium' === browser)) {
@@ -3643,7 +3705,7 @@ var __webpack_modules__ = {
3643
3705
  const { browser, profile, browserFlags = [] } = configOptions;
3644
3706
  const binaryArgs = [];
3645
3707
  const excludeFlags = configOptions.excludeBrowserFlags || [];
3646
- const filteredFlags = (browserFlags || []).filter((flag)=>excludeFlags.every((ex)=>!String(flag).startsWith(ex)));
3708
+ const filteredFlags = (0, shared_utils.ov)((browserFlags || []).map(String), excludeFlags);
3647
3709
  if (filteredFlags.length > 0) binaryArgs.push(...filteredFlags);
3648
3710
  binaryArgs.push(...(0, shared_utils.W0)(process.env.EXTENSION_BROWSER_FLAGS));
3649
3711
  if (configOptions.startingUrl && !configOptions.noOpen) binaryArgs.push('--url', String(configOptions.startingUrl));
@@ -5165,18 +5227,16 @@ var __webpack_modules__ = {
5165
5227
  },
5166
5228
  "./browsers/run-only.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
5167
5229
  var node_fs__rspack_import_0 = __webpack_require__("node:fs");
5168
- var chrome_location2__rspack_import_1 = __webpack_require__("chrome-location2");
5169
- var chromium_location__rspack_import_2 = __webpack_require__("chromium-location");
5170
- var edge_location__rspack_import_3 = __webpack_require__("edge-location");
5171
- var firefox_location2__rspack_import_4 = __webpack_require__("firefox-location2");
5172
- var _browsers_lib_banner__rspack_import_5 = __webpack_require__("./browsers/browsers-lib/banner.ts");
5173
- var _browsers_lib_browser_family__rspack_import_6 = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
5174
- var _browsers_lib_output_binaries_resolver__rspack_import_7 = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
5175
- var _browsers_lib_runtime_options__rspack_import_12 = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
5176
- var _run_chromium_chromium_context__rspack_import_10 = __webpack_require__("./browsers/run-chromium/chromium-context/index.ts");
5177
- var _run_chromium_chromium_launch__rspack_import_8 = __webpack_require__("./browsers/run-chromium/chromium-launch/index.ts");
5178
- var _run_firefox_firefox_context__rspack_import_11 = __webpack_require__("./browsers/run-firefox/firefox-context/index.ts");
5179
- var _run_firefox_firefox_launch__rspack_import_9 = __webpack_require__("./browsers/run-firefox/firefox-launch/index.ts");
5230
+ var firefox_location2__rspack_import_1 = __webpack_require__("firefox-location2");
5231
+ var _browsers_lib_banner__rspack_import_2 = __webpack_require__("./browsers/browsers-lib/banner.ts");
5232
+ var _browsers_lib_browser_family__rspack_import_3 = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
5233
+ var _browsers_lib_output_binaries_resolver__rspack_import_4 = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
5234
+ var _browsers_lib_runtime_options__rspack_import_10 = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
5235
+ var _browsers_lib_shared_utils__rspack_import_5 = __webpack_require__("./browsers/browsers-lib/shared-utils.ts");
5236
+ var _run_chromium_chromium_context__rspack_import_8 = __webpack_require__("./browsers/run-chromium/chromium-context/index.ts");
5237
+ var _run_chromium_chromium_launch__rspack_import_6 = __webpack_require__("./browsers/run-chromium/chromium-launch/index.ts");
5238
+ var _run_firefox_firefox_context__rspack_import_9 = __webpack_require__("./browsers/run-firefox/firefox-context/index.ts");
5239
+ var _run_firefox_firefox_launch__rspack_import_7 = __webpack_require__("./browsers/run-firefox/firefox-launch/index.ts");
5180
5240
  function createPreviewCompilationLike(opts) {
5181
5241
  return {
5182
5242
  options: {
@@ -5262,26 +5322,29 @@ var __webpack_modules__ = {
5262
5322
  }
5263
5323
  function resolvePinnedBinaryVersionLine(opts) {
5264
5324
  try {
5265
- if ((0, _browsers_lib_browser_family__rspack_import_6.M_)(opts.browser)) {
5325
+ if ((0, _browsers_lib_browser_family__rspack_import_3.M_)(opts.browser)) {
5266
5326
  if (!opts.geckoBinary || !node_fs__rspack_import_0.existsSync(opts.geckoBinary)) return;
5267
- return (0, firefox_location2__rspack_import_4.getFirefoxVersion)(opts.geckoBinary) || void 0;
5327
+ return (0, firefox_location2__rspack_import_1.getFirefoxVersion)(opts.geckoBinary) || void 0;
5268
5328
  }
5269
5329
  if (!opts.chromiumBinary || !node_fs__rspack_import_0.existsSync(opts.chromiumBinary)) return;
5270
- if ('edge' === opts.browser) return (0, edge_location__rspack_import_3.getEdgeVersion)(opts.chromiumBinary) || void 0;
5271
- if ('chromium' === opts.browser || 'chromium-based' === opts.browser) return (0, chromium_location__rspack_import_2.getChromiumVersion)(opts.chromiumBinary) || void 0;
5272
- return (0, chrome_location2__rspack_import_1.getChromeVersion)(opts.chromiumBinary) || void 0;
5330
+ return (0, _browsers_lib_shared_utils__rspack_import_5.yO)(opts.chromiumBinary, String(opts.browser)) || void 0;
5273
5331
  } catch {
5274
5332
  return;
5275
5333
  }
5276
5334
  }
5277
5335
  function buildPreviewBannerOptions(opts) {
5336
+ const chromiumPinned = !(0, _browsers_lib_browser_family__rspack_import_3.M_)(opts.browser) && 'string' == typeof opts.chromiumBinary && node_fs__rspack_import_0.existsSync(opts.chromiumBinary);
5278
5337
  return {
5279
5338
  browser: opts.browser,
5280
5339
  outPath: opts.outPath,
5281
5340
  includeExtensionId: true,
5282
5341
  includeRunId: false,
5283
5342
  readyPath: opts.readyPath,
5284
- browserVersionLine: resolvePinnedBinaryVersionLine(opts)
5343
+ browserVersionLine: resolvePinnedBinaryVersionLine(opts),
5344
+ ...chromiumPinned ? {
5345
+ binaryPath: opts.chromiumBinary,
5346
+ binaryProvenance: 'pinned'
5347
+ } : {}
5285
5348
  };
5286
5349
  }
5287
5350
  async function runOnlyPreviewBrowser(opts) {
@@ -5297,21 +5360,21 @@ var __webpack_modules__ = {
5297
5360
  const compilationLike = createPreviewCompilationLike(opts);
5298
5361
  const previewPluginOptions = buildPreviewPluginOptions(opts);
5299
5362
  const bannerOptions = buildPreviewBannerOptions(opts);
5300
- (0, _browsers_lib_output_binaries_resolver__rspack_import_7.LB)(compilationLike);
5301
- if ((0, _browsers_lib_browser_family__rspack_import_6.rG)(opts.browser)) {
5302
- const ctx = (0, _run_chromium_chromium_context__rspack_import_10.g)();
5303
- const launcher = new _run_chromium_chromium_launch__rspack_import_8.f(buildPreviewChromiumOptions(opts), ctx);
5304
- await (0, _browsers_lib_banner__rspack_import_5.MK)(bannerOptions);
5363
+ (0, _browsers_lib_output_binaries_resolver__rspack_import_4.LB)(compilationLike);
5364
+ if ((0, _browsers_lib_browser_family__rspack_import_3.rG)(opts.browser)) {
5365
+ const ctx = (0, _run_chromium_chromium_context__rspack_import_8.g)();
5366
+ const launcher = new _run_chromium_chromium_launch__rspack_import_6.f(buildPreviewChromiumOptions(opts), ctx);
5367
+ await (0, _browsers_lib_banner__rspack_import_2.MK)(bannerOptions);
5305
5368
  await launcher.runOnce(compilationLike, {
5306
5369
  enableCdpPostLaunch: false
5307
5370
  });
5308
5371
  return;
5309
5372
  }
5310
- if ((0, _browsers_lib_browser_family__rspack_import_6.M_)(opts.browser)) {
5311
- const ctx = (0, _run_firefox_firefox_context__rspack_import_11.D)();
5312
- const launcher = new _run_firefox_firefox_launch__rspack_import_9.c(buildPreviewFirefoxOptions(opts), ctx);
5313
- await (0, _browsers_lib_banner__rspack_import_5.MK)(bannerOptions);
5314
- await launcher.runOnce(compilationLike, (0, _browsers_lib_runtime_options__rspack_import_12.zU)(previewPluginOptions, 'production', {
5373
+ if ((0, _browsers_lib_browser_family__rspack_import_3.M_)(opts.browser)) {
5374
+ const ctx = (0, _run_firefox_firefox_context__rspack_import_9.D)();
5375
+ const launcher = new _run_firefox_firefox_launch__rspack_import_7.c(buildPreviewFirefoxOptions(opts), ctx);
5376
+ await (0, _browsers_lib_banner__rspack_import_2.MK)(bannerOptions);
5377
+ await launcher.runOnce(compilationLike, (0, _browsers_lib_runtime_options__rspack_import_10.zU)(previewPluginOptions, 'production', {
5315
5378
  persistProfile: previewPluginOptions.persistProfile,
5316
5379
  geckoBinary: previewPluginOptions.geckoBinary
5317
5380
  }));
@@ -6422,7 +6485,7 @@ var __webpack_modules__ = {
6422
6485
  if (0 === this.buffer.length) return;
6423
6486
  const batch = this.buffer.splice(0, this.buffer.length);
6424
6487
  const ac = new AbortController();
6425
- const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
6488
+ const t = setTimeout(()=>ac.abort(), this.timeoutMs);
6426
6489
  const url = new URL('/capture/', this.host);
6427
6490
  await fetch(url.toString(), {
6428
6491
  method: 'POST',
@@ -6481,6 +6544,7 @@ var __webpack_modules__ = {
6481
6544
  _define_property(this, "sampleRate", void 0);
6482
6545
  _define_property(this, "maxEventsPerRun", void 0);
6483
6546
  _define_property(this, "debounceMs", void 0);
6547
+ _define_property(this, "timeoutMs", void 0);
6484
6548
  _define_property(this, "debug", void 0);
6485
6549
  _define_property(this, "common", void 0);
6486
6550
  _define_property(this, "recent", new Map());
@@ -6494,6 +6558,7 @@ var __webpack_modules__ = {
6494
6558
  this.sampleRate = clamp(init.sampleRate ?? DEFAULT_SAMPLE_RATE, 0, 1);
6495
6559
  this.maxEventsPerRun = Math.max(0, init.maxEventsPerRun ?? DEFAULT_MAX_EVENTS);
6496
6560
  this.debounceMs = Math.max(0, init.debounceMs ?? DEFAULT_DEBOUNCE_MS);
6561
+ this.timeoutMs = Math.max(1, init.timeoutMs ?? DEFAULT_TIMEOUT_MS);
6497
6562
  this.common = {
6498
6563
  os: process.platform,
6499
6564
  arch: process.arch,
@@ -6544,14 +6609,14 @@ var __webpack_modules__ = {
6544
6609
  }
6545
6610
  }
6546
6611
  }
6547
- function commandContext(command) {
6612
+ function telemetryCommandContext(command, argv = process.argv) {
6548
6613
  if ('create' !== command) return {};
6549
6614
  return {
6550
- template: readArgValue(process.argv, [
6615
+ template: readArgValue(argv, [
6551
6616
  '--template',
6552
6617
  '-t'
6553
6618
  ]),
6554
- source: readArgValue(process.argv, [
6619
+ source: readArgValue(argv, [
6555
6620
  '--source'
6556
6621
  ]) || 'cli'
6557
6622
  };
@@ -6587,7 +6652,7 @@ var __webpack_modules__ = {
6587
6652
  command,
6588
6653
  success: true,
6589
6654
  version: telemetry_cli_version,
6590
- ...commandContext(command)
6655
+ ...telemetryCommandContext(command)
6591
6656
  });
6592
6657
  }
6593
6658
  function markCommandFailure(command = invoked) {
@@ -6596,7 +6661,7 @@ var __webpack_modules__ = {
6596
6661
  command,
6597
6662
  success: false,
6598
6663
  version: telemetry_cli_version,
6599
- ...commandContext(command)
6664
+ ...telemetryCommandContext(command)
6600
6665
  });
6601
6666
  }
6602
6667
  function printOptOutNoticeIfFirstRun() {
@@ -7188,7 +7253,7 @@ var __webpack_modules__ = {
7188
7253
  notes: [
7189
7254
  {
7190
7255
  usage: '--browser <chrome|chromium|edge|firefox|chromium-based|gecko-based|firefox-based|all>',
7191
- description: 'Install multiple browsers, browser families, or all'
7256
+ description: 'Install one or more managed browsers (comma-separated) or all'
7192
7257
  },
7193
7258
  {
7194
7259
  usage: '--where',
@@ -7207,13 +7272,17 @@ var __webpack_modules__ = {
7207
7272
  description: 'Remove managed browser binaries from the Extension.js cache',
7208
7273
  supportsSourceInspection: false,
7209
7274
  notes: [
7275
+ {
7276
+ usage: '--browser <chrome|chromium|edge|firefox|chromium-based|gecko-based|firefox-based|all>',
7277
+ description: 'Remove one or more managed browsers (comma-separated), same names as install'
7278
+ },
7210
7279
  {
7211
7280
  usage: '--all',
7212
7281
  description: 'Remove every managed browser binary'
7213
7282
  },
7214
7283
  {
7215
7284
  usage: '--where',
7216
- description: 'Print the managed browser cache root (or browser install path(s) when --browser/--all is provided)'
7285
+ description: 'Print the managed browser cache root (or browser install path(s) when a browser name, --browser, or --all is provided)'
7217
7286
  }
7218
7287
  ]
7219
7288
  },
@@ -7359,6 +7428,23 @@ AI assistants
7359
7428
  function unsupportedBrowserFlag(value, supported) {
7360
7429
  return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}.\n${external_pintor_default().red('Choose one of:')} ${supported.join(', ')}${external_pintor_default().red('.')}`;
7361
7430
  }
7431
+ function browserNotInstallablePlain(value) {
7432
+ const name = String(value || '').trim().toLowerCase();
7433
+ if ('safari' === name || 'webkit-based' === name || name.includes('safari') || name.includes('webkit')) return "There is no Safari binary to install. Safari ships with macOS. Safari builds need the full Xcode app instead (Mac App Store), then run `extension build --browser safari`.";
7434
+ const display = name || String(value || 'browser');
7435
+ return `${display} cannot be installed by Extension.js. This CLI never downloads it. It is located from the system when present. Install it yourself, then run with --browser=${display}. Managed installs cover: chrome, chromium, edge, firefox.`;
7436
+ }
7437
+ function browserNotInstallable(value) {
7438
+ const name = String(value || '').trim().toLowerCase();
7439
+ if ('safari' === name || 'webkit-based' === name || name.includes('safari') || name.includes('webkit')) return `${getLoggingPrefix('error')} There is no Safari binary to install.\n${external_pintor_default().red('Safari ships with macOS. Safari builds need the full Xcode app')} ${external_pintor_default().red('(Mac App Store), then run')} ${messages_code('extension build --browser safari')}${external_pintor_default().red('.')}`;
7440
+ const display = name || String(value || 'browser');
7441
+ return `${getLoggingPrefix('error')} ${external_pintor_default().blue(display)} cannot be installed by Extension.js.\n${external_pintor_default().red('This CLI never downloads it. It is located from the system when present.')}\n${external_pintor_default().red('Install it yourself, then run with')} ${messages_code(`--browser=${display}`)}${external_pintor_default().red('.')}\n${external_pintor_default().red('Managed installs cover:')} chrome, chromium, edge, firefox${external_pintor_default().red('.')}`;
7442
+ }
7443
+ function browserDownloadFailed(browser, detail) {
7444
+ const name = String(browser || 'browser').trim() || 'browser';
7445
+ const body = String(detail || '').trim();
7446
+ return `${getLoggingPrefix('error')} Couldn't download ${external_pintor_default().blue(name)}.\n` + (body ? `${external_pintor_default().red(body)}\n` : '') + `${external_pintor_default().red('Retry, or install')} ${external_pintor_default().blue(name)} ${external_pintor_default().red('manually.')}`;
7447
+ }
7362
7448
  function safariOnlyOption(flags) {
7363
7449
  return `${getLoggingPrefix('error')} ${flags.map(messages_code).join(', ')} only appl${1 === flags.length ? 'ies' : 'y'} to Safari targets.\nAdd ${messages_code('--browser safari')} (or ${messages_code('webkit-based')}).`;
7364
7450
  }
@@ -8219,13 +8305,29 @@ Cross-browser compatibility
8219
8305
  'chrome',
8220
8306
  'edge',
8221
8307
  'firefox'
8222
- ] : String(value).split(',');
8308
+ ] : String(value).split(',').map((part)=>part.trim()).filter(Boolean);
8223
8309
  };
8310
+ const MANAGED_INSTALL_TARGETS = [
8311
+ 'chrome',
8312
+ 'chromium',
8313
+ 'edge',
8314
+ 'firefox',
8315
+ 'chromium-based',
8316
+ 'gecko-based',
8317
+ 'firefox-based'
8318
+ ];
8319
+ const MANAGED_INSTALL_TARGETS_HELP = [
8320
+ ...MANAGED_INSTALL_TARGETS,
8321
+ 'all'
8322
+ ].join(' | ');
8323
+ const MANAGED_INSTALL_BINARIES = [
8324
+ 'chrome',
8325
+ 'chromium',
8326
+ 'edge',
8327
+ 'firefox'
8328
+ ];
8224
8329
  const installTargets = (browser)=>'all' === browser ? [
8225
- 'chrome',
8226
- 'chromium',
8227
- 'edge',
8228
- 'firefox'
8330
+ ...MANAGED_INSTALL_BINARIES
8229
8331
  ] : vendors(browser);
8230
8332
  function validateVendors(vendorsList, onInvalid) {
8231
8333
  const supported = SUPPORTED_BROWSER_TARGETS;
@@ -8235,6 +8337,25 @@ Cross-browser compatibility
8235
8337
  }
8236
8338
  return true;
8237
8339
  }
8340
+ const MANAGED_INSTALL_TARGET_SET = new Set(MANAGED_INSTALL_TARGETS);
8341
+ const SUPPORTED_BROWSER_TARGET_SET = new Set(SUPPORTED_BROWSER_TARGETS);
8342
+ function classifyManagedInstallTarget(name) {
8343
+ const value = String(name || '').trim().toLowerCase();
8344
+ if (!value) return 'unknown';
8345
+ if (MANAGED_INSTALL_TARGET_SET.has(value)) return 'managed';
8346
+ if (SUPPORTED_BROWSER_TARGET_SET.has(value)) return 'not-installable';
8347
+ return 'unknown';
8348
+ }
8349
+ function firstNonManagedInstallTarget(targetsList) {
8350
+ for (const name of targetsList){
8351
+ const kind = classifyManagedInstallTarget(name);
8352
+ if ('managed' !== kind) return {
8353
+ name,
8354
+ kind
8355
+ };
8356
+ }
8357
+ return null;
8358
+ }
8238
8359
  function registerBuildCommand(program) {
8239
8360
  program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', parseOptionalBoolean).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser = 'chromium', ...buildOptions })=>{
8240
8361
  if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
@@ -9313,31 +9434,75 @@ Cross-browser compatibility
9313
9434
  function install_emit(frame) {
9314
9435
  console.log(JSON.stringify(frame));
9315
9436
  }
9437
+ function errorText(error) {
9438
+ return error instanceof Error ? error.message : String(error);
9439
+ }
9440
+ function isNotInstallableRefusal(error) {
9441
+ return Boolean(error && 'object' == typeof error && ('BrowserNotInstallableError' === error.name || 'BROWSER_NOT_INSTALLABLE' === error.code));
9442
+ }
9443
+ async function refuseNotInstallable(command, error, asJson) {
9444
+ const message = errorText(error);
9445
+ if (asJson) install_emit(messaging.Pr.fail(command, 'usage', {
9446
+ code: messaging.Lp.E_BROWSER_NOT_INSTALLABLE,
9447
+ message
9448
+ }));
9449
+ else console.error(message);
9450
+ await exitAfterDrain(1);
9451
+ }
9452
+ async function refuseIfNotManagedTarget(command, browserList, asJson) {
9453
+ const bad = firstNonManagedInstallTarget(browserList);
9454
+ if (!bad) return false;
9455
+ if ('not-installable' === bad.kind) {
9456
+ const message = browserNotInstallablePlain(bad.name);
9457
+ if (asJson) install_emit(messaging.Pr.fail(command, 'usage', {
9458
+ code: messaging.Lp.E_BROWSER_NOT_INSTALLABLE,
9459
+ message
9460
+ }));
9461
+ else console.error(browserNotInstallable(bad.name));
9462
+ await exitAfterDrain(1);
9463
+ return true;
9464
+ }
9465
+ if (asJson) install_emit(messaging.Pr.fail(command, 'usage', {
9466
+ code: messaging.Lp.E_UNSUPPORTED_BROWSER,
9467
+ message: `Unsupported browser: ${bad.name}.`
9468
+ }));
9469
+ else console.error(unsupportedBrowserFlag(bad.name, [
9470
+ ...MANAGED_INSTALL_TARGETS
9471
+ ]));
9472
+ await exitAfterDrain(1);
9473
+ return true;
9474
+ }
9475
+ async function refuseDownloadFailed(browser, error, asJson) {
9476
+ const detail = errorText(error);
9477
+ if (asJson) install_emit(messaging.Pr.fail('install', 'failed', {
9478
+ code: messaging.Lp.E_BROWSER_DOWNLOAD,
9479
+ message: detail
9480
+ }, {
9481
+ hint: `Retry, or install ${browser} manually.`
9482
+ }));
9483
+ else console.error(browserDownloadFailed(browser, detail));
9484
+ await exitAfterDrain(1);
9485
+ }
9316
9486
  function registerInstallCommand(program) {
9317
- program.command('install').arguments('[browser-name]').usage('[browser-name] [options]').description(commandDescriptions.install).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | all>', 'override the positional browser name. Supports comma-separated values and `all`.').option('--where', 'print the resolved managed browser cache root').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').action(async (browserArg, options)=>{
9487
+ program.command('install').arguments('[browser-name]').usage('[browser-name] [options]').description(commandDescriptions.install).option(`--browser <${MANAGED_INSTALL_TARGETS_HELP}>`, 'override the positional browser name. Supports comma-separated values and `all`.').option('--where', 'print the resolved managed browser cache root').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').action(async (browserArg, options)=>{
9318
9488
  const asJson = 'json' === options.output;
9489
+ const named = Boolean(options.browser || browserArg);
9319
9490
  const selectedBrowser = options.browser || browserArg || 'chromium';
9320
9491
  const browserList = installTargets(selectedBrowser);
9321
- let unsupported = '';
9322
- const vendorsAreSupported = validateVendors(browserList, (invalid, supported)=>{
9323
- unsupported = invalid;
9324
- if (asJson) return;
9325
- console.error(unsupportedBrowserFlag(invalid, supported));
9326
- });
9327
- if (!vendorsAreSupported) {
9328
- if (asJson) install_emit(messaging.Pr.fail('install', 'usage', {
9329
- code: messaging.Lp.E_UNSUPPORTED_BROWSER,
9330
- message: `Unsupported browser: ${unsupported}.`
9331
- }));
9332
- await exitAfterDrain(1);
9333
- return;
9492
+ if (!(options.where && !named)) {
9493
+ if (await refuseIfNotManagedTarget('install', browserList, asJson)) return;
9334
9494
  }
9335
9495
  const { extensionInstall, getManagedBrowsersCacheRoot, getManagedBrowserInstallDir } = await import("extension-install");
9336
9496
  if (options.where) {
9337
- const named = Boolean(options.browser || browserArg);
9338
- const paths = named ? browserList.map((browser)=>getManagedBrowserInstallDir(browser)) : [
9339
- getManagedBrowsersCacheRoot()
9340
- ];
9497
+ let paths;
9498
+ try {
9499
+ paths = named ? browserList.map((browser)=>getManagedBrowserInstallDir(browser)) : [
9500
+ getManagedBrowsersCacheRoot()
9501
+ ];
9502
+ } catch (error) {
9503
+ await refuseNotInstallable('install', error, asJson);
9504
+ return;
9505
+ }
9341
9506
  if (asJson) install_emit(messaging.Pr.ok('install', 'located', {
9342
9507
  paths
9343
9508
  }));
@@ -9351,45 +9516,21 @@ Cross-browser compatibility
9351
9516
  });
9352
9517
  installed.push(browser);
9353
9518
  } catch (error) {
9354
- if (!asJson) throw error;
9355
- install_emit(messaging.Pr.fail('install', 'failed', {
9356
- code: messaging.Lp.E_BROWSER_DOWNLOAD,
9357
- message: error instanceof Error ? error.message : String(error)
9358
- }, {
9359
- hint: `Retry, or install ${browser} manually.`
9360
- }));
9361
- await exitAfterDrain(1);
9519
+ if (isNotInstallableRefusal(error)) return void await refuseNotInstallable('install', error, asJson);
9520
+ await refuseDownloadFailed(browser, error, asJson);
9362
9521
  return;
9363
9522
  }
9364
9523
  if (asJson) install_emit(messaging.Pr.ok('install', 'installed', {
9365
9524
  browsers: installed
9366
9525
  }));
9367
9526
  });
9368
- program.command('uninstall').usage('<browser-name> | --all | --where').description(commandDescriptions.uninstall).option('--browser <browser-name>', 'browser to uninstall').option('--all', 'remove all managed browser binaries').option('--where', 'print the resolved managed browser cache root').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').argument('[browser-name]').action(async (browserArg, { browser, all, where, output })=>{
9527
+ program.command('uninstall').usage('<browser-name> | --all | --where').description(commandDescriptions.uninstall).option(`--browser <${MANAGED_INSTALL_TARGETS_HELP}>`, 'browser(s) to uninstall. Supports comma-separated values and `all`.').option('--all', 'remove all managed browser binaries').option('--where', 'print the resolved managed browser cache root').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').argument('[browser-name]').action(async (browserArg, { browser, all, where, output })=>{
9369
9528
  const asJson = 'json' === output;
9370
- const target = browserArg || browser;
9529
+ const named = Boolean(browserArg || browser);
9530
+ const selected = all || 'all' === browserArg || 'all' === browser ? 'all' : browser || browserArg;
9371
9531
  const { extensionUninstall, getManagedBrowsersCacheRoot, getManagedBrowserInstallDir } = await import("extension-install");
9372
- if (where) {
9373
- let paths;
9374
- if (all) paths = installTargets('all').map((name)=>getManagedBrowserInstallDir(name));
9375
- else if (target) {
9376
- const list = vendors(target);
9377
- let unsupported = '';
9378
- const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
9379
- unsupported = invalid;
9380
- if (asJson) return;
9381
- console.error(unsupportedBrowserFlag(invalid, supported));
9382
- });
9383
- if (!vendorsAreSupported) {
9384
- if (asJson) install_emit(messaging.Pr.fail('uninstall', 'usage', {
9385
- code: messaging.Lp.E_UNSUPPORTED_BROWSER,
9386
- message: `Unsupported browser: ${unsupported}.`
9387
- }));
9388
- await exitAfterDrain(1);
9389
- return;
9390
- }
9391
- paths = list.map((name)=>getManagedBrowserInstallDir(name));
9392
- } else paths = [
9532
+ if (where && !named && !all) {
9533
+ const paths = [
9393
9534
  getManagedBrowsersCacheRoot()
9394
9535
  ];
9395
9536
  if (asJson) install_emit(messaging.Pr.ok('uninstall', 'located', {
@@ -9398,23 +9539,51 @@ Cross-browser compatibility
9398
9539
  else for (const location of paths)console.log(location);
9399
9540
  return;
9400
9541
  }
9542
+ if (!selected) {
9543
+ const message = 'A browser target is required. Pass a browser name, --browser <name>, or --all.';
9544
+ if (asJson) install_emit(messaging.Pr.fail('uninstall', 'usage', {
9545
+ code: messaging.Lp.E_ARGS,
9546
+ message
9547
+ }));
9548
+ else console.error(message);
9549
+ await exitAfterDrain(1);
9550
+ return;
9551
+ }
9552
+ const browserList = installTargets(selected);
9553
+ if (await refuseIfNotManagedTarget('uninstall', browserList, asJson)) return;
9554
+ if (where) {
9555
+ let paths;
9556
+ try {
9557
+ paths = browserList.map((name)=>getManagedBrowserInstallDir(name));
9558
+ } catch (error) {
9559
+ await refuseNotInstallable('uninstall', error, asJson);
9560
+ return;
9561
+ }
9562
+ if (asJson) install_emit(messaging.Pr.ok('uninstall', 'located', {
9563
+ paths
9564
+ }));
9565
+ else for (const location of paths)console.log(location);
9566
+ return;
9567
+ }
9568
+ const removeAll = Boolean(all || 'all' === selected);
9401
9569
  try {
9402
9570
  await extensionUninstall({
9403
- browser: target,
9404
- all
9571
+ browser: removeAll ? void 0 : browserList.join(','),
9572
+ all: removeAll
9405
9573
  });
9406
9574
  } catch (error) {
9407
- if (!asJson) throw error;
9408
- install_emit(messaging.Pr.fail('uninstall', 'failed', {
9575
+ if (isNotInstallableRefusal(error)) return void await refuseNotInstallable('uninstall', error, asJson);
9576
+ if (asJson) install_emit(messaging.Pr.fail('uninstall', 'failed', {
9409
9577
  code: messaging.Lp.E_BROWSER_UNINSTALL,
9410
- message: error instanceof Error ? error.message : String(error)
9578
+ message: errorText(error)
9411
9579
  }));
9580
+ else console.error(errorText(error));
9412
9581
  await exitAfterDrain(1);
9413
9582
  return;
9414
9583
  }
9415
9584
  if (asJson) install_emit(messaging.Pr.ok('uninstall', 'uninstalled', {
9416
- browser: target,
9417
- all
9585
+ browsers: browserList,
9586
+ all: removeAll
9418
9587
  }));
9419
9588
  });
9420
9589
  }
@@ -9424,7 +9593,7 @@ Cross-browser compatibility
9424
9593
  'Manifest file not found'
9425
9594
  ];
9426
9595
  function registerPreviewCommand(program) {
9427
- program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', '\nAdditional option:\n --no-browser do not launch the browser\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`--browser <${NO_SAFARI_BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, options, command)=>{
9596
+ program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', '\nAdditional option:\n --no-browser do not launch the browser\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`--browser <${NO_SAFARI_BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--output-path <dir>', 'path to an existing unpacked extension directory. Defaults to dist/<browser> when available').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, options, command)=>{
9428
9597
  const { browser = 'chromium', ...previewOptions } = options;
9429
9598
  if (previewOptions.debug || previewOptions.author || previewOptions.authorMode) {
9430
9599
  process.env.EXTENSION_DEBUG = '1';
@@ -9432,6 +9601,7 @@ Cross-browser compatibility
9432
9601
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
9433
9602
  }
9434
9603
  const asJson = 'json' === previewOptions.output;
9604
+ if (asJson) process.env.EXTENSION_OUTPUT = 'json';
9435
9605
  const emit = (frame)=>{
9436
9606
  console.log(JSON.stringify(frame));
9437
9607
  };
@@ -9480,6 +9650,7 @@ Cross-browser compatibility
9480
9650
  port: previewOptions.port,
9481
9651
  noBrowser: await resolveNoBrowser(pathOrRemoteUrl || process.cwd(), 'preview'),
9482
9652
  extensions: parseExtensionsList(previewOptions.extensions),
9653
+ outputPath: previewOptions.outputPath,
9483
9654
  logLevel: logsOption || previewOptions.logLevel || void 0,
9484
9655
  logContexts,
9485
9656
  logFormat: previewOptions.logFormat,
@@ -9683,10 +9854,12 @@ Cross-browser compatibility
9683
9854
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
9684
9855
  }
9685
9856
  const asJson = 'json' === resolveOutputFormat(startOptions);
9857
+ if (asJson) process.env.EXTENSION_OUTPUT = 'json';
9686
9858
  const list = vendors(browser);
9687
9859
  let unsupportedBrowser = '';
9688
9860
  const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
9689
9861
  unsupportedBrowser = invalid;
9862
+ if (asJson) return;
9690
9863
  console.error(unsupportedBrowserFlag(invalid, supported));
9691
9864
  });
9692
9865
  if (!vendorsAreSupported) start_failAndExit(asJson, 'usage', {
@@ -9694,10 +9867,10 @@ Cross-browser compatibility
9694
9867
  message: `Unsupported browser: ${unsupportedBrowser}`
9695
9868
  });
9696
9869
  if (list.some(isSafariVendor)) {
9697
- console.error(safariCommandNotSupported('start'));
9870
+ if (!asJson) console.error(safariCommandNotSupported('start'));
9698
9871
  start_failAndExit(asJson, 'usage', {
9699
- code: messaging.Lp.E_UNSUPPORTED_BROWSER,
9700
- message: 'Safari targets are not supported by start.'
9872
+ code: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET,
9873
+ message: 'Safari is not supported by start.'
9701
9874
  });
9702
9875
  }
9703
9876
  if (startOptions.wait) {