extension 4.0.19 → 4.0.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/browsers.cjs CHANGED
@@ -1260,6 +1260,18 @@ var __webpack_modules__ = {
1260
1260
  node_fs__rspack_import_0.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
1261
1261
  } catch {}
1262
1262
  }
1263
+ function stampReadyBrowserLaunch(extensionOutputPath, details) {
1264
+ try {
1265
+ if (!extensionOutputPath) return;
1266
+ const readyPath = readyPathFor(extensionOutputPath);
1267
+ if (!node_fs__rspack_import_0.existsSync(readyPath)) return;
1268
+ const ready = JSON.parse(node_fs__rspack_import_0.readFileSync(readyPath, 'utf-8'));
1269
+ const profilePath = String(details?.profilePath || '').trim();
1270
+ if (profilePath) ready.profilePath = profilePath;
1271
+ if ('number' == typeof details?.browserPid && Number.isFinite(details.browserPid)) ready.browserPid = details.browserPid;
1272
+ node_fs__rspack_import_0.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
1273
+ } catch {}
1274
+ }
1263
1275
  function stampReadyExtensionLoadRefused(extensionOutputPath, reason) {
1264
1276
  try {
1265
1277
  if (!extensionOutputPath) return;
@@ -1306,6 +1318,7 @@ var __webpack_modules__ = {
1306
1318
  } catch {}
1307
1319
  }
1308
1320
  __webpack_require__.d(__webpack_exports__, {
1321
+ M: ()=>stampReadyBrowserLaunch,
1309
1322
  Wi: ()=>stampReadyBrowserExited,
1310
1323
  __: ()=>stampReadyRdpPort,
1311
1324
  iD: ()=>stampReadyProfileLocked,
@@ -3066,6 +3079,10 @@ var __webpack_modules__ = {
3066
3079
  extensionOutputPath: (0, extension_output_path.W)(compilation, chromiumConfig.find((flag)=>flag.startsWith('--load-extension='))) || void 0
3067
3080
  };
3068
3081
  const child = await this.launchWithDirectSpawn(browserBinaryLocation, chromiumConfig, usePipe);
3082
+ (0, ready_stamp.M)(this.closeHandlerContext?.extensionOutputPath, {
3083
+ profilePath: chromiumConfig.find((flag)=>flag.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, ''),
3084
+ browserPid: child?.pid
3085
+ });
3069
3086
  const pipeStreams = usePipe && child?.stdio?.[3] && child?.stdio?.[4] ? {
3070
3087
  input: child.stdio[4],
3071
3088
  output: child.stdio[3]
@@ -4835,6 +4852,10 @@ var __webpack_modules__ = {
4835
4852
  const profilePath = profileMatch[1];
4836
4853
  const { binary, args } = FirefoxBinaryDetector.generateFirefoxArgs(binaryPath, profilePath, debugPort, firefoxArgs, isFirefoxHeadlessRequested());
4837
4854
  this.child = await this.spawnFirefoxChild(binary, args, wslFallbackBinary);
4855
+ (0, ready_stamp.M)(this.extensionOutputPath, {
4856
+ profilePath,
4857
+ browserPid: this.child?.pid
4858
+ });
4838
4859
  this.child.on('close', ()=>{
4839
4860
  (0, shared_utils.sW)(profilePath);
4840
4861
  });
@@ -4883,6 +4904,9 @@ var __webpack_modules__ = {
4883
4904
  ...firefoxArgs
4884
4905
  ];
4885
4906
  this.child = await this.spawnFirefoxChild(binaryPath, args, wslFallbackBinary);
4907
+ (0, ready_stamp.M)(this.extensionOutputPath, {
4908
+ browserPid: this.child?.pid
4909
+ });
4886
4910
  this.wireChildLifecycle();
4887
4911
  if (debugPort > 0) (0, ready_stamp.__)(this.extensionOutputPath, debugPort);
4888
4912
  this.scheduleWatchTimeout();
package/dist/cli.cjs CHANGED
@@ -1261,6 +1261,18 @@ var __webpack_modules__ = {
1261
1261
  node_fs__rspack_import_0.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
1262
1262
  } catch {}
1263
1263
  }
1264
+ function stampReadyBrowserLaunch(extensionOutputPath, details) {
1265
+ try {
1266
+ if (!extensionOutputPath) return;
1267
+ const readyPath = readyPathFor(extensionOutputPath);
1268
+ if (!node_fs__rspack_import_0.existsSync(readyPath)) return;
1269
+ const ready = JSON.parse(node_fs__rspack_import_0.readFileSync(readyPath, 'utf-8'));
1270
+ const profilePath = String(details?.profilePath || '').trim();
1271
+ if (profilePath) ready.profilePath = profilePath;
1272
+ if ('number' == typeof details?.browserPid && Number.isFinite(details.browserPid)) ready.browserPid = details.browserPid;
1273
+ node_fs__rspack_import_0.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
1274
+ } catch {}
1275
+ }
1264
1276
  function stampReadyExtensionLoadRefused(extensionOutputPath, reason) {
1265
1277
  try {
1266
1278
  if (!extensionOutputPath) return;
@@ -1307,6 +1319,7 @@ var __webpack_modules__ = {
1307
1319
  } catch {}
1308
1320
  }
1309
1321
  __webpack_require__.d(__webpack_exports__, {
1322
+ M: ()=>stampReadyBrowserLaunch,
1310
1323
  Wi: ()=>stampReadyBrowserExited,
1311
1324
  __: ()=>stampReadyRdpPort,
1312
1325
  iD: ()=>stampReadyProfileLocked,
@@ -3056,6 +3069,10 @@ var __webpack_modules__ = {
3056
3069
  extensionOutputPath: (0, extension_output_path.W)(compilation, chromiumConfig.find((flag)=>flag.startsWith('--load-extension='))) || void 0
3057
3070
  };
3058
3071
  const child = await this.launchWithDirectSpawn(browserBinaryLocation, chromiumConfig, usePipe);
3072
+ (0, ready_stamp.M)(this.closeHandlerContext?.extensionOutputPath, {
3073
+ profilePath: chromiumConfig.find((flag)=>flag.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, ''),
3074
+ browserPid: child?.pid
3075
+ });
3059
3076
  const pipeStreams = usePipe && child?.stdio?.[3] && child?.stdio?.[4] ? {
3060
3077
  input: child.stdio[4],
3061
3078
  output: child.stdio[3]
@@ -4825,6 +4842,10 @@ var __webpack_modules__ = {
4825
4842
  const profilePath = profileMatch[1];
4826
4843
  const { binary, args } = FirefoxBinaryDetector.generateFirefoxArgs(binaryPath, profilePath, debugPort, firefoxArgs, isFirefoxHeadlessRequested());
4827
4844
  this.child = await this.spawnFirefoxChild(binary, args, wslFallbackBinary);
4845
+ (0, ready_stamp.M)(this.extensionOutputPath, {
4846
+ profilePath,
4847
+ browserPid: this.child?.pid
4848
+ });
4828
4849
  this.child.on('close', ()=>{
4829
4850
  (0, shared_utils.sW)(profilePath);
4830
4851
  });
@@ -4873,6 +4894,9 @@ var __webpack_modules__ = {
4873
4894
  ...firefoxArgs
4874
4895
  ];
4875
4896
  this.child = await this.spawnFirefoxChild(binaryPath, args, wslFallbackBinary);
4897
+ (0, ready_stamp.M)(this.extensionOutputPath, {
4898
+ browserPid: this.child?.pid
4899
+ });
4876
4900
  this.wireChildLifecycle();
4877
4901
  if (debugPort > 0) (0, ready_stamp.__)(this.extensionOutputPath, debugPort);
4878
4902
  this.scheduleWatchTimeout();
@@ -5754,6 +5778,8 @@ var __webpack_modules__ = {
5754
5778
  E_SESSION_NOT_FOUND: 'E_SESSION_NOT_FOUND',
5755
5779
  E_EVAL_REFUSED: 'E_EVAL_REFUSED',
5756
5780
  E_TARGET_NOT_FOUND: 'E_TARGET_NOT_FOUND',
5781
+ E_HEADED_WINDOW_REQUIRED: 'E_HEADED_WINDOW_REQUIRED',
5782
+ E_USER_GESTURE_REQUIRED: 'E_USER_GESTURE_REQUIRED',
5757
5783
  E_TIMEOUT: 'E_TIMEOUT',
5758
5784
  E_PUBLISH_REJECTED: 'E_PUBLISH_REJECTED',
5759
5785
  E_AUTH_REQUIRED: 'E_AUTH_REQUIRED',
@@ -6296,6 +6322,12 @@ var __webpack_modules__ = {
6296
6322
  ],
6297
6323
  description: 'Diagnose a dev session: ready contract, control channel, token, executor, browser',
6298
6324
  supportsSourceInspection: false
6325
+ },
6326
+ {
6327
+ name: 'capabilities',
6328
+ positionals: [],
6329
+ description: 'Print the engine version, contract versions, and json-capable commands',
6330
+ supportsSourceInspection: false
6299
6331
  }
6300
6332
  ];
6301
6333
  const COMMANDS = COMMAND_TABLE.map((entry)=>({
@@ -6746,12 +6778,21 @@ Cross-Browser Compatibility
6746
6778
  }
6747
6779
  return out.slice(Math.max(0, out.length - limit));
6748
6780
  }
6749
- function codeForBridgeError(name, message) {
6781
+ const REFUSAL_TO_CODE = {
6782
+ needs_headed_window: messaging.Lp.E_HEADED_WINDOW_REQUIRED,
6783
+ needs_user_gesture: messaging.Lp.E_USER_GESTURE_REQUIRED,
6784
+ surface_not_open: messaging.Lp.E_TARGET_NOT_FOUND,
6785
+ api_unavailable: messaging.Lp.E_NOT_IMPLEMENTED
6786
+ };
6787
+ function codeForBridgeError(name, message, refusal) {
6788
+ if (refusal && refusal in REFUSAL_TO_CODE) return REFUSAL_TO_CODE[refusal];
6750
6789
  if ('Timeout' === name) return messaging.Lp.E_TIMEOUT;
6751
6790
  if ('Unavailable' === name) return messaging.Lp.E_CONTROL_UNAVAILABLE;
6752
- if ('Forbidden' === name) return /token missing/i.test(message) ? messaging.Lp.E_TOKEN_MISSING : messaging.Lp.E_EVAL_REFUSED;
6791
+ if ('EvalTokenMissing' === name) return messaging.Lp.E_TOKEN_MISSING;
6792
+ if ('EvalDisabled' === name || 'EvalTokenMismatch' === name || 'Forbidden' === name) return messaging.Lp.E_EVAL_REFUSED;
6793
+ if ('TargetNotFound' === name) return messaging.Lp.E_TARGET_NOT_FOUND;
6753
6794
  if ('BadRequest' === name) return messaging.Lp.E_ARGS;
6754
- if ('Unsupported' === name) return /needs a --tab id|no injectable frame|is not open/i.test(message) ? messaging.Lp.E_TARGET_NOT_FOUND : messaging.Lp.E_NOT_IMPLEMENTED;
6795
+ if ('Unsupported' === name) return /needs a --tab id|is not open/i.test(message) ? messaging.Lp.E_TARGET_NOT_FOUND : messaging.Lp.E_NOT_IMPLEMENTED;
6755
6796
  if ('EvalError' === name) return messaging.Lp.E_EVAL;
6756
6797
  if ('InspectError' === name) return messaging.Lp.E_INSPECT;
6757
6798
  if ('StorageError' === name) return messaging.Lp.E_STORAGE;
@@ -6776,14 +6817,19 @@ Cross-Browser Compatibility
6776
6817
  const raw = error || {};
6777
6818
  const name = 'string' == typeof raw.name ? raw.name : 'Error';
6778
6819
  const message = 'string' == typeof raw.message ? raw.message : 'command failed';
6779
- const code = codeForBridgeError(name, message);
6820
+ const refusal = 'string' == typeof raw.code ? raw.code : void 0;
6821
+ const code = codeForBridgeError(name, message, refusal);
6822
+ const hint = 'string' == typeof raw.hint ? raw.hint : code === messaging.Lp.E_EVAL ? 'The expression threw inside the page. Check the expression itself.' : void 0;
6780
6823
  return {
6781
6824
  ...extras,
6782
6825
  ...messaging.Pr.fail(command, statusForCode(code), {
6783
6826
  ...raw,
6784
6827
  code,
6785
6828
  message,
6786
- name
6829
+ name,
6830
+ ...hint ? {
6831
+ hint
6832
+ } : {}
6787
6833
  }, {
6788
6834
  truncated: wasTruncated
6789
6835
  })
@@ -7193,7 +7239,7 @@ Cross-Browser Compatibility
7193
7239
  if (asJson) console.log(JSON.stringify(messaging.Pr.ok('build', 'built', {
7194
7240
  projectPath: pathOrRemoteUrl,
7195
7241
  browsers: built,
7196
- mode,
7242
+ mode: mode ?? 'production',
7197
7243
  summaries
7198
7244
  })));
7199
7245
  });
@@ -7213,6 +7259,43 @@ Cross-Browser Compatibility
7213
7259
  }
7214
7260
  throw new Error('Extension.js CLI package.json not found.');
7215
7261
  }
7262
+ const READY_CONTRACT_SCHEMA_VERSION = 2;
7263
+ function collectOutputJsonCommands(program) {
7264
+ const names = new Set();
7265
+ for (const command of program.commands){
7266
+ const accepts = (command.options || []).some((option)=>'--output' === option.long && String(option.flags || '').includes('json'));
7267
+ if (accepts) names.add(command.name());
7268
+ }
7269
+ return Array.from(names).sort();
7270
+ }
7271
+ function buildEngineCapabilities(program) {
7272
+ const cliPackageJson = getCliPackageJson();
7273
+ return {
7274
+ name: String(cliPackageJson.name || 'extension'),
7275
+ version: String(cliPackageJson.version || ''),
7276
+ envelopeSchema: 1,
7277
+ readySchemaVersion: READY_CONTRACT_SCHEMA_VERSION,
7278
+ outputJsonCommands: collectOutputJsonCommands(program)
7279
+ };
7280
+ }
7281
+ function registerCapabilitiesCommand(program) {
7282
+ program.command('capabilities').description(commandDescriptions.capabilities).option('--output <pretty|json>', 'result format. This command defaults to json').action(async (opts = {})=>{
7283
+ const format = 'pretty' === String(opts.output ?? 'json').trim().toLowerCase() ? 'pretty' : 'json';
7284
+ const value = buildEngineCapabilities(program);
7285
+ if ('json' === format) {
7286
+ console.log(JSON.stringify(messaging.Pr.ok('capabilities', 'ok', value)));
7287
+ await exitAfterDrain(0);
7288
+ return;
7289
+ }
7290
+ console.log([
7291
+ `${value.name} ${value.version}`,
7292
+ `envelope schema: ${value.envelopeSchema}`,
7293
+ `ready contract schemaVersion: ${value.readySchemaVersion}`,
7294
+ `commands that accept --output json: ${value.outputJsonCommands.join(', ')}`
7295
+ ].join('\n'));
7296
+ await exitAfterDrain(0);
7297
+ });
7298
+ }
7216
7299
  const create_require = (0, external_node_module_.createRequire)(__rslib_import_meta_url__);
7217
7300
  const CREATE_ERROR_NEEDLES = {
7218
7301
  E_DESTINATION_NOT_EMPTY: 'already contains files that would be overwritten',
@@ -7274,6 +7357,95 @@ Cross-Browser Compatibility
7274
7357
  });
7275
7358
  }
7276
7359
  var browsers = __webpack_require__("./browsers/index.ts");
7360
+ const FRAMED_FLAG = 'extensionEnvelopePrinted';
7361
+ function markErrorFramed(err) {
7362
+ if (err && 'object' == typeof err) try {
7363
+ err[FRAMED_FLAG] = true;
7364
+ } catch {}
7365
+ }
7366
+ function isErrorFramed(err) {
7367
+ return Boolean(err && 'object' == typeof err && true === err[FRAMED_FLAG]);
7368
+ }
7369
+ function wantsJsonOutput(argv) {
7370
+ const equalArg = argv.find((arg)=>arg.startsWith('--output='));
7371
+ if (equalArg) return 'json' === equalArg.slice(9).trim().toLowerCase();
7372
+ const flagIndex = argv.indexOf('--output');
7373
+ if (flagIndex >= 0) return 'json' === String(argv[flagIndex + 1] || '').trim().toLowerCase();
7374
+ return false;
7375
+ }
7376
+ function isCommanderError(err) {
7377
+ return Boolean(err && 'object' == typeof err && 'string' == typeof err.code && String(err.code).startsWith('commander.'));
7378
+ }
7379
+ function commanderExitCode(err) {
7380
+ const exitCode = Number(err.exitCode);
7381
+ return Number.isFinite(exitCode) ? exitCode : 1;
7382
+ }
7383
+ function firstQuoted(message, pattern) {
7384
+ const match = pattern.exec(message);
7385
+ return match?.[1];
7386
+ }
7387
+ function refsFromMessage(code, message) {
7388
+ if ('commander.unknownOption' === code) {
7389
+ const flag = firstQuoted(message, /'(-[^']*)'/);
7390
+ return flag ? {
7391
+ flag
7392
+ } : void 0;
7393
+ }
7394
+ if ('commander.unknownCommand' === code) {
7395
+ const command = firstQuoted(message, /'([^']+)'/);
7396
+ return command ? {
7397
+ command
7398
+ } : void 0;
7399
+ }
7400
+ if ('commander.invalidArgument' === code || 'commander.optionMissingArgument' === code) {
7401
+ const option = firstQuoted(message, /option '([^']+)'/);
7402
+ const flag = option?.split(/\s+/)[0];
7403
+ return flag?.startsWith('-') ? {
7404
+ flag
7405
+ } : void 0;
7406
+ }
7407
+ }
7408
+ function codeForCommanderError(code) {
7409
+ if ('commander.unknownCommand' === code) return messaging.Lp.E_UNKNOWN_COMMAND;
7410
+ if ('commander.unknownOption' === code) return messaging.Lp.E_FLAG_NOT_SUPPORTED_HERE;
7411
+ if ('commander.invalidArgument' === code || 'commander.optionMissingArgument' === code) return messaging.Lp.E_FLAG_VALUE_INVALID;
7412
+ return messaging.Lp.E_ARGS;
7413
+ }
7414
+ function commanderErrorEnvelope(err, command) {
7415
+ const commanderCode = String(err.code);
7416
+ const message = String(err.message || 'the command line could not be parsed').replace(/^error:\s*/i, '').trim();
7417
+ const error = {
7418
+ code: codeForCommanderError(commanderCode),
7419
+ message,
7420
+ name: 'CliError'
7421
+ };
7422
+ const refs = refsFromMessage(commanderCode, message);
7423
+ if (refs) error.refs = refs;
7424
+ return messaging.Pr.fail(command, 'usage', error);
7425
+ }
7426
+ function internalErrorEnvelope(err, command) {
7427
+ return messaging.Pr.fail(command, 'failed', {
7428
+ code: messaging.Lp.E_INTERNAL,
7429
+ message: err instanceof Error ? err.message : String(err),
7430
+ name: err instanceof Error ? err.name : 'Error'
7431
+ });
7432
+ }
7433
+ function earlyExitEnvelope(command, code, message, refs) {
7434
+ const error = {
7435
+ code,
7436
+ message,
7437
+ name: 'CliError'
7438
+ };
7439
+ if (refs) error.refs = refs;
7440
+ return messaging.Pr.fail(command, 'usage', error);
7441
+ }
7442
+ function writeStdoutFrame(frame) {
7443
+ try {
7444
+ external_node_fs_.writeSync(1, `${JSON.stringify(frame)}\n`);
7445
+ } catch {
7446
+ console.log(JSON.stringify(frame));
7447
+ }
7448
+ }
7277
7449
  let warnedDeprecatedAlias = false;
7278
7450
  function warnDeprecatedOutputAlias(flag) {
7279
7451
  if (warnedDeprecatedAlias) return;
@@ -7602,6 +7774,7 @@ Cross-Browser Compatibility
7602
7774
  }, {
7603
7775
  hint: failure.hint
7604
7776
  }));
7777
+ markErrorFramed(error);
7605
7778
  }
7606
7779
  throw error;
7607
7780
  }
@@ -8426,6 +8599,7 @@ Cross-Browser Compatibility
8426
8599
  }, {
8427
8600
  hint: failure.hint
8428
8601
  }));
8602
+ markErrorFramed(error);
8429
8603
  }
8430
8604
  throw error;
8431
8605
  }
@@ -8964,9 +9138,9 @@ Cross-Browser Compatibility
8964
9138
  }
8965
9139
  return null;
8966
9140
  }
8967
- const cliPackageJson = getCliPackageJson();
9141
+ const index_cliPackageJson = getCliPackageJson();
8968
9142
  function developVersion() {
8969
- return resolveExtensionDevelopVersion(__dirname, cliPackageJson.version);
9143
+ return resolveExtensionDevelopVersion(__dirname, index_cliPackageJson.version);
8970
9144
  }
8971
9145
  process.env.EXTENSION_DEVELOP_VERSION = developVersion();
8972
9146
  function scanArgvValue(argv, flag) {
@@ -8991,19 +9165,23 @@ Cross-Browser Compatibility
8991
9165
  if (!arg.startsWith('-')) return arg;
8992
9166
  }
8993
9167
  }
9168
+ function failBeforeParse(argv, humanMessage, code, plainMessage, flag) {
9169
+ console.error(humanMessage);
9170
+ if (wantsJsonOutput(argv)) writeStdoutFrame(earlyExitEnvelope(resolveCommandFromArgv(argv) || 'extension', code, plainMessage, {
9171
+ flag
9172
+ }));
9173
+ process.exit(1);
9174
+ }
8994
9175
  function applyNoBrowserArgvShim(argv) {
8995
9176
  const hasNoRunner = argv.includes('--no-runner');
8996
- if (hasNoRunner) {
8997
- console.error(removedNoRunnerFlag());
8998
- process.exit(1);
8999
- }
9177
+ if (hasNoRunner) failBeforeParse(argv, removedNoRunnerFlag(), messaging.Lp.E_REMOVED_FLAG, '--no-runner was removed. Use --no-browser instead.', '--no-runner');
9000
9178
  let nextArgv = argv;
9001
9179
  const hasNoReload = nextArgv.includes('--no-reload');
9002
9180
  if (hasNoReload) {
9003
9181
  const command = resolveCommandFromArgv(nextArgv);
9004
9182
  if ('dev' !== command) {
9005
- console.error(`--no-reload is only supported on \`extension dev\` (got: ${command || 'no command'}).`);
9006
- process.exit(1);
9183
+ const message = `--no-reload is only supported on \`extension dev\` (got: ${command || 'no command'}).`;
9184
+ failBeforeParse(nextArgv, message, messaging.Lp.E_FLAG_NOT_SUPPORTED_HERE, message, '--no-reload');
9007
9185
  }
9008
9186
  process.env.EXTENSION_NO_RELOAD = 'true';
9009
9187
  nextArgv = nextArgv.filter((arg)=>'--no-reload' !== arg);
@@ -9012,10 +9190,7 @@ Cross-Browser Compatibility
9012
9190
  if (!hasNoBrowser) return nextArgv;
9013
9191
  const command = resolveCommandFromArgv(nextArgv);
9014
9192
  const supportsNoBrowser = 'dev' === command || 'start' === command || 'preview' === command;
9015
- if (!supportsNoBrowser) {
9016
- console.error(noBrowserNotSupportedForCommand(command));
9017
- process.exit(1);
9018
- }
9193
+ if (!supportsNoBrowser) failBeforeParse(nextArgv, noBrowserNotSupportedForCommand(command), messaging.Lp.E_FLAG_NOT_SUPPORTED_HERE, command ? `--no-browser is not supported on \`extension ${command}\`.` : '--no-browser needs a command that launches a browser.', '--no-browser');
9019
9194
  process.env.EXTENSION_CLI_NO_BROWSER = '1';
9020
9195
  return nextArgv.filter((arg)=>'--no-browser' !== arg);
9021
9196
  }
@@ -9025,7 +9200,7 @@ Cross-Browser Compatibility
9025
9200
  process.env.EXTENSION_CLI_UPDATE_SUFFIX = updateMessage.suffix;
9026
9201
  });
9027
9202
  const extensionJs = external_commander_namespaceObject.program;
9028
- extensionJs.name(String(cliPackageJson.name)).description(String(cliPackageJson.description)).version(String(cliPackageJson.version)).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').addOption(new external_commander_namespaceObject.Option('--format <pretty|json>').hideHelp()).addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true);
9203
+ extensionJs.name(String(index_cliPackageJson.name)).description(String(index_cliPackageJson.description)).version(String(index_cliPackageJson.version)).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').addOption(new external_commander_namespaceObject.Option('--format <pretty|json>').hideHelp()).addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true).exitOverride();
9029
9204
  registerCreateCommand(extensionJs);
9030
9205
  registerDevCommand(extensionJs);
9031
9206
  registerStartCommand(extensionJs);
@@ -9037,10 +9212,11 @@ Cross-Browser Compatibility
9037
9212
  registerInstallCommand(extensionJs);
9038
9213
  registerTelemetryCommand(extensionJs);
9039
9214
  registerDoctorCommand(extensionJs);
9215
+ registerCapabilitiesCommand(extensionJs);
9040
9216
  function runAIHelp() {
9041
9217
  const format = resolveAIHelpFormatFromArgv(process.argv).trim().toLowerCase();
9042
9218
  if ('json' === format) {
9043
- console.log(JSON.stringify(programAIHelpJSON(String(cliPackageJson.version)), null, 2));
9219
+ console.log(JSON.stringify(programAIHelpJSON(String(index_cliPackageJson.version)), null, 2));
9044
9220
  exitAfterDrain(0);
9045
9221
  return;
9046
9222
  }
@@ -9059,13 +9235,26 @@ Cross-Browser Compatibility
9059
9235
  if (process.argv.includes('--ai-help')) runAIHelp();
9060
9236
  else {
9061
9237
  const argv = applyNoBrowserArgvShim(process.argv);
9062
- extensionJs.parseAsync(argv).then(()=>{
9063
- markCommandSuccess();
9064
- }).catch((err)=>{
9065
- markCommandFailure();
9066
- console.error(unhandledError(err));
9067
- process.exit(1);
9068
- });
9238
+ const asJson = wantsJsonOutput(argv);
9239
+ const commandName = resolveCommandFromArgv(argv) || 'extension';
9240
+ (async ()=>{
9241
+ try {
9242
+ await extensionJs.parseAsync(argv);
9243
+ markCommandSuccess();
9244
+ } catch (err) {
9245
+ if (isCommanderError(err)) {
9246
+ const exitCode = commanderExitCode(err);
9247
+ if (0 === exitCode) process.exit(0);
9248
+ markCommandFailure();
9249
+ if (asJson) writeStdoutFrame(commanderErrorEnvelope(err, commandName));
9250
+ process.exit(exitCode);
9251
+ }
9252
+ markCommandFailure();
9253
+ console.error(unhandledError(err));
9254
+ if (asJson && !isErrorFramed(err)) writeStdoutFrame(internalErrorEnvelope(err, commandName));
9255
+ process.exit(1);
9256
+ }
9257
+ })();
9069
9258
  }
9070
9259
  },
9071
9260
  "chrome-location2" (module) {
@@ -1,4 +1,8 @@
1
1
  export declare function stampReadyRdpPort(extensionOutputPath: string | undefined, rdpPort: number): void;
2
+ export declare function stampReadyBrowserLaunch(extensionOutputPath: string | undefined, details: {
3
+ profilePath?: string;
4
+ browserPid?: number;
5
+ }): void;
2
6
  export declare function stampReadyExtensionLoadRefused(extensionOutputPath: string | undefined, reason: string): void;
3
7
  export declare function stampReadyProfileLocked(extensionOutputPath: string | undefined, details: {
4
8
  message?: string;
@@ -11,6 +11,7 @@ interface ActResultLike {
11
11
  name?: unknown;
12
12
  message?: unknown;
13
13
  engine?: unknown;
14
+ code?: unknown;
14
15
  };
15
16
  }
16
17
  /**
@@ -0,0 +1,12 @@
1
+ import type { Command } from 'commander';
2
+ export declare const READY_CONTRACT_SCHEMA_VERSION = 2;
3
+ export declare function collectOutputJsonCommands(program: Command): string[];
4
+ export interface EngineCapabilities {
5
+ name: string;
6
+ version: string;
7
+ envelopeSchema: number;
8
+ readySchemaVersion: number;
9
+ outputJsonCommands: string[];
10
+ }
11
+ export declare function buildEngineCapabilities(program: Command): EngineCapabilities;
12
+ export declare function registerCapabilitiesCommand(program: Command): void;
@@ -0,0 +1,16 @@
1
+ import { ENVELOPE, type EnvelopeErrorRefs, type ErrorCode } from './messaging';
2
+ export declare function markErrorFramed(err: unknown): void;
3
+ export declare function isErrorFramed(err: unknown): boolean;
4
+ export declare function wantsJsonOutput(argv: string[]): boolean;
5
+ interface CommanderErrorLike {
6
+ code?: unknown;
7
+ exitCode?: unknown;
8
+ message?: unknown;
9
+ }
10
+ export declare function isCommanderError(err: unknown): err is CommanderErrorLike;
11
+ export declare function commanderExitCode(err: CommanderErrorLike): number;
12
+ export declare function commanderErrorEnvelope(err: CommanderErrorLike, command: string): ReturnType<typeof ENVELOPE.fail>;
13
+ export declare function internalErrorEnvelope(err: unknown, command: string): ReturnType<typeof ENVELOPE.fail>;
14
+ export declare function earlyExitEnvelope(command: string, code: ErrorCode, message: string, refs?: EnvelopeErrorRefs): ReturnType<typeof ENVELOPE.fail>;
15
+ export declare function writeStdoutFrame(frame: unknown): void;
16
+ export {};
@@ -177,6 +177,11 @@ declare const COMMAND_TABLE: readonly [{
177
177
  }];
178
178
  readonly description: 'Diagnose a dev session: ready contract, control channel, token, executor, browser';
179
179
  readonly supportsSourceInspection: false;
180
+ }, {
181
+ readonly name: 'capabilities';
182
+ readonly positionals: readonly [];
183
+ readonly description: 'Print the engine version, contract versions, and json-capable commands';
184
+ readonly supportsSourceInspection: false;
180
185
  }];
181
186
  export type CommandName = (typeof COMMAND_TABLE)[number]['name'];
182
187
  export interface CommandSpec extends CommandTableEntry {
@@ -54,6 +54,8 @@ export declare const CODES: {
54
54
  readonly E_SESSION_NOT_FOUND: 'E_SESSION_NOT_FOUND';
55
55
  readonly E_EVAL_REFUSED: 'E_EVAL_REFUSED';
56
56
  readonly E_TARGET_NOT_FOUND: 'E_TARGET_NOT_FOUND';
57
+ readonly E_HEADED_WINDOW_REQUIRED: 'E_HEADED_WINDOW_REQUIRED';
58
+ readonly E_USER_GESTURE_REQUIRED: 'E_USER_GESTURE_REQUIRED';
57
59
  readonly E_TIMEOUT: 'E_TIMEOUT';
58
60
  readonly E_PUBLISH_REJECTED: 'E_PUBLISH_REJECTED';
59
61
  readonly E_AUTH_REQUIRED: 'E_AUTH_REQUIRED';
@@ -149,12 +151,19 @@ export declare const CODES: {
149
151
  readonly E_UNINSTALL_NOOP: 'E_UNINSTALL_NOOP';
150
152
  };
151
153
  export type ErrorCode = (typeof CODES)[keyof typeof CODES];
154
+ export interface EnvelopeErrorRefs {
155
+ flag?: string;
156
+ command?: string;
157
+ path?: string;
158
+ version?: string;
159
+ }
152
160
  export interface EnvelopeError {
153
161
  code: ErrorCode;
154
162
  message: string;
155
163
  name?: string;
156
164
  engine?: string;
157
165
  hint?: string;
166
+ refs?: EnvelopeErrorRefs;
158
167
  }
159
168
  export interface Envelope<T = unknown> {
160
169
  schema: typeof ENVELOPE_SCHEMA;
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "extension": "./bin/extension.cjs"
39
39
  },
40
40
  "name": "extension",
41
- "version": "4.0.19",
41
+ "version": "4.0.20",
42
42
  "description": "The cross-browser extension framework. Build Chrome, Edge, Firefox, and Safari extensions with no build configuration.",
43
43
  "homepage": "https://extension.js.org/",
44
44
  "bugs": {
@@ -106,9 +106,9 @@
106
106
  "vivaldi-location2": "2.1.0",
107
107
  "waterfox-location": "2.1.0",
108
108
  "yandex-location": "2.1.0",
109
- "extension-create": "4.0.19",
110
- "extension-develop": "4.0.19",
111
- "extension-install": "4.0.19",
109
+ "extension-create": "4.0.20",
110
+ "extension-develop": "4.0.20",
111
+ "extension-install": "4.0.20",
112
112
  "commander": "^15.0.0",
113
113
  "pintor": "0.3.0",
114
114
  "semver": "^7.7.3",