extension 4.1.18 → 4.1.20

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
@@ -741,16 +741,19 @@ var __webpack_modules__ = {
741
741
  const tail = outputTail.trim().length ? `\n${pintor__rspack_import_8_default().gray('── last output ──')}\n${outputTail}` : `\n${pintor__rspack_import_8_default().gray('(no output captured)')}`;
742
742
  return `${getLoggingPrefix('error')} Safari packaging tool ${pintor__rspack_import_8_default().underline(tool)} failed (${pintor__rspack_import_8_default().red(code)}).${tail}`;
743
743
  }
744
+ const SAFARI_KEPT_ON_PURPOSE = {
745
+ world: 'Safari has honored the MAIN world since Safari 18, so the key stays'
746
+ };
744
747
  function safariConverterWarnings(warnings) {
745
- return `${getLoggingPrefix('warn')} safari-web-extension-converter reported ${pintor__rspack_import_8_default().yellow(String(warnings.length))} ${1 === warnings.length ? 'warning' : 'warnings'}, some manifest keys/APIs may not be supported by Safari:\n` + warnings.map((line)=>` ${pintor__rspack_import_8_default().gray('•')} ${line}`).join('\n');
748
+ const kept = warnings.map((line)=>line.trim()).filter((line)=>line in SAFARI_KEPT_ON_PURPOSE);
749
+ const keptLines = kept.map((line)=>` ${pintor__rspack_import_8_default().yellow(line)} ${pintor__rspack_import_8_default().gray(SAFARI_KEPT_ON_PURPOSE[line])}`).join('\n');
750
+ return `${getLoggingPrefix('warn')} safari-web-extension-converter reported ${pintor__rspack_import_8_default().yellow(String(warnings.length))} ${1 === warnings.length ? 'warning' : 'warnings'}, some manifest keys/APIs may not be supported by Safari:\n` + warnings.map((line)=>` ${pintor__rspack_import_8_default().gray('•')} ${line}`).join('\n') + (kept.length ? `\nExtension.js kept ${1 === kept.length ? 'one of these keys' : 'some of these keys'} on purpose:\n${keptLines}` : '');
746
751
  }
747
752
  function safariDefaultBundleIdNote(bundleId) {
748
753
  return `${getLoggingPrefix('warn')} The bundle id ${pintor__rspack_import_8_default().gray(bundleId)} is generated from the app name.\nEvery project built from the same source shares this id, and the first team to register it takes it.\nSet your own with ${pintor__rspack_import_8_default().blue('--bundle-id')} before your first submission.\nAfter a submission, a new id is a new extension with none of your users.`;
749
754
  }
750
- function safariOpenHint(appPath, appName, signed) {
751
- const launch = `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\n`;
752
- if (signed) return launch + `Then turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
753
- return launch + `Then enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ` + `${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
755
+ function safariOpenHint(appPath, appName) {
756
+ return `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\nThen turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
754
757
  }
755
758
  function safariDryRunNotBuilding() {
756
759
  return `${getLoggingPrefix('info')} Dry run: skip the Safari app build.`;
@@ -762,8 +765,9 @@ var __webpack_modules__ = {
762
765
  return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
763
766
  }
764
767
  function safariNextSteps(appName, signed) {
765
- if (signed) return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} Signed with your team id, so this survives a restart.`;
766
- return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari Settings Advanced check ${pintor__rspack_import_8_default().yellow('“Show features for web developers”')}\n ${pintor__rspack_import_8_default().gray('2.')} Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} ${pintor__rspack_import_8_default().gray('(resets each launch)')}\n ${pintor__rspack_import_8_default().gray('3.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} The app window that just opened can also take you there.`;
768
+ const steps = `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n`;
769
+ if (signed) return steps + ` ${pintor__rspack_import_8_default().gray('')} Signed with your team id, so the identity is stable for distribution.`;
770
+ return steps + ` ${pintor__rspack_import_8_default().gray('→')} Ad-hoc signed, so it stays enabled across restarts.`;
767
771
  }
768
772
  function safariRegistered(appName) {
769
773
  return `${getLoggingPrefix('success')} Safari recognizes ${pintor__rspack_import_8_default().yellow(appName)}, finish enabling it with the steps above.`;
@@ -772,7 +776,7 @@ var __webpack_modules__ = {
772
776
  return `${getLoggingPrefix('info')} Safari hasn't picked up ${pintor__rspack_import_8_default().yellow(appName)} yet.\nOpen the app once, then check Safari ▸ Settings ▸ Extensions.`;
773
777
  }
774
778
  function safariRebuilt(appName) {
775
- return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().yellow(appName)}, reload the page (or toggle the extension) in Safari to see changes.`;
779
+ return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().yellow(appName)}.`;
776
780
  }
777
781
  function safariProjectStale() {
778
782
  return `${getLoggingPrefix('info')} Regenerating the Xcode project, manifest.json or identity options changed since it was generated.`;
@@ -5927,7 +5931,24 @@ var __webpack_modules__ = {
5927
5931
  });
5928
5932
  }
5929
5933
  function converterWarnings(output) {
5930
- return output.split(/\r?\n/).filter((line)=>/warning/i.test(line)).map((line)=>line.trim()).filter((line)=>line.length > 0);
5934
+ const lines = output.split(/\r?\n/);
5935
+ const collected = [];
5936
+ let inWarning = false;
5937
+ for (const line of lines){
5938
+ const trimmed = line.trim();
5939
+ if (/warning/i.test(line)) {
5940
+ inWarning = true;
5941
+ if (trimmed.length > 0) collected.push(trimmed);
5942
+ continue;
5943
+ }
5944
+ const isContinuation = inWarning && /^\s/.test(line) && trimmed.length > 0;
5945
+ if (isContinuation) {
5946
+ collected.push(trimmed);
5947
+ continue;
5948
+ }
5949
+ inWarning = false;
5950
+ }
5951
+ return collected;
5931
5952
  }
5932
5953
  async function confirmRegisteredWithSafari(bundleIdentifier) {
5933
5954
  const needle = `${bundleIdentifier}.Extension`;
@@ -6058,7 +6079,7 @@ var __webpack_modules__ = {
6058
6079
  if (preservedKeys.length > 0) logger.info?.(messages.oB(preservedKeys));
6059
6080
  (0, safari_config.x7)(config);
6060
6081
  logger.info?.(messages.l_(config.projectLocation));
6061
- } else logger.info?.(messages.oM());
6082
+ } else if ('full' === mode) logger.info?.(messages.oM());
6062
6083
  if ('full' === mode) logger.info?.(messages.jR((0, safari_config.aD)(config)));
6063
6084
  const built = await runTool('xcodebuild', xcodebuildArgs);
6064
6085
  if (!built.ok) {
@@ -6073,7 +6094,7 @@ var __webpack_modules__ = {
6073
6094
  }
6074
6095
  logger.info?.(messages.Rl(appPath));
6075
6096
  if (!config.open) {
6076
- logger.info?.(messages.aO(appPath, config.appName, isSigned));
6097
+ logger.info?.(messages.aO(appPath, config.appName));
6077
6098
  if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
6078
6099
  return describePackage(config);
6079
6100
  }
@@ -6218,36 +6239,55 @@ var __webpack_modules__ = {
6218
6239
  function manifestFingerprintPath(config) {
6219
6240
  return node_path__rspack_import_1.join(config.projectLocation, '.manifest-fingerprint');
6220
6241
  }
6221
- function stableStringify(obj) {
6222
- if (null == obj) return JSON.stringify(obj);
6223
- if ('object' != typeof obj) return JSON.stringify(obj);
6224
- if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(',')}]`;
6225
- const keys = Object.keys(obj).sort();
6226
- return `{${keys.map((k)=>`${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',')}}`;
6227
- }
6228
- function readManifestRaw(extensionDir) {
6242
+ function topLevelEntries(extensionDir) {
6229
6243
  try {
6230
- return node_fs__rspack_import_0.readFileSync(node_path__rspack_import_1.join(extensionDir, 'manifest.json'), 'utf8');
6244
+ return node_fs__rspack_import_0.readdirSync(extensionDir).sort();
6231
6245
  } catch {
6232
- return '';
6246
+ return [];
6233
6247
  }
6234
6248
  }
6235
- function normalizeManifest(raw) {
6249
+ function iconsFingerprint(extensionDir) {
6236
6250
  try {
6237
- return stableStringify(JSON.parse(raw));
6251
+ const raw = node_fs__rspack_import_0.readFileSync(node_path__rspack_import_1.join(extensionDir, 'manifest.json'), 'utf8');
6252
+ const icons = JSON.parse(raw).icons;
6253
+ if (!icons || 'object' != typeof icons) return '';
6254
+ return Object.keys(icons).sort().map((size)=>`${size}:${String(icons[size])}`).join(',');
6238
6255
  } catch {
6239
- return raw;
6256
+ return '';
6257
+ }
6258
+ }
6259
+ function asRecord(value) {
6260
+ return value && 'object' == typeof value && !Array.isArray(value) ? value : {};
6261
+ }
6262
+ function judgedManifestSurface(extensionDir) {
6263
+ const manifest = readManifest(extensionDir);
6264
+ const parts = [
6265
+ Object.keys(manifest).sort().join(',')
6266
+ ];
6267
+ for (const listName of [
6268
+ 'permissions',
6269
+ 'optional_permissions'
6270
+ ]){
6271
+ const list = manifest[listName];
6272
+ const names = Array.isArray(list) ? list.filter((entry)=>'string' == typeof entry).sort() : [];
6273
+ parts.push(`${listName}:${names.join(',')}`);
6240
6274
  }
6275
+ const contentScripts = manifest.content_scripts;
6276
+ if (Array.isArray(contentScripts)) parts.push(contentScripts.map((entry)=>Object.keys(asRecord(entry)).sort().join('+')).join(';'));
6277
+ parts.push(Object.keys(asRecord(manifest.options_ui)).sort().join(','));
6278
+ return parts.join('|');
6241
6279
  }
6242
6280
  function composeProjectFingerprint(config) {
6243
6281
  return JSON.stringify({
6244
- v: 2,
6282
+ v: 4,
6245
6283
  identity: {
6246
6284
  appName: config.appName,
6247
6285
  bundleId: config.bundleIdentifier,
6248
6286
  macOsOnly: config.macOsOnly
6249
6287
  },
6250
- manifest: normalizeManifest(readManifestRaw(config.extensionDir))
6288
+ entries: topLevelEntries(config.extensionDir),
6289
+ icons: iconsFingerprint(config.extensionDir),
6290
+ judged: judgedManifestSurface(config.extensionDir)
6251
6291
  });
6252
6292
  }
6253
6293
  function saveManifestFingerprint(config) {
@@ -6663,21 +6703,47 @@ var __webpack_modules__ = {
6663
6703
  "./index.ts" (__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
6664
6704
  const MIN_NODE_MAJOR = 22;
6665
6705
  const MIN_NODE_MINOR = 12;
6706
+ const MIN_DENO_MAJOR = 2;
6707
+ const MIN_DENO_MINOR = 5;
6708
+ const BLOCKED_DENO_VERSIONS = [
6709
+ '2.8.0'
6710
+ ];
6711
+ function meetsFloor(version, major, minor) {
6712
+ const [actualMajor, actualMinor] = version.split('.').map((part)=>parseInt(part, 10));
6713
+ if (!Number.isFinite(actualMajor)) return true;
6714
+ if (actualMajor !== major) return actualMajor > major;
6715
+ return (Number.isFinite(actualMinor) ? actualMinor : 0) >= minor;
6716
+ }
6666
6717
  function isSupportedNodeVersion(version) {
6667
- const [major, minor] = version.split('.').map((part)=>parseInt(part, 10));
6668
- if (!Number.isFinite(major)) return true;
6669
- if (major !== MIN_NODE_MAJOR) return major > MIN_NODE_MAJOR;
6670
- return (Number.isFinite(minor) ? minor : 0) >= MIN_NODE_MINOR;
6718
+ return meetsFloor(version, MIN_NODE_MAJOR, MIN_NODE_MINOR);
6719
+ }
6720
+ function isSupportedDenoVersion(version) {
6721
+ if (BLOCKED_DENO_VERSIONS.includes(version)) return false;
6722
+ return meetsFloor(version, MIN_DENO_MAJOR, MIN_DENO_MINOR);
6671
6723
  }
6672
6724
  function detectBunVersion(versions = process.versions) {
6673
6725
  const bunVersion = versions.bun;
6674
6726
  return 'string' == typeof bunVersion && bunVersion.length > 0 ? bunVersion : void 0;
6675
6727
  }
6728
+ function detectDenoVersion(versions = process.versions) {
6729
+ const denoVersion = versions.deno;
6730
+ return 'string' == typeof denoVersion && denoVersion.length > 0 ? denoVersion : void 0;
6731
+ }
6732
+ function unsupportedDenoVersionMessage(version) {
6733
+ if (BLOCKED_DENO_VERSIONS.includes(version)) return `[Extension.js] Deno ${version} cannot load node:querystring inside the bundler, so every build fails on it. Deno fixed that in 2.8.1. Run deno upgrade to build the extension on Deno.`;
6734
+ return `[Extension.js] Requires Deno >= ${MIN_DENO_MAJOR}.${MIN_DENO_MINOR} (you are on ${version}). Run deno upgrade, or run the extension CLI on Node.js >= ${MIN_NODE_MAJOR}.${MIN_NODE_MINOR} instead.`;
6735
+ }
6676
6736
  function unsupportedNodeVersionMessage(version, bunVersion) {
6677
6737
  if (bunVersion) return `[Extension.js] The extension CLI runs on Node.js, not on the Bun runtime (Bun ${bunVersion}, reporting Node.js ${version}), so the Node.js you have installed is not the problem. Run it on Node.js instead: drop --bun from bunx or bun run, or unset run.bun in bunfig.toml, plain bunx runs the extension CLI on Node.js.`;
6678
6738
  return `[Extension.js] Requires Node.js >= ${MIN_NODE_MAJOR}.${MIN_NODE_MINOR} (you are on ${version}). Upgrade Node.js to run the extension CLI.`;
6679
6739
  }
6680
- function enforceSupportedNodeVersion(version = process.versions.node, bunVersion = detectBunVersion()) {
6740
+ function enforceSupportedNodeVersion(version = process.versions.node, bunVersion = detectBunVersion(), denoVersion = detectDenoVersion()) {
6741
+ if (denoVersion) {
6742
+ if (isSupportedDenoVersion(denoVersion)) return;
6743
+ console.error(unsupportedDenoVersionMessage(denoVersion));
6744
+ process.exit(1);
6745
+ return;
6746
+ }
6681
6747
  if (!bunVersion && isSupportedNodeVersion(version)) return;
6682
6748
  console.error(unsupportedNodeVersionMessage(version, bunVersion));
6683
6749
  process.exit(1);
@@ -7075,7 +7141,7 @@ var __webpack_modules__ = {
7075
7141
  return Math.min(Math.max(n, min), max);
7076
7142
  }
7077
7143
  const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
7078
- const TEMPLATE_CORPUS_REF = 'e552f6db6f2862093ba9d7026e0d376f002d95cc';
7144
+ const TEMPLATE_CORPUS_REF = '39448a235ea1b02516e6d555bcae409db2258b7f';
7079
7145
  const TEMPLATE_CORPUS_SLUGS = [
7080
7146
  'action',
7081
7147
  'action-locales',
@@ -8066,15 +8132,16 @@ AI assistants
8066
8132
  return `${getLoggingPrefix('error')} Can't use ${messages_code(bundleId)} as a bundle identifier.\nUse reverse-DNS form: dot-separated segments of letters, digits and hyphens, each starting with a letter (e.g. ${messages_code('com.example.my-extension')}).`;
8067
8133
  }
8068
8134
  function safariCommandNotSupported(command) {
8069
- return `${getLoggingPrefix('error')} ${messages_code(command)} can't load an extension into Safari automatically.\nSafari extensions ship inside a signed app and are enabled by hand, so there's no live browser session to load into, unlike Chromium and Firefox.\nBuild the Safari app instead: ${messages_code('extension build --browser safari')}\nThen open the generated app and enable it in Safari Settings Extensions.`;
8135
+ return `${getLoggingPrefix('error')} ${messages_code(command)} can't load an extension into Safari.\nSafari loads an extension only from an app it has registered, and that app is enabled by hand once installed.\nIts automation route can load a folder but grants no website access, so content scripts never run.\nRun a live Safari session: ${messages_code('extension dev --browser safari')}\nOr package the app and open it: ${messages_code('extension build --browser safari --open')}\nBoth need macOS with Xcode, and Safari takes the enable gesture once in Safari Settings Extensions.`;
8070
8136
  }
8071
8137
  function programAIHelp() {
8072
8138
  return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
8073
8139
 
8074
8140
  Browser-specific configuration
8075
8141
  - Use browser prefixes in manifest.json for browser-specific fields:
8076
- ${messages_code('{"firefox:manifest": 2, "chrome:manifest": 3}')}
8077
- This applies manifest v2 to Firefox only, v3 to Chrome/Edge.
8142
+ ${messages_code('{"firefox:manifest_version": 2, "chromium:manifest_version": 3}')}
8143
+ This applies manifest v2 to Firefox only, v3 to every Chromium-based browser.
8144
+ ${messages_code('chrome:')} and ${messages_code('edge:')} apply only to that one browser.
8078
8145
 
8079
8146
  Centralized logger (for AI & CI)
8080
8147
  - Logs from all contexts are centralized by the manager extension and streamed to the CLI.
@@ -8482,6 +8549,96 @@ Cross-browser compatibility
8482
8549
  function sessionLogsPath(bridge, projectPath, browser) {
8483
8550
  return sessionFilePath(bridge, 'logsPath', projectPath, browser, 'logs.ndjson');
8484
8551
  }
8552
+ function isSafariVendor(value) {
8553
+ return 'safari' === value || 'webkit-based' === value;
8554
+ }
8555
+ const SUPPORTED_BROWSER_TARGETS = [
8556
+ 'chrome',
8557
+ 'chromium',
8558
+ 'edge',
8559
+ 'firefox',
8560
+ 'brave',
8561
+ 'opera',
8562
+ 'vivaldi',
8563
+ 'yandex',
8564
+ 'waterfox',
8565
+ 'librewolf',
8566
+ 'chromium-based',
8567
+ 'gecko-based',
8568
+ 'firefox-based',
8569
+ 'safari',
8570
+ 'webkit-based'
8571
+ ];
8572
+ const BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.join(' | ');
8573
+ const SESSION_BROWSER_TARGETS_HELP = "chrome | chromium | edge | firefox | safari";
8574
+ const NO_SAFARI_BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.filter((target)=>!isSafariVendor(target)).join(' | ');
8575
+ function parseOptionalBoolean(value) {
8576
+ if (void 0 === value) return true;
8577
+ const normalized = String(value).trim().toLowerCase();
8578
+ return ![
8579
+ 'false',
8580
+ '0',
8581
+ 'no',
8582
+ 'off'
8583
+ ].includes(normalized);
8584
+ }
8585
+ const vendors = (browser)=>{
8586
+ const value = browser ?? 'chromium';
8587
+ return 'all' === value ? [
8588
+ 'chrome',
8589
+ 'edge',
8590
+ 'firefox'
8591
+ ] : String(value).split(',').map((part)=>part.trim()).filter(Boolean);
8592
+ };
8593
+ const MANAGED_INSTALL_TARGETS = [
8594
+ 'chrome',
8595
+ 'chromium',
8596
+ 'edge',
8597
+ 'firefox',
8598
+ 'chromium-based',
8599
+ 'gecko-based',
8600
+ 'firefox-based'
8601
+ ];
8602
+ const MANAGED_INSTALL_TARGETS_HELP = [
8603
+ ...MANAGED_INSTALL_TARGETS,
8604
+ 'all'
8605
+ ].join(' | ');
8606
+ const MANAGED_INSTALL_BINARIES = [
8607
+ 'chrome',
8608
+ 'chromium',
8609
+ 'edge',
8610
+ 'firefox'
8611
+ ];
8612
+ const installTargets = (browser)=>'all' === browser ? [
8613
+ ...MANAGED_INSTALL_BINARIES
8614
+ ] : vendors(browser);
8615
+ function validateVendors(vendorsList, onInvalid) {
8616
+ const supported = SUPPORTED_BROWSER_TARGETS;
8617
+ for (const v of vendorsList)if (!supported.includes(v)) {
8618
+ onInvalid(v, supported);
8619
+ return false;
8620
+ }
8621
+ return true;
8622
+ }
8623
+ const MANAGED_INSTALL_TARGET_SET = new Set(MANAGED_INSTALL_TARGETS);
8624
+ const SUPPORTED_BROWSER_TARGET_SET = new Set(SUPPORTED_BROWSER_TARGETS);
8625
+ function classifyManagedInstallTarget(name) {
8626
+ const value = String(name || '').trim().toLowerCase();
8627
+ if (!value) return 'unknown';
8628
+ if (MANAGED_INSTALL_TARGET_SET.has(value)) return 'managed';
8629
+ if (SUPPORTED_BROWSER_TARGET_SET.has(value)) return 'not-installable';
8630
+ return 'unknown';
8631
+ }
8632
+ function firstNonManagedInstallTarget(targetsList) {
8633
+ for (const name of targetsList){
8634
+ const kind = classifyManagedInstallTarget(name);
8635
+ if ('managed' !== kind) return {
8636
+ name,
8637
+ kind
8638
+ };
8639
+ }
8640
+ return null;
8641
+ }
8485
8642
  function parseLogSinceLocal(value) {
8486
8643
  if (null == value || '' === value) return null;
8487
8644
  if ('number' == typeof value) return Number.isFinite(value) ? {
@@ -8592,7 +8749,7 @@ Cross-browser compatibility
8592
8749
  }
8593
8750
  }
8594
8751
  function registerLogsCommand(program) {
8595
- program.command('logs').arguments('[project-path]').usage('[project-path] [options]').description(commandDescriptions.logs).option('--browser <chrome | chromium | edge | firefox>', '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)=>{
8752
+ 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)=>{
8596
8753
  const bridge = await loadExtensionDevelopBridgeModule();
8597
8754
  const projectPath = resolveSessionProjectPath(bridge, projectPathArg);
8598
8755
  const browser = options.browser || 'chromium';
@@ -8935,7 +9092,7 @@ Cross-browser compatibility
8935
9092
  if (null != opts.tab && '' !== opts.tab) target.tabId = Number(opts.tab);
8936
9093
  return target;
8937
9094
  }
8938
- const commonOptions = (cmd)=>cmd.option('--browser <chrome | chromium | edge | firefox>', 'which session to target (default chromium)').option('--timeout <ms>', 'command timeout in milliseconds (default 5000)').option('--output <pretty|json>', 'output format (default pretty)');
9095
+ 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)');
8939
9096
  function registerActCommands(program) {
8940
9097
  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)=>{
8941
9098
  await runCommand({
@@ -9106,97 +9263,8 @@ Cross-browser compatibility
9106
9263
  const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
9107
9264
  return values.length > 0 ? values : void 0;
9108
9265
  }
9109
- function isSafariVendor(value) {
9110
- return 'safari' === value || 'webkit-based' === value;
9111
- }
9112
- const SUPPORTED_BROWSER_TARGETS = [
9113
- 'chrome',
9114
- 'chromium',
9115
- 'edge',
9116
- 'firefox',
9117
- 'brave',
9118
- 'opera',
9119
- 'vivaldi',
9120
- 'yandex',
9121
- 'waterfox',
9122
- 'librewolf',
9123
- 'chromium-based',
9124
- 'gecko-based',
9125
- 'firefox-based',
9126
- 'safari',
9127
- 'webkit-based'
9128
- ];
9129
- const BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.join(' | ');
9130
- const NO_SAFARI_BROWSER_TARGETS_HELP = SUPPORTED_BROWSER_TARGETS.filter((target)=>!isSafariVendor(target)).join(' | ');
9131
- function parseOptionalBoolean(value) {
9132
- if (void 0 === value) return true;
9133
- const normalized = String(value).trim().toLowerCase();
9134
- return ![
9135
- 'false',
9136
- '0',
9137
- 'no',
9138
- 'off'
9139
- ].includes(normalized);
9140
- }
9141
- const vendors = (browser)=>{
9142
- const value = browser ?? 'chromium';
9143
- return 'all' === value ? [
9144
- 'chrome',
9145
- 'edge',
9146
- 'firefox'
9147
- ] : String(value).split(',').map((part)=>part.trim()).filter(Boolean);
9148
- };
9149
- const MANAGED_INSTALL_TARGETS = [
9150
- 'chrome',
9151
- 'chromium',
9152
- 'edge',
9153
- 'firefox',
9154
- 'chromium-based',
9155
- 'gecko-based',
9156
- 'firefox-based'
9157
- ];
9158
- const MANAGED_INSTALL_TARGETS_HELP = [
9159
- ...MANAGED_INSTALL_TARGETS,
9160
- 'all'
9161
- ].join(' | ');
9162
- const MANAGED_INSTALL_BINARIES = [
9163
- 'chrome',
9164
- 'chromium',
9165
- 'edge',
9166
- 'firefox'
9167
- ];
9168
- const installTargets = (browser)=>'all' === browser ? [
9169
- ...MANAGED_INSTALL_BINARIES
9170
- ] : vendors(browser);
9171
- function validateVendors(vendorsList, onInvalid) {
9172
- const supported = SUPPORTED_BROWSER_TARGETS;
9173
- for (const v of vendorsList)if (!supported.includes(v)) {
9174
- onInvalid(v, supported);
9175
- return false;
9176
- }
9177
- return true;
9178
- }
9179
- const MANAGED_INSTALL_TARGET_SET = new Set(MANAGED_INSTALL_TARGETS);
9180
- const SUPPORTED_BROWSER_TARGET_SET = new Set(SUPPORTED_BROWSER_TARGETS);
9181
- function classifyManagedInstallTarget(name) {
9182
- const value = String(name || '').trim().toLowerCase();
9183
- if (!value) return 'unknown';
9184
- if (MANAGED_INSTALL_TARGET_SET.has(value)) return 'managed';
9185
- if (SUPPORTED_BROWSER_TARGET_SET.has(value)) return 'not-installable';
9186
- return 'unknown';
9187
- }
9188
- function firstNonManagedInstallTarget(targetsList) {
9189
- for (const name of targetsList){
9190
- const kind = classifyManagedInstallTarget(name);
9191
- if ('managed' !== kind) return {
9192
- name,
9193
- kind
9194
- };
9195
- }
9196
- return null;
9197
- }
9198
9266
  function registerBuildCommand(program) {
9199
- 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').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 treats as unsigned: the extension then needs Develop \u25b8 Allow Unsigned Extensions re-ticked on every launch. A signed build is listed and stays enabled across restarts').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 })=>{
9267
+ 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').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 })=>{
9200
9268
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'build') ?? 'chromium';
9201
9269
  if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
9202
9270
  process.env.EXTENSION_DEBUG = '1';
@@ -9832,7 +9900,7 @@ Cross-browser compatibility
9832
9900
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
9833
9901
  }
9834
9902
  function registerDevCommand(program) {
9835
- 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; no live reload)').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').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 treats as unsigned: the extension then needs Develop \u25b8 Allow Unsigned Extensions re-ticked on every launch. A signed build is listed and stays enabled across restarts').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)=>{
9903
+ 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').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)=>{
9836
9904
  const { browser: cliBrowser, ...devOptions } = options;
9837
9905
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'dev') ?? 'chromium';
9838
9906
  if (devOptions.debug || devOptions.author || devOptions.authorMode) {
@@ -10312,7 +10380,7 @@ Cross-browser compatibility
10312
10380
  browser: messaging.Lp.E_BROWSER_LAUNCH
10313
10381
  };
10314
10382
  function registerDoctorCommand(program) {
10315
- program.command('doctor').argument('[project-path]', 'path to the extension project root or the folder holding its manifest').option('--browser <chrome | chromium | edge | firefox>', '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)=>{
10383
+ 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)=>{
10316
10384
  const asJson = isJsonOutput(opts);
10317
10385
  let results;
10318
10386
  try {
@@ -1,10 +1,8 @@
1
1
  export declare const DEFAULT_DEBUG_PORT = 9222;
2
2
  export declare const PORT_OFFSET = 100;
3
3
  export declare const CDP_COMMAND_TIMEOUT_MS: number;
4
- /** CDP HTTP endpoint timeout for /json discovery (ms). Override: EXTENSION_CDP_HTTP_TIMEOUT_MS */
5
4
  export declare const CDP_HTTP_TIMEOUT_MS: number;
6
5
  export declare const RDP_EVAL_TIMEOUT_MS: number;
7
- /** Firefox RDP connect retry count. Override: EXTENSION_RDP_MAX_RETRIES */
8
6
  export declare const RDP_MAX_RETRIES: number;
9
7
  export declare const RDP_RETRY_INTERVAL_MS: number;
10
8
  export declare const CDP_HEARTBEAT_INTERVAL_MS: number;
@@ -72,7 +72,7 @@ export declare function safariOpening(target: string): string;
72
72
  export declare function safariToolFailed(tool: string, exitCode: number | null, outputTail: string): string;
73
73
  export declare function safariConverterWarnings(warnings: string[]): string;
74
74
  export declare function safariDefaultBundleIdNote(bundleId: string): string;
75
- export declare function safariOpenHint(appPath: string, appName: string, signed?: boolean): string;
75
+ export declare function safariOpenHint(appPath: string, appName: string): string;
76
76
  export declare function safariDryRunNotBuilding(): string;
77
77
  export declare function safariDryRunConverter(cmd: string): string;
78
78
  export declare function safariDryRunXcodebuild(cmd: string): string;
@@ -1,33 +1,10 @@
1
- /**
2
- * The single decision about what profile a development run gets. Both the
3
- * chromium and firefox launchers route through this so the profile contract
4
- * (`false`, `copyFromProfile`, `keepProfileChanges`, the env switch, explicit
5
- * paths and the plain ephemeral default) is interpreted in exactly one place.
6
- *
7
- * - `system`, the browser's own default profile. No managed directory is
8
- * created, seeded or cleaned and no profile launch arg is
9
- * emitted. Produced by `profile: false` and by the
10
- * EXTENSION_USE_SYSTEM_PROFILE / EXTJS_USE_SYSTEM_PROFILE switch.
11
- * - `explicit`, a user-provided profile path; launched against exactly that
12
- * directory.
13
- * - `managed`, a directory under `dist/extension-js/profiles/<browser>-profile`
14
- * that extension.js owns. Ephemeral by default (marked so it is
15
- * reclaimed on browser exit); persistent (`dev`) when
16
- * `persistProfile` or `keepProfileChanges` is set, in which case
17
- * the marker is withheld so the cleanup hook skips it.
18
- */
19
1
  export type ProfileKind = 'system' | 'explicit' | 'managed';
20
2
  export interface ResolveProfileInput {
21
3
  rawProfile?: string | boolean;
22
- /** Managed-profile base directory: `<distRoot>/extension-js/profiles/<browser>-profile`. */
23
4
  managedBaseDir: string;
24
- /** EXTENSION_USE_SYSTEM_PROFILE / EXTJS_USE_SYSTEM_PROFILE resolved to a boolean. */
25
5
  useSystemProfile: boolean;
26
- /** `persistProfile` option (stable `dev` directory, never auto-cleaned). */
27
6
  persistProfile?: boolean;
28
- /** `keepProfileChanges` option, keep the managed profile and its changes across runs. */
29
7
  keepProfileChanges?: boolean;
30
- /** `copyFromProfile` option, seed the managed profile as a copy of this path. */
31
8
  copyFromProfile?: string;
32
9
  resolveExplicit: (trimmedProfile: string) => string;
33
10
  provision?: boolean;
@@ -35,21 +12,9 @@ export interface ResolveProfileInput {
35
12
  export interface ResolvedProfile {
36
13
  kind: ProfileKind;
37
14
  profilePath: string;
38
- /** True when the managed profile is persisted (no cleanup on exit). */
39
15
  persisted: boolean;
40
- /** Set when `copyFromProfile` seeded this run, for logging/visibility. */
41
16
  seededFrom?: string;
42
17
  }
43
- /**
44
- * The one interpretation of the `--profile` / `profile` option value.
45
- * Commander delivers flag values as strings, so `--profile false` arrives as
46
- * the string `'false'`. Without this normalization that string reads as an
47
- * explicit path and a literal profile directory named `false` gets created.
48
- *
49
- * - `false` / `'false'`: the browser's own default profile (system).
50
- * - `true` / `'true'`: the managed default (same as leaving the option unset).
51
- * - any other string: an explicit profile path.
52
- */
53
18
  export declare function normalizeProfileOption(value: string | boolean | undefined): string | false | undefined;
54
19
  export declare function ensureProfileRootIgnoreFile(managedBaseDir: string): void;
55
20
  export declare function seedProfileFrom(source: string, dest: string): void;