extension 4.1.25 → 4.1.26

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
@@ -71,14 +71,27 @@ var __webpack_modules__ = {
71
71
  return '';
72
72
  }
73
73
  }
74
+ function registeredDirectoryPath(dir, platform) {
75
+ const absolute = node_path__rspack_import_2.resolve(dir);
76
+ if ('win32' === platform) return absolute;
77
+ try {
78
+ return node_fs__rspack_import_1.realpathSync.native(absolute);
79
+ } catch {
80
+ return absolute;
81
+ }
82
+ }
83
+ function upperCaseDriveLetter(windowsPath) {
84
+ return /^[a-z]:/.test(windowsPath) ? windowsPath[0].toUpperCase() + windowsPath.slice(1) : windowsPath;
85
+ }
86
+ function chromiumExtensionIdFromRegisteredPath(registeredPath, platform = process.platform) {
87
+ const bytes = 'win32' === platform ? Buffer.from(upperCaseDriveLetter(registeredPath.replace(/\//g, '\\')), 'utf16le') : Buffer.from(registeredPath, 'utf8');
88
+ const digest = (0, node_crypto__rspack_import_0.createHash)('sha256').update(bytes).digest().subarray(0, 16);
89
+ return encodeChromiumExtensionIdFromDigest(digest);
90
+ }
74
91
  function deriveChromiumExtensionIdFromPath(extensionPath) {
75
92
  if (!extensionPath || 'string' != typeof extensionPath) return '';
76
93
  try {
77
- const absolute = node_path__rspack_import_2.resolve(extensionPath);
78
- const isWindows = 'win32' === process.platform;
79
- const seedBuffer = isWindows ? Buffer.from(absolute.replace(/\//g, '\\'), 'utf16le') : Buffer.from(absolute, 'utf8');
80
- const digest = (0, node_crypto__rspack_import_0.createHash)('sha256').update(seedBuffer).digest().subarray(0, 16);
81
- return encodeChromiumExtensionIdFromDigest(digest);
94
+ return chromiumExtensionIdFromRegisteredPath(registeredDirectoryPath(extensionPath, process.platform), process.platform);
82
95
  } catch {
83
96
  return '';
84
97
  }
@@ -275,6 +288,8 @@ var __webpack_modules__ = {
275
288
  'firefox',
276
289
  'waterfox',
277
290
  'librewolf',
291
+ 'zen',
292
+ 'floorp',
278
293
  'gecko-based',
279
294
  'firefox-based'
280
295
  ]);
@@ -284,8 +299,15 @@ var __webpack_modules__ = {
284
299
  function isFirefoxBrowser(browser) {
285
300
  return FIREFOX_BROWSERS.has(String(browser));
286
301
  }
302
+ const EMULATOR_BROWSERS = new Set([
303
+ 'chromium-emulator'
304
+ ]);
305
+ function isEmulatorBrowser(browser) {
306
+ return EMULATOR_BROWSERS.has(String(browser));
307
+ }
287
308
  __webpack_require__.d(__webpack_exports__, {
288
309
  M_: ()=>isFirefoxBrowser,
310
+ eP: ()=>isEmulatorBrowser,
289
311
  rG: ()=>isChromiumBrowser
290
312
  });
291
313
  },
@@ -1139,7 +1161,7 @@ var __webpack_modules__ = {
1139
1161
  const root = String(cacheRoot || '').trim();
1140
1162
  if (!root) return {};
1141
1163
  if ('safari' === browser || 'webkit-based' === browser) return {};
1142
- if ('brave' === browser || 'opera' === browser || 'vivaldi' === browser || 'yandex' === browser || 'waterfox' === browser || 'librewolf' === browser) return {};
1164
+ if ('brave' === browser || 'opera' === browser || 'vivaldi' === browser || 'yandex' === browser || 'waterfox' === browser || 'librewolf' === browser || 'zen' === browser || 'floorp' === browser) return {};
1143
1165
  if ('chrome' === browser) return {
1144
1166
  PUPPETEER_CACHE_DIR: node_path__rspack_import_1.join(root, 'chrome', 'chrome')
1145
1167
  };
@@ -2032,13 +2054,113 @@ var __webpack_modules__ = {
2032
2054
  const external_wsl_support_namespaceObject = require("wsl-support");
2033
2055
  },
2034
2056
  "./browsers/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2035
- var _browsers_lib_browser_family__rspack_import_0 = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
2036
- var _browsers_lib_output_binaries_resolver__rspack_import_1 = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
2037
- var _browsers_lib_runtime_options__rspack_import_10 = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
2038
- var _run_chromium_chromium_context__rspack_import_8 = __webpack_require__("./browsers/run-chromium/chromium-context/index.ts");
2039
- var _run_chromium_chromium_launch__rspack_import_2 = __webpack_require__("./browsers/run-chromium/chromium-launch/index.ts");
2040
- var _run_firefox_firefox_context__rspack_import_9 = __webpack_require__("./browsers/run-firefox/firefox-context/index.ts");
2041
- var _run_firefox_firefox_launch__rspack_import_3 = __webpack_require__("./browsers/run-firefox/firefox-launch/index.ts");
2057
+ __webpack_require__.d(__webpack_exports__, {
2058
+ launchBrowser: ()=>launchBrowser
2059
+ });
2060
+ var browser_family = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
2061
+ var output_binaries_resolver = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
2062
+ var runtime_options = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
2063
+ var chromium_context = __webpack_require__("./browsers/run-chromium/chromium-context/index.ts");
2064
+ var chromium_launch = __webpack_require__("./browsers/run-chromium/chromium-launch/index.ts");
2065
+ var external_node_child_process_ = __webpack_require__("node:child_process");
2066
+ var external_pintor_ = __webpack_require__("pintor");
2067
+ var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
2068
+ var emulator_session = __webpack_require__("./helpers/emulator-session.ts");
2069
+ var messaging = __webpack_require__("./helpers/messaging.ts");
2070
+ function emulatorViewerUrlLine(url) {
2071
+ return `${(0, messaging.Pl)('info')} Emulated Chromium runs in a web page. Open this address to load your extension:\n${external_pintor_default().underline(url)}`;
2072
+ }
2073
+ function emulatorLogsLimitLine() {
2074
+ return `${(0, messaging.Pl)('warn')} --logs has no effect here: ${emulator_session.fg}`;
2075
+ }
2076
+ function openCommandFor(url, platform = process.platform) {
2077
+ if ('darwin' === platform) return {
2078
+ command: 'open',
2079
+ args: [
2080
+ url
2081
+ ]
2082
+ };
2083
+ if ('win32' === platform) return {
2084
+ command: 'rundll32',
2085
+ args: [
2086
+ 'url.dll,FileProtocolHandler',
2087
+ url
2088
+ ]
2089
+ };
2090
+ return {
2091
+ command: 'xdg-open',
2092
+ args: [
2093
+ url
2094
+ ]
2095
+ };
2096
+ }
2097
+ function engineVersionUrl(viewerUrl) {
2098
+ try {
2099
+ const parsed = new URL(viewerUrl);
2100
+ const base = parsed.pathname.endsWith('/') ? parsed.pathname : `${parsed.pathname.replace(/[^/]*$/, '')}`;
2101
+ return `${parsed.origin}${base}version.json`;
2102
+ } catch {
2103
+ return null;
2104
+ }
2105
+ }
2106
+ async function probeEngineOrigin(viewerUrl, fetchImpl = (url, init)=>fetch(url, init), timeoutMs = 3000) {
2107
+ const url = engineVersionUrl(viewerUrl);
2108
+ if (!url) return 'unknown';
2109
+ const controller = new AbortController();
2110
+ const timer = setTimeout(()=>controller.abort(), timeoutMs);
2111
+ try {
2112
+ const response = await fetchImpl(url, {
2113
+ signal: controller.signal
2114
+ });
2115
+ if (429 === response.status) return 'throttled';
2116
+ if (503 === response.status) return 'held';
2117
+ if (200 !== response.status) return 'unknown';
2118
+ const report = await response.json();
2119
+ return report && 'held' === report.hold ? 'held' : 'open';
2120
+ } catch {
2121
+ return 'unknown';
2122
+ } finally{
2123
+ clearTimeout(timer);
2124
+ }
2125
+ }
2126
+ function engineOriginLine(verdict) {
2127
+ if ('held' === verdict) return `${(0, messaging.Pl)('warn')} emulated Chromium is not open to the public yet, so this address answers 503 until it is. Run this project with --browser=chrome in the meantime.`;
2128
+ if ('throttled' === verdict) return `${(0, messaging.Pl)('warn')} the emulated Chromium origin is rate limiting this address (HTTP 429). Wait a minute, then run extension dev again, or run this project with --browser=chrome.`;
2129
+ return null;
2130
+ }
2131
+ function openInDefaultBrowser(url) {
2132
+ const { command, args } = openCommandFor(url);
2133
+ try {
2134
+ const child = (0, external_node_child_process_.spawn)(command, args, {
2135
+ detached: true,
2136
+ stdio: 'ignore',
2137
+ windowsHide: true
2138
+ });
2139
+ child.on('error', ()=>{});
2140
+ child.unref();
2141
+ } catch {
2142
+ return;
2143
+ }
2144
+ }
2145
+ async function launchEmulator(opts, opener = openInDefaultBrowser, probe = probeEngineOrigin) {
2146
+ if ('development' !== (opts.mode || 'production')) throw new Error('emulated Chromium needs the dev server that serves the files the page reads. Run extension dev instead.');
2147
+ const url = opts.emulatorViewerUrl;
2148
+ if (!url) throw new Error('this version of extension-develop does not serve emulated Chromium. Update extension-develop so it matches the CLI, then run extension dev again.');
2149
+ console.log(emulatorViewerUrlLine(url));
2150
+ const willOpen = !opts.noOpen && !opts.dryRun;
2151
+ const verdict = willOpen ? await probe(url) : 'unknown';
2152
+ const originLine = engineOriginLine(verdict);
2153
+ if (originLine) console.warn(originLine);
2154
+ if (willOpen && !originLine) opener(url);
2155
+ const logsRequested = Boolean(opts.logLevel && 'off' !== opts.logLevel);
2156
+ return {
2157
+ async enableUnifiedLogging () {
2158
+ if (logsRequested) console.warn(emulatorLogsLimitLine());
2159
+ }
2160
+ };
2161
+ }
2162
+ var firefox_context = __webpack_require__("./browsers/run-firefox/firefox-context/index.ts");
2163
+ var firefox_launch = __webpack_require__("./browsers/run-firefox/firefox-launch/index.ts");
2042
2164
  __webpack_require__("./browsers/run-only.ts");
2043
2165
  __webpack_require__("./browsers/run-safari/safari-launch/index.ts");
2044
2166
  __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
@@ -2058,11 +2180,12 @@ var __webpack_modules__ = {
2058
2180
  };
2059
2181
  }
2060
2182
  async function launchBrowser(opts) {
2183
+ if ((0, browser_family.eP)(opts.browser)) return launchEmulator(opts);
2061
2184
  const compilationLike = createCompilationLike(opts);
2062
2185
  const mode = opts.mode || 'production';
2063
- (0, _browsers_lib_output_binaries_resolver__rspack_import_1.LB)(compilationLike);
2064
- if ((0, _browsers_lib_browser_family__rspack_import_0.rG)(opts.browser)) return launchChromium(opts, compilationLike, mode);
2065
- if ((0, _browsers_lib_browser_family__rspack_import_0.M_)(opts.browser)) return launchFirefox(opts, compilationLike, mode);
2186
+ (0, output_binaries_resolver.LB)(compilationLike);
2187
+ if ((0, browser_family.rG)(opts.browser)) return launchChromium(opts, compilationLike, mode);
2188
+ if ((0, browser_family.M_)(opts.browser)) return launchFirefox(opts, compilationLike, mode);
2066
2189
  throw new Error(`Unsupported browser: ${String(opts.browser)}`);
2067
2190
  }
2068
2191
  async function launchChromium(opts, compilationLike, mode) {
@@ -2091,8 +2214,8 @@ var __webpack_modules__ = {
2091
2214
  logTab: opts.logTab,
2092
2215
  logSink: opts.logSink
2093
2216
  };
2094
- const ctx = (0, _run_chromium_chromium_context__rspack_import_8.g)();
2095
- const launcher = new _run_chromium_chromium_launch__rspack_import_2.f(chromiumOpts, ctx);
2217
+ const ctx = (0, chromium_context.g)();
2218
+ const launcher = new chromium_launch.f(chromiumOpts, ctx);
2096
2219
  const enableCdp = 'development' === mode;
2097
2220
  await launcher.runOnce(compilationLike, {
2098
2221
  enableCdpPostLaunch: enableCdp
@@ -2166,9 +2289,9 @@ var __webpack_modules__ = {
2166
2289
  port: opts.port,
2167
2290
  dryRun: opts.dryRun
2168
2291
  };
2169
- const ctx = (0, _run_firefox_firefox_context__rspack_import_9.D)();
2170
- const launcher = new _run_firefox_firefox_launch__rspack_import_3.c(firefoxOpts, ctx);
2171
- const launchRequest = (0, _browsers_lib_runtime_options__rspack_import_10.zU)(pluginOptions, mode, {
2292
+ const ctx = (0, firefox_context.D)();
2293
+ const launcher = new firefox_launch.c(firefoxOpts, ctx);
2294
+ const launchRequest = (0, runtime_options.zU)(pluginOptions, mode, {
2172
2295
  persistProfile: opts.persistProfile,
2173
2296
  geckoBinary: opts.geckoBinary
2174
2297
  });
@@ -2198,9 +2321,6 @@ var __webpack_modules__ = {
2198
2321
  }
2199
2322
  };
2200
2323
  }
2201
- __webpack_require__.d(__webpack_exports__, {
2202
- launchBrowser: ()=>launchBrowser
2203
- });
2204
2324
  },
2205
2325
  "./browsers/run-chromium/cdp/discovery.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2206
2326
  __webpack_require__.d(__webpack_exports__, {
@@ -3836,10 +3956,14 @@ var __webpack_modules__ = {
3836
3956
  var external_node_fs_ = __webpack_require__("node:fs");
3837
3957
  var external_firefox_location2_ = __webpack_require__("firefox-location2");
3838
3958
  var external_firefox_location2_default = /*#__PURE__*/ __webpack_require__.n(external_firefox_location2_);
3959
+ const external_floorp_location_namespaceObject = require("floorp-location");
3960
+ var external_floorp_location_default = /*#__PURE__*/ __webpack_require__.n(external_floorp_location_namespaceObject);
3839
3961
  const external_librewolf_location_namespaceObject = require("librewolf-location");
3840
3962
  var external_librewolf_location_default = /*#__PURE__*/ __webpack_require__.n(external_librewolf_location_namespaceObject);
3841
3963
  const external_waterfox_location_namespaceObject = require("waterfox-location");
3842
3964
  var external_waterfox_location_default = /*#__PURE__*/ __webpack_require__.n(external_waterfox_location_namespaceObject);
3965
+ const external_zen_location_namespaceObject = require("zen-location");
3966
+ var external_zen_location_default = /*#__PURE__*/ __webpack_require__.n(external_zen_location_namespaceObject);
3843
3967
  var messaging = __webpack_require__("./helpers/messaging.ts");
3844
3968
  var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
3845
3969
  var instance_registry = __webpack_require__("./browsers/browsers-lib/instance-registry.ts");
@@ -5582,6 +5706,18 @@ var __webpack_modules__ = {
5582
5706
  });
5583
5707
  const normalized = normalizePath(located);
5584
5708
  if (normalized) browserBinaryLocation = normalized;
5709
+ } else if ('zen' === this.host.browser) {
5710
+ const located = external_zen_location_default()(true, {
5711
+ env: process.env
5712
+ });
5713
+ const normalized = normalizePath(located);
5714
+ if (normalized) browserBinaryLocation = normalized;
5715
+ } else if ('floorp' === this.host.browser) {
5716
+ const located = external_floorp_location_default()(true, {
5717
+ env: process.env
5718
+ });
5719
+ const normalized = normalizePath(located);
5720
+ if (normalized) browserBinaryLocation = normalized;
5585
5721
  } else {
5586
5722
  const cacheRoot = (0, output_binaries_resolver.LB)(compilation);
5587
5723
  const env = {
@@ -6710,6 +6846,32 @@ var __webpack_modules__ = {
6710
6846
  w6: ()=>readBrowserInstall
6711
6847
  });
6712
6848
  },
6849
+ "./helpers/emulator-session.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
6850
+ var _vendors__rspack_import_0 = __webpack_require__("./helpers/vendors.ts");
6851
+ const EMULATOR_LOGS_REFUSAL = 'emulated Chromium runs in a web page, so extension logs has nothing to attach to. Open your browser devtools on that page to read the console.';
6852
+ function emulatorRefusalFor(command) {
6853
+ if ('logs' === command) return EMULATOR_LOGS_REFUSAL;
6854
+ return `emulated Chromium runs in a web page and speaks no debugging protocol, so extension ${command} cannot reach it. Work in the page the dev server printed, or run this project with --browser=chrome.`;
6855
+ }
6856
+ function isEmulatorSession(bridge, projectPath, browser, env = process.env) {
6857
+ if ((0, _vendors__rspack_import_0.CM)(browser) && (0, _vendors__rspack_import_0.hs)(env)) return true;
6858
+ const reader = bridge?.readReadyContractDocument;
6859
+ if ('function' != typeof reader) return false;
6860
+ try {
6861
+ return reader(projectPath, browser)?.engine === 'emulator';
6862
+ } catch {
6863
+ return false;
6864
+ }
6865
+ }
6866
+ function emulatorSessionRefusal(bridge, projectPath, browser, command, env = process.env) {
6867
+ return isEmulatorSession(bridge, projectPath, browser, env) ? emulatorRefusalFor(command) : null;
6868
+ }
6869
+ __webpack_require__.d(__webpack_exports__, {
6870
+ MC: ()=>emulatorSessionRefusal
6871
+ }, {
6872
+ fg: EMULATOR_LOGS_REFUSAL
6873
+ });
6874
+ },
6713
6875
  "./helpers/messaging.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
6714
6876
  var pintor__rspack_import_0 = __webpack_require__("pintor");
6715
6877
  var pintor__rspack_import_0_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_0);
@@ -6821,6 +6983,8 @@ var __webpack_modules__ = {
6821
6983
  'firefox-based',
6822
6984
  'gecko-based',
6823
6985
  'librewolf',
6986
+ 'zen',
6987
+ 'floorp',
6824
6988
  'waterfox'
6825
6989
  ]);
6826
6990
  function artifactNoun(browser) {
@@ -7011,6 +7175,134 @@ var __webpack_modules__ = {
7011
7175
  Sc: fmt
7012
7176
  });
7013
7177
  },
7178
+ "./helpers/vendors.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
7179
+ const EMULATOR_BROWSER_TARGET = 'chromium-emulator';
7180
+ function isEmulatorLaneEnabled(env = process.env) {
7181
+ const value = String(env.EXTENSION_EXPERIMENTAL_EMULATOR || '').trim().toLowerCase();
7182
+ return '1' === value || 'true' === value;
7183
+ }
7184
+ function isEmulatorVendor(value) {
7185
+ return value === EMULATOR_BROWSER_TARGET;
7186
+ }
7187
+ function isSafariVendor(value) {
7188
+ return 'safari' === value || 'webkit-based' === value;
7189
+ }
7190
+ const SUPPORTED_BROWSER_TARGETS = [
7191
+ 'chrome',
7192
+ 'chromium',
7193
+ 'edge',
7194
+ 'firefox',
7195
+ 'brave',
7196
+ 'opera',
7197
+ 'vivaldi',
7198
+ 'yandex',
7199
+ 'waterfox',
7200
+ 'librewolf',
7201
+ 'zen',
7202
+ 'floorp',
7203
+ 'chromium-based',
7204
+ 'gecko-based',
7205
+ 'firefox-based',
7206
+ 'safari',
7207
+ 'webkit-based'
7208
+ ];
7209
+ const BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.join(' | ');
7210
+ function supportedBrowserTargets(env = process.env) {
7211
+ return isEmulatorLaneEnabled(env) ? [
7212
+ ...SUPPORTED_BROWSER_TARGETS,
7213
+ EMULATOR_BROWSER_TARGET
7214
+ ] : [
7215
+ ...SUPPORTED_BROWSER_TARGETS
7216
+ ];
7217
+ }
7218
+ const SESSION_BROWSER_TARGETS_HELP = "chrome | chromium | edge | firefox | safari";
7219
+ const NO_SAFARI_BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.filter((target)=>!isSafariVendor(target)).join(' | ');
7220
+ function parseOptionalBoolean(value) {
7221
+ if (void 0 === value) return true;
7222
+ const normalized = String(value).trim().toLowerCase();
7223
+ return ![
7224
+ 'false',
7225
+ '0',
7226
+ 'no',
7227
+ 'off'
7228
+ ].includes(normalized);
7229
+ }
7230
+ const vendors = (browser)=>{
7231
+ const value = browser ?? 'chromium';
7232
+ return 'all' === value ? [
7233
+ 'chrome',
7234
+ 'edge',
7235
+ 'firefox'
7236
+ ] : String(value).split(',').map((part)=>part.trim()).filter(Boolean);
7237
+ };
7238
+ const MANAGED_INSTALL_TARGETS = [
7239
+ 'chrome',
7240
+ 'chromium',
7241
+ 'edge',
7242
+ 'firefox',
7243
+ 'chromium-based',
7244
+ 'gecko-based',
7245
+ 'firefox-based'
7246
+ ];
7247
+ const MANAGED_INSTALL_TARGETS_HELP = [
7248
+ ...MANAGED_INSTALL_TARGETS,
7249
+ 'all'
7250
+ ].join(' | ');
7251
+ const MANAGED_INSTALL_BINARIES = [
7252
+ 'chrome',
7253
+ 'chromium',
7254
+ 'edge',
7255
+ 'firefox'
7256
+ ];
7257
+ const installTargets = (browser)=>'all' === browser ? [
7258
+ ...MANAGED_INSTALL_BINARIES
7259
+ ] : vendors(browser);
7260
+ function validateVendors(vendorsList, onInvalid, options = {}) {
7261
+ const supported = false === options.allowEmulator ? [
7262
+ ...SUPPORTED_BROWSER_TARGETS
7263
+ ] : supportedBrowserTargets();
7264
+ for (const v of vendorsList)if (!supported.includes(v)) {
7265
+ onInvalid(v, supported);
7266
+ return false;
7267
+ }
7268
+ return true;
7269
+ }
7270
+ const MANAGED_INSTALL_TARGET_SET = new Set(MANAGED_INSTALL_TARGETS);
7271
+ const SUPPORTED_BROWSER_TARGET_SET = new Set(SUPPORTED_BROWSER_TARGETS);
7272
+ function classifyManagedInstallTarget(name) {
7273
+ const value = String(name || '').trim().toLowerCase();
7274
+ if (!value) return 'unknown';
7275
+ if (MANAGED_INSTALL_TARGET_SET.has(value)) return 'managed';
7276
+ if (SUPPORTED_BROWSER_TARGET_SET.has(value)) return 'not-installable';
7277
+ return 'unknown';
7278
+ }
7279
+ function firstNonManagedInstallTarget(targetsList) {
7280
+ for (const name of targetsList){
7281
+ const kind = classifyManagedInstallTarget(name);
7282
+ if ('managed' !== kind) return {
7283
+ name,
7284
+ kind
7285
+ };
7286
+ }
7287
+ return null;
7288
+ }
7289
+ __webpack_require__.d(__webpack_exports__, {
7290
+ $q: ()=>isSafariVendor,
7291
+ CM: ()=>isEmulatorVendor,
7292
+ RY: ()=>firstNonManagedInstallTarget,
7293
+ hs: ()=>isEmulatorLaneEnabled,
7294
+ sJ: ()=>parseOptionalBoolean,
7295
+ sS: ()=>validateVendors
7296
+ }, {
7297
+ DB: NO_SAFARI_BROWSER_TARGETS_HELP,
7298
+ I9: BROWSER_TARGETS_HELP,
7299
+ L_: MANAGED_INSTALL_TARGETS,
7300
+ OB: installTargets,
7301
+ Xf: SESSION_BROWSER_TARGETS_HELP,
7302
+ b_: MANAGED_INSTALL_TARGETS_HELP,
7303
+ oJ: vendors
7304
+ });
7305
+ },
7014
7306
  "./index.ts" (__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
7015
7307
  const MIN_NODE_MAJOR = 22;
7016
7308
  const MIN_NODE_MINOR = 12;
@@ -7078,6 +7370,7 @@ var __webpack_modules__ = {
7078
7370
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_);
7079
7371
  var external_node_path_ = __webpack_require__("node:path");
7080
7372
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_);
7373
+ var emulator_session = __webpack_require__("./helpers/emulator-session.ts");
7081
7374
  var external_pintor_ = __webpack_require__("pintor");
7082
7375
  var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
7083
7376
  var browser_install_outcome = __webpack_require__("./helpers/browser-install-outcome.ts");
@@ -8406,6 +8699,7 @@ Build options
8406
8699
  - ${messages_code('--zip-source')} ${messages_arg('[boolean]')} Include source files in ZIP
8407
8700
  - ${messages_code('--zip-filename')} ${messages_arg('<name>')} Custom ZIP filename
8408
8701
  - ${messages_code('--no-addon-lint')} Skip the addons.mozilla.org lint of Firefox builds (runs when addons-linter is installed)
8702
+ - ${messages_code('--no-minify')} Ship readable first-party code (the default for ${messages_code('--browser=opera')}, whose store rejects minified code)
8409
8703
 
8410
8704
  ${external_pintor_default().underline('Centralized logger (terminal output)')}
8411
8705
  - The manager extension embeds a centralized logger that streams events to the CLI.
@@ -8922,96 +9216,7 @@ Cross-browser compatibility
8922
9216
  function sessionLogsPath(bridge, projectPath, browser) {
8923
9217
  return sessionFilePath(bridge, 'logsPath', projectPath, browser, 'logs.ndjson');
8924
9218
  }
8925
- function isSafariVendor(value) {
8926
- return 'safari' === value || 'webkit-based' === value;
8927
- }
8928
- const SUPPORTED_BROWSER_TARGETS = [
8929
- 'chrome',
8930
- 'chromium',
8931
- 'edge',
8932
- 'firefox',
8933
- 'brave',
8934
- 'opera',
8935
- 'vivaldi',
8936
- 'yandex',
8937
- 'waterfox',
8938
- 'librewolf',
8939
- 'chromium-based',
8940
- 'gecko-based',
8941
- 'firefox-based',
8942
- 'safari',
8943
- 'webkit-based'
8944
- ];
8945
- const BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.join(' | ');
8946
- const SESSION_BROWSER_TARGETS_HELP = "chrome | chromium | edge | firefox | safari";
8947
- const NO_SAFARI_BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.filter((target)=>!isSafariVendor(target)).join(' | ');
8948
- function parseOptionalBoolean(value) {
8949
- if (void 0 === value) return true;
8950
- const normalized = String(value).trim().toLowerCase();
8951
- return ![
8952
- 'false',
8953
- '0',
8954
- 'no',
8955
- 'off'
8956
- ].includes(normalized);
8957
- }
8958
- const vendors = (browser)=>{
8959
- const value = browser ?? 'chromium';
8960
- return 'all' === value ? [
8961
- 'chrome',
8962
- 'edge',
8963
- 'firefox'
8964
- ] : String(value).split(',').map((part)=>part.trim()).filter(Boolean);
8965
- };
8966
- const MANAGED_INSTALL_TARGETS = [
8967
- 'chrome',
8968
- 'chromium',
8969
- 'edge',
8970
- 'firefox',
8971
- 'chromium-based',
8972
- 'gecko-based',
8973
- 'firefox-based'
8974
- ];
8975
- const MANAGED_INSTALL_TARGETS_HELP = [
8976
- ...MANAGED_INSTALL_TARGETS,
8977
- 'all'
8978
- ].join(' | ');
8979
- const MANAGED_INSTALL_BINARIES = [
8980
- 'chrome',
8981
- 'chromium',
8982
- 'edge',
8983
- 'firefox'
8984
- ];
8985
- const installTargets = (browser)=>'all' === browser ? [
8986
- ...MANAGED_INSTALL_BINARIES
8987
- ] : vendors(browser);
8988
- function validateVendors(vendorsList, onInvalid) {
8989
- const supported = SUPPORTED_BROWSER_TARGETS;
8990
- for (const v of vendorsList)if (!supported.includes(v)) {
8991
- onInvalid(v, supported);
8992
- return false;
8993
- }
8994
- return true;
8995
- }
8996
- const MANAGED_INSTALL_TARGET_SET = new Set(MANAGED_INSTALL_TARGETS);
8997
- const SUPPORTED_BROWSER_TARGET_SET = new Set(SUPPORTED_BROWSER_TARGETS);
8998
- function classifyManagedInstallTarget(name) {
8999
- const value = String(name || '').trim().toLowerCase();
9000
- if (!value) return 'unknown';
9001
- if (MANAGED_INSTALL_TARGET_SET.has(value)) return 'managed';
9002
- if (SUPPORTED_BROWSER_TARGET_SET.has(value)) return 'not-installable';
9003
- return 'unknown';
9004
- }
9005
- function firstNonManagedInstallTarget(targetsList) {
9006
- for (const name of targetsList){
9007
- const kind = classifyManagedInstallTarget(name);
9008
- if ('managed' !== kind) return {
9009
- name,
9010
- kind
9011
- };
9012
- }
9013
- return null;
9014
- }
9219
+ var vendors = __webpack_require__("./helpers/vendors.ts");
9015
9220
  function parseLogSinceLocal(value) {
9016
9221
  if (null == value || '' === value) return null;
9017
9222
  if ('number' == typeof value) return Number.isFinite(value) ? {
@@ -9131,7 +9336,7 @@ Cross-browser compatibility
9131
9336
  }
9132
9337
  }
9133
9338
  function registerLogsCommand(program) {
9134
- program.command('logs').arguments('[project-path]').usage('[project-path] [options]').description(commandDescriptions.logs).option(`--browser <${SESSION_BROWSER_TARGETS_HELP}>`, 'which dist/extension-js/<browser> to read. Defaults to `chromium`').option('--follow', 'stream live via the control channel instead of printing and exiting').option('--context <list>', 'comma-separated contexts (background, content, popup, options, sidebar, devtools, page)').option('--level <off|error|warn|info|debug|trace|all>', 'minimum severity to show. Defaults to `all`').option('--signals-only', '[experimental] show only structured dx.signal diagnostics. No emitter ships yet, so this currently prints nothing').option('--since <seq|iso>', 'only show events after this sequence number or ISO timestamp').option('--url <glob|substring>', 'only events whose url/hostname matches (glob with * or plain substring)').option('--tab <id>', 'only events from this tab id').option('--output <pretty|json|ndjson>', 'output format. Defaults to pretty on a TTY, ndjson when piped').action(async (projectPathArg, options)=>{
9339
+ program.command('logs').arguments('[project-path]').usage('[project-path] [options]').description(commandDescriptions.logs).option(`--browser <${vendors.Xf}>`, 'which dist/extension-js/<browser> to read. Defaults to `chromium`').option('--follow', 'stream live via the control channel instead of printing and exiting').option('--context <list>', 'comma-separated contexts (background, content, popup, options, sidebar, devtools, page)').option('--level <off|error|warn|info|debug|trace|all>', 'minimum severity to show. Defaults to `all`').option('--signals-only', '[experimental] show only structured dx.signal diagnostics. No emitter ships yet, so this currently prints nothing').option('--since <seq|iso>', 'only show events after this sequence number or ISO timestamp').option('--url <glob|substring>', 'only events whose url/hostname matches (glob with * or plain substring)').option('--tab <id>', 'only events from this tab id').option('--output <pretty|json|ndjson>', 'output format. Defaults to pretty on a TTY, ndjson when piped').action(async (projectPathArg, options)=>{
9135
9340
  const bridge = await loadExtensionDevelopBridgeModule();
9136
9341
  const projectPath = resolveSessionProjectPath(bridge, projectPathArg);
9137
9342
  const browser = options.browser || 'chromium';
@@ -9148,6 +9353,16 @@ Cross-browser compatibility
9148
9353
  }));
9149
9354
  process.exit(1);
9150
9355
  }
9356
+ const emulatorRefusal = (0, emulator_session.MC)(bridge, projectPath, browser, 'logs');
9357
+ if (emulatorRefusal) {
9358
+ console.error(emulatorRefusal);
9359
+ if ('pretty' !== format) writeFrame(messaging.Pr.fail('logs', 'failed', {
9360
+ code: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET,
9361
+ message: emulatorRefusal,
9362
+ name: 'CliError'
9363
+ }));
9364
+ process.exit(1);
9365
+ }
9151
9366
  const matches = makeFilter(options, since ?? null, helpers);
9152
9367
  if (options.signalsOnly) console.error("extension logs --signals-only: no signals emitter ships in this build, so dev sessions record no dx.signal events and this filter will print nothing.");
9153
9368
  if (options.follow) return void await followLogs(projectPath, browser, format, matches);
@@ -9439,6 +9654,11 @@ Cross-browser compatibility
9439
9654
  plain: refusal.plain,
9440
9655
  hint: refusal.hint
9441
9656
  });
9657
+ const emulatorRefusal = (0, emulator_session.MC)(bridge, projectPath, browser, input.command);
9658
+ if (emulatorRefusal) fail(emulatorRefusal, {
9659
+ ...outputFrame,
9660
+ code: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET
9661
+ });
9442
9662
  const ready = readReadyContract(projectPath, browser);
9443
9663
  if (!ready) fail(`No active control channel found for ${browser}. Looked at ${sessionReadyPath(bridge, projectPath, browser)}. Run \`extension dev --browser=${browser} ${unlockFlag}\` first.`, {
9444
9664
  ...outputFrame,
@@ -9501,7 +9721,7 @@ Cross-browser compatibility
9501
9721
  if (null != opts.tab && '' !== opts.tab) target.tabId = Number(opts.tab);
9502
9722
  return target;
9503
9723
  }
9504
- const commonOptions = (cmd)=>cmd.option(`--browser <${SESSION_BROWSER_TARGETS_HELP}>`, 'which session to target (default chromium)').option('--timeout <ms>', 'command timeout in milliseconds (default 5000)').option('--output <pretty|json>', 'output format (default pretty)');
9724
+ const commonOptions = (cmd)=>cmd.option(`--browser <${vendors.Xf}>`, 'which session to target (default chromium)').option('--timeout <ms>', 'command timeout in milliseconds (default 5000)').option('--output <pretty|json>', 'output format (default pretty)');
9505
9725
  function registerActCommands(program) {
9506
9726
  commonOptions(program.command('eval').arguments('<expression> [project-path]').description(commandDescriptions.eval).option('--context <background|popup|options|sidebar|devtools|newtab|history|bookmarks|content|page>', 'target context (default background). Extension pages (popup/options/sidebar/devtools/newtab/history/bookmarks) answer via their own in-page relay and must be open').option('--url <glob|substring>', 'for content/page: document to target (resolved to its tab)').option('--tab <id>', 'for content/page: a specific tab (default: the --url match, else the active tab)')).action(async (expression, projectPathArg, opts)=>{
9507
9727
  await runCommand({
@@ -9773,15 +9993,15 @@ Cross-browser compatibility
9773
9993
  };
9774
9994
  }
9775
9995
  function registerBuildCommand(program) {
9776
- 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('--addon-lint [boolean]', 'check Firefox builds against addons.mozilla.org rules with addons-linter when it is installed. Findings print as warnings. Defaults to `true`', parseOptionalBoolean).option('--no-addon-lint', 'skip the addons.mozilla.org lint of Firefox builds').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 shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').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: cliBrowser, ...buildOptions })=>{
9996
+ program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${vendors.I9}>`, '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`', vendors.sJ).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`', vendors.sJ).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', vendors.sJ).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`', vendors.sJ).option('--addon-lint [boolean]', 'check Firefox builds against addons.mozilla.org rules with addons-linter when it is installed. Findings print as warnings. Defaults to `true`', vendors.sJ).option('--no-addon-lint', 'skip the addons.mozilla.org lint of Firefox builds').option('--minify [boolean]', 'minify first-party code in production builds. Defaults to `true`, and to `false` for `opera`, whose store rejects minified code', vendors.sJ).option('--no-minify', 'ship readable first-party code, the Opera Add-ons review requirement').option('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).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`', vendors.sJ).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 shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').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`', vendors.sJ).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: cliBrowser, ...buildOptions })=>{
9777
9997
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'build') ?? 'chromium';
9778
9998
  if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
9779
9999
  process.env.EXTENSION_DEBUG = '1';
9780
10000
  process.env.EXTENSION_AUTHOR_MODE = 'true';
9781
10001
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
9782
10002
  }
9783
- const list = vendors(browser);
9784
- const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
10003
+ const list = (0, vendors.oJ)(browser);
10004
+ const vendorsAreSupported = (0, vendors.sS)(list, (invalid, supported)=>{
9785
10005
  console.error(unsupportedBrowserFlag(invalid, supported));
9786
10006
  });
9787
10007
  if (!vendorsAreSupported) process.exit(1);
@@ -9817,7 +10037,7 @@ Cross-browser compatibility
9817
10037
  ]
9818
10038
  ].filter(([, value])=>void 0 !== value && false !== value).map(([flag])=>flag);
9819
10039
  if (void 0 !== buildOptions.macosOnly) safariOnlyFlags.push('--macos-only');
9820
- if (safariOnlyFlags.length > 0 && !list.some(isSafariVendor)) {
10040
+ if (safariOnlyFlags.length > 0 && !list.some(vendors.$q)) {
9821
10041
  console.error(safariOnlyOption(safariOnlyFlags));
9822
10042
  process.exit(1);
9823
10043
  }
@@ -9826,7 +10046,7 @@ Cross-browser compatibility
9826
10046
  process.exit(1);
9827
10047
  }
9828
10048
  let safariPackagingEnabled = true;
9829
- if (list.some(isSafariVendor)) {
10049
+ if (list.some(vendors.$q)) {
9830
10050
  const preflight = (0, safari_launch.QW)();
9831
10051
  if ('fatal' === preflight.severity) {
9832
10052
  console.error(preflight.message);
@@ -9854,6 +10074,7 @@ Cross-browser compatibility
9854
10074
  zipFilename: buildOptions.zipFilename,
9855
10075
  silent: buildOptions.silent,
9856
10076
  addonLint: buildOptions.addonLint,
10077
+ minify: buildOptions.minify,
9857
10078
  install: buildOptions.install,
9858
10079
  extensions: parseExtensionsList(buildOptions.extensions),
9859
10080
  mode,
@@ -9939,7 +10160,7 @@ Cross-browser compatibility
9939
10160
  return messaging.Lp.E_INTERNAL;
9940
10161
  }
9941
10162
  function registerCreateCommand(program) {
9942
- program.command('create').arguments('<project-name|project-path>').usage('<project-name|project-path> [options]').description(commandDescriptions.create).option('-t, --template <template-name>', `catalog name, GitHub URL, or ZIP URL to scaffold from; every catalog name is listed below (default: ${DEFAULT_TEMPLATE})`).option('--install [boolean]', 'whether or not to install the dependencies after creating the project (disabled by default, pass --install to opt in)', parseOptionalBoolean, false).option('--source <source>', 'attribution tag for where this create was initiated (e.g. cli, templates); recorded in anonymous telemetry only').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addHelpText('after', renderCreateTemplateHelp()).action(async (pathOrRemoteUrl, { template, install, output })=>{
10163
+ program.command('create').arguments('<project-name|project-path>').usage('<project-name|project-path> [options]').description(commandDescriptions.create).option('-t, --template <template-name>', `catalog name, GitHub URL, or ZIP URL to scaffold from; every catalog name is listed below (default: ${DEFAULT_TEMPLATE})`).option('--install [boolean]', 'whether or not to install the dependencies after creating the project (disabled by default, pass --install to opt in)', vendors.sJ, false).option('--source <source>', 'attribution tag for where this create was initiated (e.g. cli, templates); recorded in anonymous telemetry only').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addHelpText('after', renderCreateTemplateHelp()).action(async (pathOrRemoteUrl, { template, install, output })=>{
9943
10164
  const asJson = isJsonOutput({
9944
10165
  output
9945
10166
  });
@@ -10419,7 +10640,7 @@ Cross-browser compatibility
10419
10640
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
10420
10641
  }
10421
10642
  function registerDevCommand(program) {
10422
- program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the dev server still starts\n --no-reload emit a dev-mode dist without the content-script reload runtime, tabs need a manual reload to see changes\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).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(`-b, --browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').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 shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').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('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').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('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).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()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
10643
+ program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the dev server still starts\n --no-reload emit a dev-mode dist without the content-script reload runtime, tabs need a manual reload to see changes\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).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(`-b, --browser <${vendors.I9}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').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 shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').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`', vendors.sJ).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').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('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', vendors.sJ).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).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()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
10423
10644
  const { browser: cliBrowser, ...devOptions } = options;
10424
10645
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'dev') ?? 'chromium';
10425
10646
  if (devOptions.debug || devOptions.author || devOptions.authorMode) {
@@ -10442,9 +10663,9 @@ Cross-browser compatibility
10442
10663
  }
10443
10664
  setupParentWatchdog(parentPid);
10444
10665
  }
10445
- const list = vendors(browser);
10666
+ const list = (0, vendors.oJ)(browser);
10446
10667
  let unsupportedBrowser = '';
10447
- const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
10668
+ const vendorsAreSupported = (0, vendors.sS)(list, (invalid, supported)=>{
10448
10669
  unsupportedBrowser = invalid;
10449
10670
  console.error(unsupportedBrowserFlag(invalid, supported));
10450
10671
  });
@@ -10476,7 +10697,7 @@ Cross-browser compatibility
10476
10697
  ]
10477
10698
  ].filter(([, value])=>void 0 !== value && false !== value).map(([flag])=>flag);
10478
10699
  if (void 0 !== opts.macosOnly) safariOnlyFlags.push('--macos-only');
10479
- if (safariOnlyFlags.length > 0 && !list.some(isSafariVendor)) {
10700
+ if (safariOnlyFlags.length > 0 && !list.some(vendors.$q)) {
10480
10701
  console.error(safariOnlyOption(safariOnlyFlags));
10481
10702
  failAndExit(asJson, 'usage', {
10482
10703
  code: messaging.Lp.E_INVALID_OPTION,
@@ -10490,7 +10711,7 @@ Cross-browser compatibility
10490
10711
  message: `--bundle-id expects a reverse-DNS identifier, got: ${opts.bundleId}`
10491
10712
  });
10492
10713
  }
10493
- if (list.some(isSafariVendor)) {
10714
+ if (list.some(vendors.$q)) {
10494
10715
  const issue = (0, safari_launch.iF)();
10495
10716
  if (issue) {
10496
10717
  console.error(issue);
@@ -10666,6 +10887,15 @@ Cross-browser compatibility
10666
10887
  detail: `multiple live sessions found (${sessionBrowsers.join(', ')}), diagnosing ${browser}`,
10667
10888
  remediation: 'Pass --browser=<name> to diagnose a specific session'
10668
10889
  });
10890
+ const emulatorRefusal = (0, emulator_session.MC)(bridge, projectPath, browser, 'doctor');
10891
+ if (emulatorRefusal) {
10892
+ results.push({
10893
+ check: 'engine',
10894
+ status: 'fail',
10895
+ detail: emulatorRefusal
10896
+ });
10897
+ return results;
10898
+ }
10669
10899
  const skip = (check, blockedBy)=>{
10670
10900
  results.push({
10671
10901
  check,
@@ -10898,10 +11128,11 @@ Cross-browser compatibility
10898
11128
  'control-channel': messaging.Lp.E_CONTROL_UNAVAILABLE,
10899
11129
  'eval-token': messaging.Lp.E_TOKEN_MISSING,
10900
11130
  executor: messaging.Lp.E_CONTROL_UNAVAILABLE,
10901
- browser: messaging.Lp.E_BROWSER_LAUNCH
11131
+ browser: messaging.Lp.E_BROWSER_LAUNCH,
11132
+ engine: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET
10902
11133
  };
10903
11134
  function registerDoctorCommand(program) {
10904
- program.command('doctor').argument('[project-path]', 'path to the extension project root or the folder holding its manifest').option(`--browser <${SESSION_BROWSER_TARGETS_HELP}>`, 'which session to diagnose (defaults to the single live session, else chromium)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').description(commandDescriptions.doctor).action(async (projectPathArg, opts)=>{
11135
+ program.command('doctor').argument('[project-path]', 'path to the extension project root or the folder holding its manifest').option(`--browser <${vendors.Xf}>`, 'which session to diagnose (defaults to the single live session, else chromium)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').description(commandDescriptions.doctor).action(async (projectPathArg, opts)=>{
10905
11136
  const asJson = isJsonOutput(opts);
10906
11137
  let results;
10907
11138
  try {
@@ -10949,7 +11180,7 @@ Cross-browser compatibility
10949
11180
  await exitAfterDrain(1);
10950
11181
  }
10951
11182
  async function refuseIfNotManagedTarget(command, browserList, asJson) {
10952
- const bad = firstNonManagedInstallTarget(browserList);
11183
+ const bad = (0, vendors.RY)(browserList);
10953
11184
  if (!bad) return false;
10954
11185
  if ('not-installable' === bad.kind) {
10955
11186
  const message = browserNotInstallablePlain(bad.name);
@@ -10966,7 +11197,7 @@ Cross-browser compatibility
10966
11197
  message: `Unsupported browser: ${bad.name}.`
10967
11198
  }));
10968
11199
  else console.error(unsupportedBrowserFlag(bad.name, [
10969
- ...MANAGED_INSTALL_TARGETS
11200
+ ...vendors.L_
10970
11201
  ]));
10971
11202
  await exitAfterDrain(1);
10972
11203
  return true;
@@ -10983,11 +11214,11 @@ Cross-browser compatibility
10983
11214
  await exitAfterDrain(1);
10984
11215
  }
10985
11216
  function registerInstallCommand(program) {
10986
- 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)=>{
11217
+ program.command('install').arguments('[browser-name]').usage('[browser-name] [options]').description(commandDescriptions.install).option(`--browser <${vendors.b_}>`, '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)=>{
10987
11218
  const asJson = isJsonOutput(options);
10988
11219
  const named = Boolean(options.browser || browserArg);
10989
11220
  const selectedBrowser = options.browser || browserArg || 'chromium';
10990
- const browserList = installTargets(selectedBrowser);
11221
+ const browserList = (0, vendors.OB)(selectedBrowser);
10991
11222
  if (!(options.where && !named)) {
10992
11223
  if (await refuseIfNotManagedTarget('install', browserList, asJson)) return;
10993
11224
  }
@@ -11023,7 +11254,7 @@ Cross-browser compatibility
11023
11254
  browsers: installed
11024
11255
  }));
11025
11256
  });
11026
- 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 })=>{
11257
+ program.command('uninstall').usage('<browser-name> | --all | --where').description(commandDescriptions.uninstall).option(`--browser <${vendors.b_}>`, '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 })=>{
11027
11258
  const asJson = isJsonOutput({
11028
11259
  output
11029
11260
  });
@@ -11050,7 +11281,7 @@ Cross-browser compatibility
11050
11281
  await exitAfterDrain(1);
11051
11282
  return;
11052
11283
  }
11053
- const browserList = installTargets(selected);
11284
+ const browserList = (0, vendors.OB)(selected);
11054
11285
  if (await refuseIfNotManagedTarget('uninstall', browserList, asJson)) return;
11055
11286
  if (where) {
11056
11287
  let paths;
@@ -11094,7 +11325,7 @@ Cross-browser compatibility
11094
11325
  'Manifest file not found'
11095
11326
  ];
11096
11327
  function registerPreviewCommand(program) {
11097
- program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch\n" + BROWSER_LAUNCH_HELP_FOOTER).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').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--no-open', NO_OPEN_FLAG_DESCRIPTION).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)=>{
11328
+ program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch\n" + BROWSER_LAUNCH_HELP_FOOTER).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 <${vendors.DB}>`, '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').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--no-open', NO_OPEN_FLAG_DESCRIPTION).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)=>{
11098
11329
  const { browser: cliBrowser, ...previewOptions } = options;
11099
11330
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'preview') ?? 'chromium';
11100
11331
  if (previewOptions.debug || previewOptions.author || previewOptions.authorMode) {
@@ -11107,12 +11338,14 @@ Cross-browser compatibility
11107
11338
  const emit = (frame)=>{
11108
11339
  console.log(JSON.stringify(frame));
11109
11340
  };
11110
- const list = vendors(browser);
11341
+ const list = (0, vendors.oJ)(browser);
11111
11342
  let unsupported = '';
11112
- const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
11343
+ const vendorsAreSupported = (0, vendors.sS)(list, (invalid, supported)=>{
11113
11344
  unsupported = invalid;
11114
11345
  if (asJson) return;
11115
11346
  console.error(unsupportedBrowserFlag(invalid, supported));
11347
+ }, {
11348
+ allowEmulator: false
11116
11349
  });
11117
11350
  if (!vendorsAreSupported) {
11118
11351
  if (asJson) emit(messaging.Pr.fail('preview', 'usage', {
@@ -11122,7 +11355,7 @@ Cross-browser compatibility
11122
11355
  await exitAfterDrain(1);
11123
11356
  return;
11124
11357
  }
11125
- if (list.some(isSafariVendor)) {
11358
+ if (list.some(vendors.$q)) {
11126
11359
  if (asJson) emit(messaging.Pr.fail('preview', 'usage', {
11127
11360
  code: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET,
11128
11361
  message: 'Safari is not supported by preview.'
@@ -11361,7 +11594,7 @@ Cross-browser compatibility
11361
11594
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
11362
11595
  }
11363
11596
  function registerStartCommand(program) {
11364
- program.command('start').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the build still runs\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).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('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').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('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).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)=>{
11597
+ program.command('start').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the build still runs\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).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 <${vendors.DB}>`, 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').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('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', vendors.sJ).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).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)=>{
11365
11598
  const { browser: cliBrowser, ...startOptions } = options;
11366
11599
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'start') ?? 'chromium';
11367
11600
  if (startOptions.debug || startOptions.author || startOptions.authorMode) {
@@ -11373,18 +11606,20 @@ Cross-browser compatibility
11373
11606
  const cliVersion = checkProjectCliVersion(external_node_path_.resolve(pathOrRemoteUrl || process.cwd()), getCliPackageJson().version);
11374
11607
  if (cliVersion) console.warn(projectCliVersionMismatch(cliVersion.running, cliVersion.declared, cliVersion.range, cliVersion.command));
11375
11608
  if (asJson) process.env.EXTENSION_OUTPUT = 'json';
11376
- const list = vendors(browser);
11609
+ const list = (0, vendors.oJ)(browser);
11377
11610
  let unsupportedBrowser = '';
11378
- const vendorsAreSupported = validateVendors(list, (invalid, supported)=>{
11611
+ const vendorsAreSupported = (0, vendors.sS)(list, (invalid, supported)=>{
11379
11612
  unsupportedBrowser = invalid;
11380
11613
  if (asJson) return;
11381
11614
  console.error(unsupportedBrowserFlag(invalid, supported));
11615
+ }, {
11616
+ allowEmulator: false
11382
11617
  });
11383
11618
  if (!vendorsAreSupported) start_failAndExit(asJson, 'usage', {
11384
11619
  code: messaging.Lp.E_UNSUPPORTED_BROWSER,
11385
11620
  message: `Unsupported browser: ${unsupportedBrowser}`
11386
11621
  });
11387
- if (list.some(isSafariVendor)) {
11622
+ if (list.some(vendors.$q)) {
11388
11623
  if (!asJson) console.error(safariCommandNotSupported('start'));
11389
11624
  start_failAndExit(asJson, 'usage', {
11390
11625
  code: messaging.Lp.E_COMMAND_UNSUPPORTED_FOR_TARGET,