extension 3.10.3 → 3.11.1

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
@@ -3,21 +3,7 @@ const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
3
  return "u" < typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
4
4
  }();
5
5
  "use strict";
6
- var __webpack_modules__ = {
7
- "extension-develop/package.json" (module) {
8
- module.exports = require("extension-develop/package.json");
9
- }
10
- };
11
- var __webpack_module_cache__ = {};
12
- function __webpack_require__(moduleId) {
13
- var cachedModule = __webpack_module_cache__[moduleId];
14
- if (void 0 !== cachedModule) return cachedModule.exports;
15
- var module = __webpack_module_cache__[moduleId] = {
16
- exports: {}
17
- };
18
- __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
19
- return module.exports;
20
- }
6
+ var __webpack_require__ = {};
21
7
  (()=>{
22
8
  __webpack_require__.n = (module)=>{
23
9
  var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
@@ -39,73 +25,72 @@ function __webpack_require__(moduleId) {
39
25
  __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
40
26
  })();
41
27
  var __webpack_exports__ = {};
42
- (()=>{
43
- const external_commander_namespaceObject = require("commander");
44
- const external_update_check_namespaceObject = require("update-check");
45
- var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
46
- const external_pintor_namespaceObject = require("pintor");
47
- var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
48
- function getLoggingPrefix(type) {
49
- const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
50
- if (isAuthor) {
51
- const base = 'error' === type ? 'ERROR Author says' : '►►► Author says';
52
- return external_pintor_default().brightMagenta(base);
53
- }
54
- if ('error' === type) return external_pintor_default().red('ERROR');
55
- if ('warn' === type) return external_pintor_default().brightYellow('►►►');
56
- if ('info' === type) return external_pintor_default().gray('►►►');
57
- return external_pintor_default().green('►►►');
28
+ const external_commander_namespaceObject = require("commander");
29
+ const external_update_check_namespaceObject = require("update-check");
30
+ var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
31
+ const external_pintor_namespaceObject = require("pintor");
32
+ var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
33
+ function getLoggingPrefix(type) {
34
+ const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
35
+ if (isAuthor) {
36
+ const base = 'error' === type ? 'ERROR Author says' : '►►► Author says';
37
+ return external_pintor_default().brightMagenta(base);
38
+ }
39
+ if ('error' === type) return external_pintor_default().red('ERROR');
40
+ if ('warn' === type) return external_pintor_default().brightYellow('►►►');
41
+ if ('info' === type) return external_pintor_default().gray('►►►');
42
+ return external_pintor_default().green('►►►');
43
+ }
44
+ const code = (text)=>external_pintor_default().blue(text);
45
+ const messages_arg = (text)=>external_pintor_default().gray(text);
46
+ const fmt = {
47
+ heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
48
+ label: (k)=>external_pintor_default().gray(k.toUpperCase()),
49
+ val: (v)=>external_pintor_default().underline(v),
50
+ code: (v)=>external_pintor_default().blue(v),
51
+ bullet: (s)=>`- ${s}`,
52
+ block (title, rows) {
53
+ const head = fmt.heading(title);
54
+ const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
55
+ return `${head}\n${body}`;
56
+ },
57
+ truncate (input, max = 800) {
58
+ const s = (()=>{
59
+ try {
60
+ return 'string' == typeof input ? input : JSON.stringify(input);
61
+ } catch {
62
+ return String(input);
63
+ }
64
+ })();
65
+ return s.length > max ? s.slice(0, max) + '…' : s;
58
66
  }
59
- const code = (text)=>external_pintor_default().blue(text);
60
- const messages_arg = (text)=>external_pintor_default().gray(text);
61
- const fmt = {
62
- heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
63
- label: (k)=>external_pintor_default().gray(k.toUpperCase()),
64
- val: (v)=>external_pintor_default().underline(v),
65
- code: (v)=>external_pintor_default().blue(v),
66
- bullet: (s)=>`- ${s}`,
67
- block (title, rows) {
68
- const head = fmt.heading(title);
69
- const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
70
- return `${head}\n${body}`;
71
- },
72
- truncate (input, max = 800) {
73
- const s = (()=>{
74
- try {
75
- return 'string' == typeof input ? input : JSON.stringify(input);
76
- } catch {
77
- return String(input);
78
- }
79
- })();
80
- return s.length > max ? s.slice(0, max) + '…' : s;
81
- }
82
- };
83
- const commandDescriptions = {
84
- create: 'Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
85
- dev: 'Starts the development server with hot reloading',
86
- start: 'Builds and starts the extension in production mode',
87
- preview: 'Previews the extension in production mode without building',
88
- build: 'Builds the extension for packaging/distribution',
89
- install: 'Installs a managed browser binary into Extension.js cache',
90
- uninstall: 'Removes managed browser binaries from Extension.js cache'
67
+ };
68
+ const commandDescriptions = {
69
+ create: 'Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
70
+ dev: 'Starts the development server with hot reloading',
71
+ start: 'Builds and starts the extension in production mode',
72
+ preview: 'Previews the extension in production mode without building',
73
+ build: 'Builds the extension for packaging/distribution',
74
+ install: 'Installs a managed browser binary into Extension.js cache',
75
+ uninstall: 'Removes managed browser binaries from Extension.js cache'
76
+ };
77
+ function unhandledError(err) {
78
+ const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : fmt.truncate(err);
79
+ return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
80
+ }
81
+ function updateFailed(err) {
82
+ return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String(err?.message || err))}`;
83
+ }
84
+ function checkUpdates(packageJson, update) {
85
+ const suffix = external_pintor_default().gray(`(version ${String(update.latest)} is available!)`);
86
+ const message = `${getLoggingPrefix('info')} 🧩 ${external_pintor_default().blue('Extension.js')} update available.\n\nYou are currently using version ${external_pintor_default().red(String(packageJson.version))}. Latest stable is ${external_pintor_default().green(String(update.latest))}.\nUpdate to the latest stable to get fixes and new features.`;
87
+ return {
88
+ suffix,
89
+ message
91
90
  };
92
- function unhandledError(err) {
93
- const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : fmt.truncate(err);
94
- return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
95
- }
96
- function updateFailed(err) {
97
- return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String(err?.message || err))}`;
98
- }
99
- function checkUpdates(packageJson, update) {
100
- const suffix = external_pintor_default().gray(`(version ${String(update.latest)} is available!)`);
101
- const message = `${getLoggingPrefix('info')} 🧩 ${external_pintor_default().blue('Extension.js')} update available.\n\nYou are currently using version ${external_pintor_default().red(String(packageJson.version))}. Latest stable is ${external_pintor_default().green(String(update.latest))}.\nUpdate to the latest stable to get fixes and new features.`;
102
- return {
103
- suffix,
104
- message
105
- };
106
- }
107
- function programUserHelp() {
108
- return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
91
+ }
92
+ function programUserHelp() {
93
+ return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
109
94
 
110
95
  Usage: extension [command] [options]
111
96
 
@@ -214,12 +199,12 @@ AI Assistants
214
199
 
215
200
  Report issues
216
201
  - ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
217
- }
218
- function unsupportedBrowserFlag(value, supported) {
219
- return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}. Supported: ${supported.join(', ')}.`;
220
- }
221
- function programAIHelp() {
222
- return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
202
+ }
203
+ function unsupportedBrowserFlag(value, supported) {
204
+ return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}. Supported: ${supported.join(', ')}.`;
205
+ }
206
+ function programAIHelp() {
207
+ return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
223
208
 
224
209
  Browser-Specific Configuration
225
210
  - Use browser prefixes in manifest.json for browser-specific fields:
@@ -367,677 +352,774 @@ Cross-Browser Compatibility
367
352
  - Use ${code('--polyfill')} flag to enable webextension-polyfill
368
353
  - Automatically handles browser API differences
369
354
  - Supports Chrome, Edge, Firefox with single codebase`;
370
- }
371
- function programAIHelpJSON(version) {
372
- return {
373
- version,
374
- commands: [
375
- {
376
- name: 'create',
377
- summary: commandDescriptions.create,
378
- supportsSourceInspection: false
379
- },
380
- {
381
- name: 'dev',
382
- summary: commandDescriptions.dev,
383
- supportsSourceInspection: true
384
- },
385
- {
386
- name: 'start',
387
- summary: commandDescriptions.start,
388
- supportsSourceInspection: false
389
- },
390
- {
391
- name: 'preview',
392
- summary: commandDescriptions.preview,
393
- supportsSourceInspection: false
394
- },
395
- {
396
- name: 'build',
397
- summary: commandDescriptions.build,
398
- supportsSourceInspection: false
399
- },
400
- {
401
- name: 'install',
402
- summary: commandDescriptions.install,
403
- supportsSourceInspection: false
404
- },
405
- {
406
- name: 'uninstall',
407
- summary: commandDescriptions.uninstall,
408
- supportsSourceInspection: false
409
- }
410
- ],
411
- globalOptions: [
412
- {
413
- name: '--ai-help',
414
- description: 'Show AI-assistant oriented help and tips'
415
- },
416
- {
417
- name: '--format',
418
- values: [
419
- 'pretty',
420
- 'json'
421
- ],
422
- default: 'pretty',
423
- description: 'Output format for --ai-help'
424
- },
425
- {
426
- name: '--no-telemetry',
427
- description: 'Disable anonymous telemetry for this run'
428
- }
429
- ],
430
- capabilities: {
431
- sourceInspection: {
432
- supportedIn: [
433
- 'dev'
434
- ],
435
- unsupportedIn: [
436
- 'start',
437
- 'preview',
438
- 'build',
439
- 'create',
440
- 'install',
441
- 'uninstall'
442
- ],
443
- notes: [
444
- '--source supports URL fallback to --starting-url or https://example.com',
445
- 'run-only preview mode does not perform source inspection'
446
- ]
447
- },
448
- logger: {
449
- levels: [
450
- 'off',
451
- 'error',
452
- 'warn',
453
- 'info',
454
- 'debug',
455
- 'trace',
456
- 'all'
457
- ],
458
- formats: [
459
- 'pretty',
460
- 'json',
461
- 'ndjson'
462
- ],
463
- notes: [
464
- 'centralized logger streams logs from multiple extension contexts',
465
- '--logs defaults to off unless explicitly enabled'
466
- ]
467
- },
468
- managedDependencies: {
469
- enforcement: 'guarded',
470
- trigger: 'when managed packages are declared in package.json and referenced in extension.config',
471
- action: 'print an error and abort'
472
- }
355
+ }
356
+ function programAIHelpJSON(version) {
357
+ return {
358
+ version,
359
+ commands: [
360
+ {
361
+ name: 'create',
362
+ summary: commandDescriptions.create,
363
+ supportsSourceInspection: false
473
364
  },
474
- examples: [
475
- 'extension --ai-help',
476
- 'extension --ai-help --format json',
477
- 'extension dev ./my-ext --source https://example.com --source-format json',
478
- 'extension dev ./my-ext --logs=info --log-format=json',
479
- 'extension dev ./my-ext --wait --browser=chromium --wait-format=json',
480
- 'extension start ./my-ext --wait --browser=chromium --wait-format=json',
481
- 'extension install chromium',
482
- 'extension install --where',
483
- 'extension uninstall --where',
484
- 'extension uninstall --all'
485
- ]
486
- };
487
- }
488
- function invalidAIHelpFormat(value) {
489
- return `${getLoggingPrefix('error')} Invalid value for ${code('--format')}: ${external_pintor_default().red(String(value))}\nAllowed values: ${messages_arg('pretty, json')}. Example: ${code('extension --ai-help --format json')}`;
490
- }
491
- function sourceInspectionNotSupported(command) {
492
- return `${getLoggingPrefix('error')} ${code(`extension ${command}`)} currently runs in run-only preview mode and does not support source inspection.\nUse ${code('extension dev --source <url>')} for source inspection features.`;
493
- }
494
- function removedNoRunnerFlag() {
495
- return `${getLoggingPrefix('error')} ${code('--no-runner')} was removed.\nUse ${code('--no-browser')} instead.`;
496
- }
497
- function noBrowserNotSupportedForCommand(command) {
498
- return `${getLoggingPrefix('error')} ${code('--no-browser')} is only supported for ${code('dev')}, ${code('start')}, and ${code('preview')}.\nReceived command: ${code(command || '(none)')}`;
499
- }
500
- const external_semver_namespaceObject = require("semver");
501
- const external_node_fs_namespaceObject = require("node:fs");
502
- var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
503
- const external_node_path_namespaceObject = require("node:path");
504
- var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
505
- let cachedPackageJson = null;
506
- function getCliPackageJson() {
507
- if (cachedPackageJson) return cachedPackageJson;
508
- const candidates = [
509
- external_node_path_default().resolve(__dirname, 'package.json'),
510
- external_node_path_default().resolve(__dirname, '..', 'package.json')
511
- ];
512
- for (const candidate of candidates)if (external_node_fs_default().existsSync(candidate)) {
513
- const content = external_node_fs_default().readFileSync(candidate, 'utf8');
514
- const parsed = JSON.parse(content);
515
- cachedPackageJson = parsed;
516
- return parsed;
517
- }
518
- throw new Error('Extension.js CLI package.json not found.');
365
+ {
366
+ name: 'dev',
367
+ summary: commandDescriptions.dev,
368
+ supportsSourceInspection: true
369
+ },
370
+ {
371
+ name: 'start',
372
+ summary: commandDescriptions.start,
373
+ supportsSourceInspection: false
374
+ },
375
+ {
376
+ name: 'preview',
377
+ summary: commandDescriptions.preview,
378
+ supportsSourceInspection: false
379
+ },
380
+ {
381
+ name: 'build',
382
+ summary: commandDescriptions.build,
383
+ supportsSourceInspection: false
384
+ },
385
+ {
386
+ name: 'install',
387
+ summary: commandDescriptions.install,
388
+ supportsSourceInspection: false
389
+ },
390
+ {
391
+ name: 'uninstall',
392
+ summary: commandDescriptions.uninstall,
393
+ supportsSourceInspection: false
394
+ }
395
+ ],
396
+ globalOptions: [
397
+ {
398
+ name: '--ai-help',
399
+ description: 'Show AI-assistant oriented help and tips'
400
+ },
401
+ {
402
+ name: '--format',
403
+ values: [
404
+ 'pretty',
405
+ 'json'
406
+ ],
407
+ default: 'pretty',
408
+ description: 'Output format for --ai-help'
409
+ },
410
+ {
411
+ name: '--no-telemetry',
412
+ description: 'Disable anonymous telemetry for this run'
413
+ }
414
+ ],
415
+ capabilities: {
416
+ sourceInspection: {
417
+ supportedIn: [
418
+ 'dev'
419
+ ],
420
+ unsupportedIn: [
421
+ 'start',
422
+ 'preview',
423
+ 'build',
424
+ 'create',
425
+ 'install',
426
+ 'uninstall'
427
+ ],
428
+ notes: [
429
+ '--source supports URL fallback to --starting-url or https://example.com',
430
+ 'run-only preview mode does not perform source inspection'
431
+ ]
432
+ },
433
+ logger: {
434
+ levels: [
435
+ 'off',
436
+ 'error',
437
+ 'warn',
438
+ 'info',
439
+ 'debug',
440
+ 'trace',
441
+ 'all'
442
+ ],
443
+ formats: [
444
+ 'pretty',
445
+ 'json',
446
+ 'ndjson'
447
+ ],
448
+ notes: [
449
+ 'centralized logger streams logs from multiple extension contexts',
450
+ '--logs defaults to off unless explicitly enabled'
451
+ ]
452
+ },
453
+ managedDependencies: {
454
+ enforcement: 'guarded',
455
+ trigger: 'when managed packages are declared in package.json and referenced in extension.config',
456
+ action: 'print an error and abort'
457
+ }
458
+ },
459
+ examples: [
460
+ 'extension --ai-help',
461
+ 'extension --ai-help --format json',
462
+ 'extension dev ./my-ext --source https://example.com --source-format json',
463
+ 'extension dev ./my-ext --logs=info --log-format=json',
464
+ 'extension dev ./my-ext --wait --browser=chromium --wait-format=json',
465
+ 'extension start ./my-ext --wait --browser=chromium --wait-format=json',
466
+ 'extension install chromium',
467
+ 'extension install --where',
468
+ 'extension uninstall --where',
469
+ 'extension uninstall --all'
470
+ ]
471
+ };
472
+ }
473
+ function invalidAIHelpFormat(value) {
474
+ return `${getLoggingPrefix('error')} Invalid value for ${code('--format')}: ${external_pintor_default().red(String(value))}\nAllowed values: ${messages_arg('pretty, json')}. Example: ${code('extension --ai-help --format json')}`;
475
+ }
476
+ function sourceInspectionNotSupported(command) {
477
+ return `${getLoggingPrefix('error')} ${code(`extension ${command}`)} currently runs in run-only preview mode and does not support source inspection.\nUse ${code('extension dev --source <url>')} for source inspection features.`;
478
+ }
479
+ function removedNoRunnerFlag() {
480
+ return `${getLoggingPrefix('error')} ${code('--no-runner')} was removed.\nUse ${code('--no-browser')} instead.`;
481
+ }
482
+ function noBrowserNotSupportedForCommand(command) {
483
+ return `${getLoggingPrefix('error')} ${code('--no-browser')} is only supported for ${code('dev')}, ${code('start')}, and ${code('preview')}.\nReceived command: ${code(command || '(none)')}`;
484
+ }
485
+ const external_semver_namespaceObject = require("semver");
486
+ const external_node_fs_namespaceObject = require("node:fs");
487
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
488
+ const external_node_path_namespaceObject = require("node:path");
489
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
490
+ let cachedPackageJson = null;
491
+ function getCliPackageJson() {
492
+ if (cachedPackageJson) return cachedPackageJson;
493
+ const candidates = [
494
+ external_node_path_default().resolve(__dirname, 'package.json'),
495
+ external_node_path_default().resolve(__dirname, '..', 'package.json')
496
+ ];
497
+ for (const candidate of candidates)if (external_node_fs_default().existsSync(candidate)) {
498
+ const content = external_node_fs_default().readFileSync(candidate, 'utf8');
499
+ const parsed = JSON.parse(content);
500
+ cachedPackageJson = parsed;
501
+ return parsed;
502
+ }
503
+ throw new Error('Extension.js CLI package.json not found.');
504
+ }
505
+ function isStableVersion(version) {
506
+ const v = external_semver_namespaceObject.parse(version);
507
+ return Boolean(v && 0 === v.prerelease.length);
508
+ }
509
+ async function check_updates_checkUpdates() {
510
+ const packageJson = getCliPackageJson();
511
+ let update = null;
512
+ try {
513
+ update = await external_update_check_default()(packageJson);
514
+ } catch (err) {
515
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(updateFailed(err));
516
+ }
517
+ if (update && isStableVersion(update.latest)) {
518
+ if (isStableVersion(packageJson.version)) return checkUpdates(packageJson, update);
519
+ }
520
+ return null;
521
+ }
522
+ const external_fs_namespaceObject = require("fs");
523
+ var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
524
+ const external_path_namespaceObject = require("path");
525
+ var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
526
+ const external_module_namespaceObject = require("module");
527
+ const extension_develop_runtime_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
528
+ function parseJsonSafe(filePath) {
529
+ return JSON.parse(external_fs_default().readFileSync(filePath, 'utf8'));
530
+ }
531
+ function resolveDevelopRootFromDir(dir) {
532
+ try {
533
+ const packageJsonPath = external_path_default().join(dir, 'package.json');
534
+ if (!external_fs_default().existsSync(packageJsonPath)) return;
535
+ const pkg = parseJsonSafe(packageJsonPath);
536
+ return pkg?.name === 'extension-develop' ? dir : void 0;
537
+ } catch {
538
+ return;
519
539
  }
520
- function isStableVersion(version) {
521
- const v = external_semver_namespaceObject.parse(version);
522
- return Boolean(v && 0 === v.prerelease.length);
540
+ }
541
+ function resolveWorkspaceDevelopRoot(startDir) {
542
+ let currentDir = external_path_default().resolve(startDir);
543
+ for(let depth = 0; depth < 8; depth += 1){
544
+ const candidate = external_path_default().join(currentDir, 'programs', 'develop');
545
+ const resolved = resolveDevelopRootFromDir(candidate);
546
+ if (resolved) return resolved;
547
+ const parent = external_path_default().dirname(currentDir);
548
+ if (parent === currentDir) break;
549
+ currentDir = parent;
523
550
  }
524
- async function check_updates_checkUpdates() {
525
- const packageJson = getCliPackageJson();
526
- let update = null;
551
+ }
552
+ function resolveInstalledDevelopRoot() {
553
+ try {
554
+ const packageJsonPath = extension_develop_runtime_require.resolve('extension-develop/package.json');
555
+ return resolveDevelopRootFromDir(external_path_default().dirname(packageJsonPath));
556
+ } catch {
527
557
  try {
528
- update = await external_update_check_default()(packageJson);
529
- } catch (err) {
530
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(updateFailed(err));
531
- }
532
- if (update && isStableVersion(update.latest)) {
533
- if (isStableVersion(packageJson.version)) return checkUpdates(packageJson, update);
558
+ const entryPath = extension_develop_runtime_require.resolve('extension-develop');
559
+ return resolveDevelopRootFromDir(external_path_default().dirname(external_path_default().dirname(entryPath)));
560
+ } catch {
561
+ return;
534
562
  }
535
- return null;
536
- }
537
- const external_fs_namespaceObject = require("fs");
538
- var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
539
- const external_path_namespaceObject = require("path");
540
- var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
541
- const external_node_os_namespaceObject = require("node:os");
542
- var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
543
- const external_node_crypto_namespaceObject = require("node:crypto");
544
- var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
545
- function _define_property(obj, key, value) {
546
- if (key in obj) Object.defineProperty(obj, key, {
547
- value: value,
548
- enumerable: true,
549
- configurable: true,
550
- writable: true
551
- });
552
- else obj[key] = value;
553
- return obj;
554
563
  }
555
- function isCI() {
556
- const v = process.env;
557
- return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
564
+ }
565
+ function resolvePreferredDevelopRoot(startDir) {
566
+ const workspaceRoot = resolveWorkspaceDevelopRoot(startDir);
567
+ if (workspaceRoot) return {
568
+ root: workspaceRoot,
569
+ source: 'workspace'
570
+ };
571
+ const envRoot = process.env.EXTENSION_DEVELOP_ROOT ? resolveDevelopRootFromDir(external_path_default().resolve(process.env.EXTENSION_DEVELOP_ROOT)) : void 0;
572
+ if (envRoot) return {
573
+ root: envRoot,
574
+ source: 'env'
575
+ };
576
+ const installedRoot = resolveInstalledDevelopRoot();
577
+ if (installedRoot) return {
578
+ root: installedRoot,
579
+ source: 'installed'
580
+ };
581
+ return {
582
+ root: void 0,
583
+ source: 'missing'
584
+ };
585
+ }
586
+ function resolveDevelopDistEntry(root) {
587
+ const base = external_path_default().join(root, 'dist', 'module');
588
+ const candidates = [
589
+ `${base}.cjs`,
590
+ `${base}.js`,
591
+ `${base}.mjs`,
592
+ base
593
+ ];
594
+ for (const candidate of candidates)if (external_fs_default().existsSync(candidate)) return candidate;
595
+ }
596
+ function resolveExtensionDevelopRoot(startDir = __dirname) {
597
+ const { root, source } = resolvePreferredDevelopRoot(startDir);
598
+ if (!root) throw new Error('Unable to locate the extension-develop runtime.');
599
+ process.env.EXTENSION_DEVELOP_ROOT = root;
600
+ if ('workspace' === source) process.env.EXTENSION_CREATE_DEVELOP_ROOT = root;
601
+ return root;
602
+ }
603
+ function resolveExtensionDevelopVersion(startDir = __dirname, fallbackVersion) {
604
+ try {
605
+ const root = resolveExtensionDevelopRoot(startDir);
606
+ const packageJsonPath = external_path_default().join(root, 'package.json');
607
+ const pkg = parseJsonSafe(packageJsonPath);
608
+ return pkg?.version || fallbackVersion || '0.0.0';
609
+ } catch {
610
+ return fallbackVersion || '0.0.0';
558
611
  }
559
- function configDir() {
560
- const xdg = process.env.XDG_CONFIG_HOME;
561
- if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
562
- if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
563
- return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
612
+ }
613
+ function loadExtensionDevelopModule(startDir = __dirname) {
614
+ const root = resolveExtensionDevelopRoot(startDir);
615
+ const { source } = resolvePreferredDevelopRoot(startDir);
616
+ const distEntry = resolveDevelopDistEntry(root);
617
+ if (distEntry) return extension_develop_runtime_require(distEntry);
618
+ if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
619
+ return extension_develop_runtime_require('extension-develop');
620
+ }
621
+ const external_node_os_namespaceObject = require("node:os");
622
+ var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
623
+ const external_node_crypto_namespaceObject = require("node:crypto");
624
+ var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
625
+ function _define_property(obj, key, value) {
626
+ if (key in obj) Object.defineProperty(obj, key, {
627
+ value: value,
628
+ enumerable: true,
629
+ configurable: true,
630
+ writable: true
631
+ });
632
+ else obj[key] = value;
633
+ return obj;
634
+ }
635
+ function isCI() {
636
+ const v = process.env;
637
+ return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
638
+ }
639
+ function configDir() {
640
+ const xdg = process.env.XDG_CONFIG_HOME;
641
+ if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
642
+ if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
643
+ return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
644
+ }
645
+ function telemetry_cacheDir() {
646
+ const xdg = process.env.XDG_CACHE_HOME;
647
+ if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
648
+ if ('win32' === process.platform) {
649
+ const base = process.env.LOCALAPPDATA || process.env.APPDATA;
650
+ if (base) return external_node_path_default().join(base, 'extensionjs', 'Cache');
651
+ }
652
+ if ('darwin' === process.platform) return external_node_path_default().join(external_node_os_default().homedir(), 'Library', 'Caches', 'extensionjs');
653
+ return null;
654
+ }
655
+ function ensureDir(p) {
656
+ try {
657
+ if (external_node_fs_default().existsSync(p)) return true;
658
+ external_node_fs_default().mkdirSync(p, {
659
+ recursive: true
660
+ });
661
+ return true;
662
+ } catch {
663
+ return false;
564
664
  }
565
- function telemetry_cacheDir() {
566
- const xdg = process.env.XDG_CACHE_HOME;
567
- if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
568
- if ('win32' === process.platform) {
569
- const base = process.env.LOCALAPPDATA || process.env.APPDATA;
570
- if (base) return external_node_path_default().join(base, 'extensionjs', 'Cache');
571
- }
572
- if ('darwin' === process.platform) return external_node_path_default().join(external_node_os_default().homedir(), 'Library', 'Caches', 'extensionjs');
573
- return null;
665
+ }
666
+ function ensureWritableDir(p) {
667
+ if (!ensureDir(p)) return false;
668
+ try {
669
+ external_node_fs_default().accessSync(p, external_node_fs_default().constants.W_OK);
670
+ const probe = external_node_path_default().join(p, `.write-test-${process.pid}-${Date.now()}`);
671
+ external_node_fs_default().writeFileSync(probe, 'ok', 'utf8');
672
+ external_node_fs_default().unlinkSync(probe);
673
+ return true;
674
+ } catch {
675
+ return false;
574
676
  }
575
- function ensureDir(p) {
576
- try {
577
- if (external_node_fs_default().existsSync(p)) return true;
578
- external_node_fs_default().mkdirSync(p, {
579
- recursive: true
580
- });
581
- return true;
582
- } catch {
583
- return false;
584
- }
677
+ }
678
+ function loadOrCreateId(file) {
679
+ try {
680
+ if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
681
+ } catch {}
682
+ const id = external_node_crypto_default().randomUUID();
683
+ if (ensureDir(external_node_path_default().dirname(file))) try {
684
+ external_node_fs_default().writeFileSync(file, id, 'utf8');
685
+ } catch {}
686
+ return id;
687
+ }
688
+ function telemetryCandidates() {
689
+ const candidates = [
690
+ configDir(),
691
+ telemetry_cacheDir(),
692
+ external_node_path_default().join(external_node_os_default().tmpdir(), 'extensionjs'),
693
+ external_node_path_default().join(process.cwd(), '.cache', 'extensionjs')
694
+ ].filter(Boolean);
695
+ return Array.from(new Set(candidates));
696
+ }
697
+ function resolveTelemetryStorage() {
698
+ for (const base of telemetryCandidates()){
699
+ const telemetryDir = external_node_path_default().join(base, 'telemetry');
700
+ if (ensureWritableDir(telemetryDir)) return {
701
+ telemetryDir,
702
+ auditFile: external_node_path_default().join(telemetryDir, 'events.jsonl'),
703
+ idFile: external_node_path_default().join(telemetryDir, 'anonymous-id'),
704
+ consentFile: external_node_path_default().join(telemetryDir, 'consent')
705
+ };
585
706
  }
586
- function ensureWritableDir(p) {
587
- if (!ensureDir(p)) return false;
707
+ return null;
708
+ }
709
+ const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
710
+ const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
711
+ const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
712
+ const DEFAULT_POSTHOG_KEY = process.env.POSTHOG_KEY || 'phc_Np5x3Jg3h2V7kTFtNch2uz6QBaWDycQpIidzX5PetaN';
713
+ const DEFAULT_POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://us.i.posthog.com';
714
+ class Telemetry {
715
+ track(event, props = {}) {
716
+ if (this.disabled || !this.storage) return;
717
+ const payload = {
718
+ event,
719
+ properties: {
720
+ ...this.common,
721
+ ...props,
722
+ $ip: null
723
+ },
724
+ distinct_id: this.anonId
725
+ };
588
726
  try {
589
- external_node_fs_default().accessSync(p, external_node_fs_default().constants.W_OK);
590
- const probe = external_node_path_default().join(p, `.write-test-${process.pid}-${Date.now()}`);
591
- external_node_fs_default().writeFileSync(probe, 'ok', 'utf8');
592
- external_node_fs_default().unlinkSync(probe);
593
- return true;
727
+ external_node_fs_default().appendFileSync(this.storage.auditFile, JSON.stringify(payload) + '\n');
594
728
  } catch {
595
- return false;
729
+ this.disabled = true;
730
+ return;
596
731
  }
597
- }
598
- function loadOrCreateId(file) {
732
+ if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
733
+ if (!this.apiKey || !this.host) return;
734
+ if ('cli_shutdown' === event) return void this.buffer.push(payload);
735
+ this.buffer.push(payload);
736
+ if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
737
+ if (!this.timer) this.timer = setTimeout(()=>{
738
+ this.timer = null;
739
+ this.flush();
740
+ }, DEFAULT_FLUSH_INTERVAL);
741
+ }
742
+ async flush() {
743
+ if (this.disabled || !this.apiKey || !this.host) return;
744
+ if (0 === this.buffer.length) return;
745
+ const batch = this.buffer.splice(0, this.buffer.length);
599
746
  try {
600
- if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
601
- } catch {}
602
- const id = external_node_crypto_default().randomUUID();
603
- if (ensureDir(external_node_path_default().dirname(file))) try {
604
- external_node_fs_default().writeFileSync(file, id, 'utf8');
747
+ const ac = new AbortController();
748
+ const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
749
+ const url = new URL('/capture/', this.host);
750
+ await fetch(url.toString(), {
751
+ method: 'POST',
752
+ headers: {
753
+ 'content-type': 'application/json'
754
+ },
755
+ body: JSON.stringify({
756
+ api_key: this.apiKey,
757
+ batch: batch.map((e)=>({
758
+ event: e.event,
759
+ properties: e.properties,
760
+ distinct_id: e.distinct_id
761
+ }))
762
+ }),
763
+ signal: ac.signal,
764
+ keepalive: true
765
+ }).catch(()=>{});
766
+ clearTimeout(t);
605
767
  } catch {}
606
- return id;
607
- }
608
- function telemetryCandidates() {
609
- const candidates = [
610
- configDir(),
611
- telemetry_cacheDir(),
612
- external_node_path_default().join(external_node_os_default().tmpdir(), 'extensionjs'),
613
- external_node_path_default().join(process.cwd(), '.cache', 'extensionjs')
614
- ].filter(Boolean);
615
- return Array.from(new Set(candidates));
616
768
  }
617
- function resolveTelemetryStorage() {
618
- for (const base of telemetryCandidates()){
619
- const telemetryDir = external_node_path_default().join(base, 'telemetry');
620
- if (ensureWritableDir(telemetryDir)) return {
621
- telemetryDir,
622
- auditFile: external_node_path_default().join(telemetryDir, 'events.jsonl'),
623
- idFile: external_node_path_default().join(telemetryDir, 'anonymous-id'),
624
- consentFile: external_node_path_default().join(telemetryDir, 'consent')
625
- };
769
+ shutdown() {}
770
+ constructor(init){
771
+ _define_property(this, "anonId", void 0);
772
+ _define_property(this, "common", void 0);
773
+ _define_property(this, "debug", void 0);
774
+ _define_property(this, "disabled", void 0);
775
+ _define_property(this, "apiKey", void 0);
776
+ _define_property(this, "host", void 0);
777
+ _define_property(this, "storage", null);
778
+ _define_property(this, "buffer", []);
779
+ _define_property(this, "timer", null);
780
+ this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
781
+ this.disabled = Boolean(init.disabled);
782
+ this.anonId = 'disabled';
783
+ if (!this.disabled) {
784
+ this.storage = resolveTelemetryStorage();
785
+ if (this.storage) this.anonId = loadOrCreateId(this.storage.idFile);
786
+ else this.disabled = true;
626
787
  }
627
- return null;
628
- }
629
- const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
630
- const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
631
- const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
632
- const DEFAULT_POSTHOG_KEY = process.env.POSTHOG_KEY || 'phc_Np5x3Jg3h2V7kTFtNch2uz6QBaWDycQpIidzX5PetaN';
633
- const DEFAULT_POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://us.i.posthog.com';
634
- class Telemetry {
635
- track(event, props = {}) {
636
- if (this.disabled || !this.storage) return;
637
- const payload = {
638
- event,
639
- properties: {
640
- ...this.common,
641
- ...props,
642
- $ip: null
643
- },
644
- distinct_id: this.anonId
645
- };
646
- try {
647
- external_node_fs_default().appendFileSync(this.storage.auditFile, JSON.stringify(payload) + '\n');
648
- } catch {
649
- this.disabled = true;
650
- return;
651
- }
652
- if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
653
- if (!this.apiKey || !this.host) return;
654
- if ('cli_shutdown' === event) return void this.buffer.push(payload);
655
- this.buffer.push(payload);
656
- if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
657
- if (!this.timer) this.timer = setTimeout(()=>{
658
- this.timer = null;
659
- this.flush();
660
- }, DEFAULT_FLUSH_INTERVAL);
661
- }
662
- async flush() {
663
- if (this.disabled || !this.apiKey || !this.host) return;
664
- if (0 === this.buffer.length) return;
665
- const batch = this.buffer.splice(0, this.buffer.length);
788
+ this.common = {
789
+ app: init.app,
790
+ version: init.version,
791
+ os: process.platform,
792
+ arch: process.arch,
793
+ node: process.versions.node,
794
+ is_ci: isCI(),
795
+ schema_version: 2
796
+ };
797
+ this.apiKey = init.apiKey || DEFAULT_POSTHOG_KEY;
798
+ this.host = init.host || DEFAULT_POSTHOG_HOST;
799
+ if (!this.disabled && this.storage) {
800
+ const consentPath = this.storage.consentFile;
666
801
  try {
667
- const ac = new AbortController();
668
- const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
669
- const url = new URL('/capture/', this.host);
670
- await fetch(url.toString(), {
671
- method: 'POST',
672
- headers: {
673
- 'content-type': 'application/json'
674
- },
675
- body: JSON.stringify({
676
- api_key: this.apiKey,
677
- batch: batch.map((e)=>({
678
- event: e.event,
679
- properties: e.properties,
680
- distinct_id: e.distinct_id
681
- }))
682
- }),
683
- signal: ac.signal,
684
- keepalive: true
685
- }).catch(()=>{});
686
- clearTimeout(t);
802
+ if (!external_node_fs_default().existsSync(consentPath)) {
803
+ external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
804
+ this.track('cli_telemetry_consent', {
805
+ value: 'implicit_opt_in'
806
+ });
807
+ console.log(`${external_pintor_default().gray('►►►')} Telemetry is enabled for Extension.js. To opt out, run with --no-telemetry. Learn more in TELEMETRY.md.`);
808
+ }
687
809
  } catch {}
688
810
  }
689
- shutdown() {}
690
- constructor(init){
691
- _define_property(this, "anonId", void 0);
692
- _define_property(this, "common", void 0);
693
- _define_property(this, "debug", void 0);
694
- _define_property(this, "disabled", void 0);
695
- _define_property(this, "apiKey", void 0);
696
- _define_property(this, "host", void 0);
697
- _define_property(this, "storage", null);
698
- _define_property(this, "buffer", []);
699
- _define_property(this, "timer", null);
700
- this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
701
- this.disabled = Boolean(init.disabled);
702
- this.anonId = 'disabled';
703
- if (!this.disabled) {
704
- this.storage = resolveTelemetryStorage();
705
- if (this.storage) this.anonId = loadOrCreateId(this.storage.idFile);
706
- else this.disabled = true;
707
- }
708
- this.common = {
709
- app: init.app,
710
- version: init.version,
711
- os: process.platform,
712
- arch: process.arch,
713
- node: process.versions.node,
714
- is_ci: isCI(),
715
- schema_version: 2
716
- };
717
- this.apiKey = init.apiKey || DEFAULT_POSTHOG_KEY;
718
- this.host = init.host || DEFAULT_POSTHOG_HOST;
719
- if (!this.disabled && this.storage) {
720
- const consentPath = this.storage.consentFile;
721
- try {
722
- if (!external_node_fs_default().existsSync(consentPath)) {
723
- external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
724
- this.track('cli_telemetry_consent', {
725
- value: 'implicit_opt_in'
726
- });
727
- console.log(`${external_pintor_default().gray('►►►')} Telemetry is enabled for Extension.js. To opt out, run with --no-telemetry. Learn more in TELEMETRY.md.`);
728
- }
729
- } catch {}
730
- }
731
- }
732
811
  }
733
- function summarizeManifest(manifest) {
734
- const mv = manifest?.manifest_version === 2 ? 2 : 3;
735
- const permissions = Array.isArray(manifest?.permissions) ? manifest.permissions : [];
736
- const optionalPermissions = Array.isArray(manifest?.optional_permissions) ? manifest.optional_permissions : [];
737
- const hostPermissions = Array.isArray(manifest?.host_permissions) ? manifest.host_permissions : [];
738
- const usesAllUrls = [
739
- ...permissions,
740
- ...hostPermissions
741
- ].includes('<all_urls>');
742
- const usesDeclarativeNetRequest = permissions.includes('declarativeNetRequest') || permissions.includes('declarativeNetRequestWithHostAccess');
743
- const background = manifest?.background;
744
- let backgroundType = 'none';
745
- if (3 === mv && background?.service_worker) backgroundType = 'service_worker';
746
- else if (2 === mv && (Array.isArray(background?.scripts) && background.scripts.length > 0 || background?.page)) backgroundType = 'event_page';
747
- const contentScriptsCount = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts.length : 0;
748
- const hasDevtoolsPage = Boolean(manifest?.devtools_page);
749
- const hasActionPopup = Boolean(manifest?.action?.default_popup);
750
- return {
751
- mv,
752
- permissions_count: permissions.length,
753
- optional_permissions_count: optionalPermissions.length,
754
- host_permissions_count: hostPermissions.length,
755
- uses_all_urls: usesAllUrls,
756
- uses_declarative_net_request: usesDeclarativeNetRequest,
757
- background_type: backgroundType,
758
- content_scripts_count: contentScriptsCount,
759
- has_devtools_page: hasDevtoolsPage,
760
- has_action_popup: hasActionPopup
761
- };
812
+ }
813
+ function summarizeManifest(manifest) {
814
+ const mv = manifest?.manifest_version === 2 ? 2 : 3;
815
+ const permissions = Array.isArray(manifest?.permissions) ? manifest.permissions : [];
816
+ const optionalPermissions = Array.isArray(manifest?.optional_permissions) ? manifest.optional_permissions : [];
817
+ const hostPermissions = Array.isArray(manifest?.host_permissions) ? manifest.host_permissions : [];
818
+ const usesAllUrls = [
819
+ ...permissions,
820
+ ...hostPermissions
821
+ ].includes('<all_urls>');
822
+ const usesDeclarativeNetRequest = permissions.includes('declarativeNetRequest') || permissions.includes('declarativeNetRequestWithHostAccess');
823
+ const background = manifest?.background;
824
+ let backgroundType = 'none';
825
+ if (3 === mv && background?.service_worker) backgroundType = 'service_worker';
826
+ else if (2 === mv && (Array.isArray(background?.scripts) && background.scripts.length > 0 || background?.page)) backgroundType = 'event_page';
827
+ const contentScriptsCount = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts.length : 0;
828
+ const hasDevtoolsPage = Boolean(manifest?.devtools_page);
829
+ const hasActionPopup = Boolean(manifest?.action?.default_popup);
830
+ return {
831
+ mv,
832
+ permissions_count: permissions.length,
833
+ optional_permissions_count: optionalPermissions.length,
834
+ host_permissions_count: hostPermissions.length,
835
+ uses_all_urls: usesAllUrls,
836
+ uses_declarative_net_request: usesDeclarativeNetRequest,
837
+ background_type: backgroundType,
838
+ content_scripts_count: contentScriptsCount,
839
+ has_devtools_page: hasDevtoolsPage,
840
+ has_action_popup: hasActionPopup
841
+ };
842
+ }
843
+ function safeReadJson(filePath) {
844
+ try {
845
+ if (!external_node_fs_default().existsSync(filePath)) return null;
846
+ return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf8'));
847
+ } catch {
848
+ return null;
762
849
  }
763
- function safeReadJson(filePath) {
850
+ }
851
+ function findNearestPackageJson(startPath) {
852
+ let current = external_node_path_default().resolve(startPath);
853
+ for(let i = 0; i < 6; i += 1){
854
+ const candidate = external_node_path_default().join(current, 'package.json');
855
+ if (external_node_fs_default().existsSync(candidate)) return candidate;
856
+ const parent = external_node_path_default().dirname(current);
857
+ if (parent === current) break;
858
+ current = parent;
859
+ }
860
+ return null;
861
+ }
862
+ function getDependencies(pkg) {
863
+ return {
864
+ ...pkg.dependencies || {},
865
+ ...pkg.devDependencies || {},
866
+ ...pkg.peerDependencies || {}
867
+ };
868
+ }
869
+ function hasDependency(pkg, dependencyId) {
870
+ const deps = getDependencies(pkg);
871
+ return Boolean(deps[dependencyId]);
872
+ }
873
+ function detectPackageManager(projectRoot, pkg) {
874
+ const declared = String(pkg.packageManager || '').trim().toLowerCase();
875
+ if (declared.startsWith('pnpm@')) return 'pnpm';
876
+ if (declared.startsWith('yarn@')) return 'yarn';
877
+ if (declared.startsWith('npm@')) return 'npm';
878
+ if (declared.startsWith('bun@')) return 'bun';
879
+ if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';
880
+ if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'yarn.lock'))) return 'yarn';
881
+ if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'package-lock.json'))) return 'npm';
882
+ if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'bun.lockb'))) return 'bun';
883
+ if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'bun.lock'))) return 'bun';
884
+ const userAgent = String(process.env.npm_config_user_agent || '').toLowerCase();
885
+ if (userAgent.includes('pnpm')) return 'pnpm';
886
+ if (userAgent.includes('yarn')) return 'yarn';
887
+ if (userAgent.includes('bun')) return 'bun';
888
+ if (userAgent.includes('npm')) return 'npm';
889
+ return 'unknown';
890
+ }
891
+ function detectFrameworkPrimary(pkg) {
892
+ if (hasDependency(pkg, 'preact')) return 'preact';
893
+ if (hasDependency(pkg, 'react')) return 'react';
894
+ if (hasDependency(pkg, 'vue')) return 'vue';
895
+ if (hasDependency(pkg, 'svelte')) return 'svelte';
896
+ if (hasDependency(pkg, 'solid-js')) return 'solid';
897
+ if (hasDependency(pkg, '@angular/core')) return 'angular';
898
+ return 'unknown';
899
+ }
900
+ function detectMonorepo(projectRoot, pkg) {
901
+ return Boolean(pkg.workspaces || external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'pnpm-workspace.yaml')) || external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'turbo.json')));
902
+ }
903
+ function toPermissionBucket(count) {
904
+ if (count <= 0) return '0';
905
+ if (count <= 3) return '1_3';
906
+ if (count <= 10) return '4_10';
907
+ return '11_plus';
908
+ }
909
+ function toManifestSurface(summary) {
910
+ if (!summary) return 'unknown';
911
+ const surfaces = [
912
+ summary.has_action_popup,
913
+ summary.has_devtools_page,
914
+ summary.content_scripts_count > 0,
915
+ 'none' !== summary.background_type
916
+ ].filter(Boolean).length;
917
+ if (surfaces > 1) return 'multi_surface';
918
+ if (summary.has_action_popup) return 'action_popup';
919
+ if (summary.has_devtools_page) return 'devtools';
920
+ if (summary.content_scripts_count > 0) return "content_scripts";
921
+ if ('none' !== summary.background_type) return 'background_only';
922
+ return 'other';
923
+ }
924
+ function collectProjectProfile(projectRoot, summary) {
925
+ const packageJsonPath = findNearestPackageJson(projectRoot);
926
+ const pkg = (packageJsonPath ? safeReadJson(packageJsonPath) : null) || {
927
+ dependencies: {},
928
+ devDependencies: {},
929
+ peerDependencies: {}
930
+ };
931
+ const resolvedRoot = packageJsonPath ? external_node_path_default().dirname(packageJsonPath) : projectRoot;
932
+ const hasPackageSignals = Boolean(packageJsonPath);
933
+ const hasManifestSignals = Boolean(summary);
934
+ if (!hasPackageSignals && !hasManifestSignals) return null;
935
+ return {
936
+ package_manager: detectPackageManager(resolvedRoot, pkg),
937
+ framework_primary: detectFrameworkPrimary(pkg),
938
+ has_typescript: hasDependency(pkg, "typescript") || external_node_fs_default().existsSync(external_node_path_default().join(resolvedRoot, 'tsconfig.json')),
939
+ is_monorepo: detectMonorepo(resolvedRoot, pkg),
940
+ has_next_dependency: hasDependency(pkg, 'next'),
941
+ has_turbo_dependency: hasDependency(pkg, 'turbo') || external_node_fs_default().existsSync(external_node_path_default().join(resolvedRoot, 'turbo.json')),
942
+ manifest_surface: toManifestSurface(summary),
943
+ permissions_bucket: toPermissionBucket(summary?.permissions_count || 0),
944
+ host_permissions_bucket: toPermissionBucket(summary?.host_permissions_count || 0)
945
+ };
946
+ }
947
+ function isTelemetryDisabledFromArgs(argv) {
948
+ return argv.includes('--no-telemetry');
949
+ }
950
+ const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
951
+ function findManifestJson(projectRoot) {
952
+ const stack = [
953
+ projectRoot
954
+ ];
955
+ while(stack.length > 0){
956
+ const dir = stack.pop();
957
+ if (!dir) continue;
958
+ let entries;
764
959
  try {
765
- if (!external_node_fs_default().existsSync(filePath)) return null;
766
- return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf8'));
960
+ entries = external_fs_default().readdirSync(dir, {
961
+ withFileTypes: true
962
+ });
767
963
  } catch {
768
- return null;
964
+ continue;
769
965
  }
770
- }
771
- function findNearestPackageJson(startPath) {
772
- let current = external_node_path_default().resolve(startPath);
773
- for(let i = 0; i < 6; i += 1){
774
- const candidate = external_node_path_default().join(current, 'package.json');
775
- if (external_node_fs_default().existsSync(candidate)) return candidate;
776
- const parent = external_node_path_default().dirname(current);
777
- if (parent === current) break;
778
- current = parent;
966
+ for (const entry of entries){
967
+ if (entry.isFile() && 'manifest.json' === entry.name) return external_path_default().join(dir, entry.name);
968
+ if (entry.isDirectory() && !entry.name.startsWith('.') && 'node_modules' !== entry.name && 'dist' !== entry.name) stack.push(external_path_default().join(dir, entry.name));
779
969
  }
780
- return null;
781
970
  }
782
- function getDependencies(pkg) {
783
- return {
784
- ...pkg.dependencies || {},
785
- ...pkg.devDependencies || {},
786
- ...pkg.peerDependencies || {}
787
- };
788
- }
789
- function hasDependency(pkg, dependencyId) {
790
- const deps = getDependencies(pkg);
791
- return Boolean(deps[dependencyId]);
792
- }
793
- function detectPackageManager(projectRoot, pkg) {
794
- const declared = String(pkg.packageManager || '').trim().toLowerCase();
795
- if (declared.startsWith('pnpm@')) return 'pnpm';
796
- if (declared.startsWith('yarn@')) return 'yarn';
797
- if (declared.startsWith('npm@')) return 'npm';
798
- if (declared.startsWith('bun@')) return 'bun';
799
- if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';
800
- if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'yarn.lock'))) return 'yarn';
801
- if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'package-lock.json'))) return 'npm';
802
- if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'bun.lockb'))) return 'bun';
803
- if (external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'bun.lock'))) return 'bun';
804
- const userAgent = String(process.env.npm_config_user_agent || '').toLowerCase();
805
- if (userAgent.includes('pnpm')) return 'pnpm';
806
- if (userAgent.includes('yarn')) return 'yarn';
807
- if (userAgent.includes('bun')) return 'bun';
808
- if (userAgent.includes('npm')) return 'npm';
809
- return 'unknown';
810
- }
811
- function detectFrameworkPrimary(pkg) {
812
- if (hasDependency(pkg, 'preact')) return 'preact';
813
- if (hasDependency(pkg, 'react')) return 'react';
814
- if (hasDependency(pkg, 'vue')) return 'vue';
815
- if (hasDependency(pkg, 'svelte')) return 'svelte';
816
- if (hasDependency(pkg, 'solid-js')) return 'solid';
817
- if (hasDependency(pkg, '@angular/core')) return 'angular';
818
- return 'unknown';
819
- }
820
- function detectMonorepo(projectRoot, pkg) {
821
- return Boolean(pkg.workspaces || external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'pnpm-workspace.yaml')) || external_node_fs_default().existsSync(external_node_path_default().join(projectRoot, 'turbo.json')));
822
- }
823
- function toPermissionBucket(count) {
824
- if (count <= 0) return '0';
825
- if (count <= 3) return '1_3';
826
- if (count <= 10) return '4_10';
827
- return '11_plus';
828
- }
829
- function toManifestSurface(summary) {
830
- if (!summary) return 'unknown';
831
- const surfaces = [
832
- summary.has_action_popup,
833
- summary.has_devtools_page,
834
- summary.content_scripts_count > 0,
835
- 'none' !== summary.background_type
836
- ].filter(Boolean).length;
837
- if (surfaces > 1) return 'multi_surface';
838
- if (summary.has_action_popup) return 'action_popup';
839
- if (summary.has_devtools_page) return 'devtools';
840
- if (summary.content_scripts_count > 0) return "content_scripts";
841
- if ('none' !== summary.background_type) return 'background_only';
842
- return 'other';
843
- }
844
- function collectProjectProfile(projectRoot, summary) {
845
- const packageJsonPath = findNearestPackageJson(projectRoot);
846
- const pkg = (packageJsonPath ? safeReadJson(packageJsonPath) : null) || {
847
- dependencies: {},
848
- devDependencies: {},
849
- peerDependencies: {}
850
- };
851
- const resolvedRoot = packageJsonPath ? external_node_path_default().dirname(packageJsonPath) : projectRoot;
852
- const hasPackageSignals = Boolean(packageJsonPath);
853
- const hasManifestSignals = Boolean(summary);
854
- if (!hasPackageSignals && !hasManifestSignals) return null;
855
- return {
856
- package_manager: detectPackageManager(resolvedRoot, pkg),
857
- framework_primary: detectFrameworkPrimary(pkg),
858
- has_typescript: hasDependency(pkg, "typescript") || external_node_fs_default().existsSync(external_node_path_default().join(resolvedRoot, 'tsconfig.json')),
859
- is_monorepo: detectMonorepo(resolvedRoot, pkg),
860
- has_next_dependency: hasDependency(pkg, 'next'),
861
- has_turbo_dependency: hasDependency(pkg, 'turbo') || external_node_fs_default().existsSync(external_node_path_default().join(resolvedRoot, 'turbo.json')),
862
- manifest_surface: toManifestSurface(summary),
863
- permissions_bucket: toPermissionBucket(summary?.permissions_count || 0),
864
- host_permissions_bucket: toPermissionBucket(summary?.host_permissions_count || 0)
865
- };
866
- }
867
- function isTelemetryDisabledFromArgs(argv) {
868
- return argv.includes('--no-telemetry');
869
- }
870
- const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
871
- function findManifestJson(projectRoot) {
872
- const stack = [
873
- projectRoot
874
- ];
875
- while(stack.length > 0){
876
- const dir = stack.pop();
877
- if (!dir) continue;
878
- let entries;
879
- try {
880
- entries = external_fs_default().readdirSync(dir, {
881
- withFileTypes: true
882
- });
883
- } catch {
884
- continue;
885
- }
886
- for (const entry of entries){
887
- if (entry.isFile() && 'manifest.json' === entry.name) return external_path_default().join(dir, entry.name);
888
- if (entry.isDirectory() && !entry.name.startsWith('.') && 'node_modules' !== entry.name && 'dist' !== entry.name) stack.push(external_path_default().join(dir, entry.name));
889
- }
890
- }
891
- return null;
892
- }
893
- const telemetry_cli_telemetry = new Telemetry({
894
- app: 'extension',
895
- version: getCliPackageJson().version,
896
- disabled: telemetryDisabled
971
+ return null;
972
+ }
973
+ const telemetry_cli_telemetry = new Telemetry({
974
+ app: 'extension',
975
+ version: getCliPackageJson().version,
976
+ disabled: telemetryDisabled
977
+ });
978
+ function detectInvokedCommand(argv) {
979
+ const known = new Set([
980
+ 'create',
981
+ 'dev',
982
+ 'start',
983
+ 'preview',
984
+ 'build',
985
+ 'install',
986
+ 'uninstall',
987
+ 'cleanup',
988
+ 'unknown'
989
+ ]);
990
+ return argv.slice(2).find((a)=>known.has(a)) || 'unknown';
991
+ }
992
+ if (!telemetryDisabled) {
993
+ const startedAt = Date.now();
994
+ let shutdownTracked = false;
995
+ const invoked = detectInvokedCommand(process.argv);
996
+ telemetry_cli_telemetry.track('cli_boot', {
997
+ command_guess: invoked
897
998
  });
898
- function detectInvokedCommand(argv) {
899
- const known = new Set([
900
- 'create',
901
- 'dev',
902
- 'start',
903
- 'preview',
904
- 'build',
905
- 'install',
906
- 'uninstall',
907
- 'cleanup',
908
- 'unknown'
909
- ]);
910
- return argv.slice(2).find((a)=>known.has(a)) || 'unknown';
911
- }
912
- if (!telemetryDisabled) {
913
- const startedAt = Date.now();
914
- let shutdownTracked = false;
915
- const invoked = detectInvokedCommand(process.argv);
916
- telemetry_cli_telemetry.track('cli_boot', {
917
- command_guess: invoked
999
+ const manifestPath = findManifestJson(process.cwd());
1000
+ let manifestSummary = null;
1001
+ if (manifestPath) try {
1002
+ const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
1003
+ const json = JSON.parse(raw);
1004
+ manifestSummary = summarizeManifest(json);
1005
+ telemetry_cli_telemetry.track('manifest_summary', manifestSummary);
1006
+ } catch {}
1007
+ const projectProfile = collectProjectProfile(process.cwd(), manifestSummary);
1008
+ if (projectProfile) telemetry_cli_telemetry.track('project_profile', projectProfile);
1009
+ process.on('beforeExit', async function() {
1010
+ if (shutdownTracked) return;
1011
+ shutdownTracked = true;
1012
+ telemetry_cli_telemetry.track('cli_shutdown', {
1013
+ command_guess: invoked,
1014
+ duration_ms: Date.now() - startedAt,
1015
+ exit_code: process.exitCode ?? 0
918
1016
  });
919
- const manifestPath = findManifestJson(process.cwd());
920
- let manifestSummary = null;
921
- if (manifestPath) try {
922
- const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
923
- const json = JSON.parse(raw);
924
- manifestSummary = summarizeManifest(json);
925
- telemetry_cli_telemetry.track('manifest_summary', manifestSummary);
926
- } catch {}
927
- const projectProfile = collectProjectProfile(process.cwd(), manifestSummary);
928
- if (projectProfile) telemetry_cli_telemetry.track('project_profile', projectProfile);
929
- process.on('beforeExit', async function() {
930
- if (shutdownTracked) return;
931
- shutdownTracked = true;
932
- telemetry_cli_telemetry.track('cli_shutdown', {
933
- command_guess: invoked,
934
- duration_ms: Date.now() - startedAt,
935
- exit_code: process.exitCode ?? 0
936
- });
937
- await telemetry_cli_telemetry.flush();
938
- });
939
- process.on('uncaughtException', function(err) {
940
- telemetry_cli_telemetry.track('cli_error', {
941
- command_guess: invoked,
942
- error_name: String(err?.name || 'Error').slice(0, 64)
943
- });
1017
+ await telemetry_cli_telemetry.flush();
1018
+ });
1019
+ process.on('uncaughtException', function(err) {
1020
+ telemetry_cli_telemetry.track('cli_error', {
1021
+ command_guess: invoked,
1022
+ error_name: String(err?.name || 'Error').slice(0, 64)
944
1023
  });
945
- process.on('unhandledRejection', function(reason) {
946
- telemetry_cli_telemetry.track('cli_error', {
947
- command_guess: invoked,
948
- error_name: String(reason?.name || 'PromiseRejection').slice(0, 64)
949
- });
1024
+ });
1025
+ process.on('unhandledRejection', function(reason) {
1026
+ telemetry_cli_telemetry.track('cli_error', {
1027
+ command_guess: invoked,
1028
+ error_name: String(reason?.name || 'PromiseRejection').slice(0, 64)
950
1029
  });
951
- }
952
- const external_module_namespaceObject = require("module");
953
- function primaryReason(automationReasons, shippingReasons) {
954
- if (automationReasons.length > 0) return automationReasons[0];
955
- if (shippingReasons.length > 0) return shippingReasons[0];
956
- return 'none';
957
- }
958
- function collectWorkflowProfile(context) {
959
- const shippingReasons = [];
960
- const automationReasons = [];
961
- if ('build' === context.command || 'start' === context.command || 'preview' === context.command) shippingReasons.push('production_command');
962
- if (context.isMultiBrowser) shippingReasons.push('multi_browser');
963
- if ('zip' === context.artifactKind || 'source_zip' === context.artifactKind || 'zip_and_source' === context.artifactKind) shippingReasons.push('artifact_output');
964
- if (context.companionExtensionsProvided) shippingReasons.push('companion_extensions');
965
- if (context.isWaitMode || context.isNoBrowserMode) automationReasons.push('headless_sync');
966
- if (context.usesMachineReadableOutput) automationReasons.push('machine_readable_output');
967
- if (context.sourceInspectionRequested) automationReasons.push('source_inspection');
968
- if (context.whereMode) automationReasons.push('where_mode');
969
- const hasAutomationIntent = automationReasons.length > 0;
970
- const hasShippingIntent = shippingReasons.length > 0;
971
- return {
972
- workflow_cohort: hasAutomationIntent ? 'automation_heavy' : hasShippingIntent ? 'shipping' : 'local_only',
973
- has_shipping_intent: hasShippingIntent,
974
- has_automation_intent: hasAutomationIntent,
975
- shipping_signal_count: shippingReasons.length,
976
- automation_signal_count: automationReasons.length,
977
- primary_workflow_signal: primaryReason(automationReasons, shippingReasons),
978
- package_manager: context.packageManager,
979
- framework_primary: context.frameworkPrimary,
980
- has_next_dependency: context.hasNextDependency,
981
- has_turbo_dependency: context.hasTurboDependency
982
- };
983
- }
984
- require("node:url");
985
- function parseOptionalBoolean(value) {
986
- if (void 0 === value) return true;
987
- const normalized = String(value).trim().toLowerCase();
988
- return ![
989
- 'false',
990
- '0',
991
- 'no',
992
- 'off'
993
- ].includes(normalized);
994
- }
995
- const vendors = (browser)=>{
996
- const value = browser ?? 'chromium';
997
- return 'all' === value ? [
998
- 'chrome',
999
- 'edge',
1000
- 'firefox'
1001
- ] : String(value).split(',');
1030
+ });
1031
+ }
1032
+ function primaryReason(automationReasons, shippingReasons) {
1033
+ if (automationReasons.length > 0) return automationReasons[0];
1034
+ if (shippingReasons.length > 0) return shippingReasons[0];
1035
+ return 'none';
1036
+ }
1037
+ function collectWorkflowProfile(context) {
1038
+ const shippingReasons = [];
1039
+ const automationReasons = [];
1040
+ if ('build' === context.command || 'start' === context.command || 'preview' === context.command) shippingReasons.push('production_command');
1041
+ if (context.isMultiBrowser) shippingReasons.push('multi_browser');
1042
+ if ('zip' === context.artifactKind || 'source_zip' === context.artifactKind || 'zip_and_source' === context.artifactKind) shippingReasons.push('artifact_output');
1043
+ if (context.companionExtensionsProvided) shippingReasons.push('companion_extensions');
1044
+ if (context.isWaitMode || context.isNoBrowserMode) automationReasons.push('headless_sync');
1045
+ if (context.usesMachineReadableOutput) automationReasons.push('machine_readable_output');
1046
+ if (context.sourceInspectionRequested) automationReasons.push('source_inspection');
1047
+ if (context.whereMode) automationReasons.push('where_mode');
1048
+ const hasAutomationIntent = automationReasons.length > 0;
1049
+ const hasShippingIntent = shippingReasons.length > 0;
1050
+ return {
1051
+ workflow_cohort: hasAutomationIntent ? 'automation_heavy' : hasShippingIntent ? 'shipping' : 'local_only',
1052
+ has_shipping_intent: hasShippingIntent,
1053
+ has_automation_intent: hasAutomationIntent,
1054
+ shipping_signal_count: shippingReasons.length,
1055
+ automation_signal_count: automationReasons.length,
1056
+ primary_workflow_signal: primaryReason(automationReasons, shippingReasons),
1057
+ package_manager: context.packageManager,
1058
+ framework_primary: context.frameworkPrimary,
1059
+ has_next_dependency: context.hasNextDependency,
1060
+ has_turbo_dependency: context.hasTurboDependency
1002
1061
  };
1003
- function validateVendorsOrExit(vendorsList, onInvalid) {
1004
- const supported = [
1005
- 'chrome',
1006
- 'edge',
1007
- 'firefox',
1008
- 'chromium',
1009
- 'chromium-based',
1010
- 'gecko-based',
1011
- 'firefox-based'
1012
- ];
1013
- for (const v of vendorsList)if (!supported.includes(v)) {
1014
- onInvalid(v, supported);
1015
- process.exit(1);
1016
- }
1062
+ }
1063
+ require("node:url");
1064
+ function parseOptionalBoolean(value) {
1065
+ if (void 0 === value) return true;
1066
+ const normalized = String(value).trim().toLowerCase();
1067
+ return ![
1068
+ 'false',
1069
+ '0',
1070
+ 'no',
1071
+ 'off'
1072
+ ].includes(normalized);
1073
+ }
1074
+ const vendors = (browser)=>{
1075
+ const value = browser ?? 'chromium';
1076
+ return 'all' === value ? [
1077
+ 'chrome',
1078
+ 'edge',
1079
+ 'firefox'
1080
+ ] : String(value).split(',');
1081
+ };
1082
+ function validateVendorsOrExit(vendorsList, onInvalid) {
1083
+ const supported = [
1084
+ 'chrome',
1085
+ 'edge',
1086
+ 'firefox',
1087
+ 'chromium',
1088
+ 'chromium-based',
1089
+ 'gecko-based',
1090
+ 'firefox-based'
1091
+ ];
1092
+ for (const v of vendorsList)if (!supported.includes(v)) {
1093
+ onInvalid(v, supported);
1094
+ process.exit(1);
1017
1095
  }
1018
- const create_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
1019
- function registerCreateCommand(program, telemetry) {
1020
- program.command('create').arguments('<project-name|project-path>').usage('create <project-name|project-path> [options]').description(commandDescriptions.create).option('-t, --template <template-name>', 'specify a template for the created project').option('--install [boolean]', 'whether or not to install the dependencies after creating the project (enabled by default)', parseOptionalBoolean, true).action(async function(pathOrRemoteUrl, { template, install }) {
1021
- const startedAt = Date.now();
1022
- const templateValue = String(template || 'default');
1023
- const isRemoteTemplate = /^https?:/i.test(templateValue);
1024
- const workflowProfile = collectWorkflowProfile({
1025
- command: 'create',
1026
- isRemoteInput: isRemoteTemplate
1027
- });
1028
- telemetry.track('workflow_profile', {
1029
- command: 'create',
1030
- ...workflowProfile
1031
- });
1032
- telemetry.track('cli_command_start', {
1033
- command: 'create',
1034
- template: templateValue,
1035
- template_source: isRemoteTemplate ? 'remote' : 'built_in',
1036
- install: Boolean(install),
1037
- ...workflowProfile
1038
- });
1039
- try {
1040
- if (!process.env.EXTENSION_CREATE_DEVELOP_ROOT) try {
1096
+ }
1097
+ const create_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
1098
+ function registerCreateCommand(program, telemetry) {
1099
+ program.command('create').arguments('<project-name|project-path>').usage('create <project-name|project-path> [options]').description(commandDescriptions.create).option('-t, --template <template-name>', 'specify a template for the created project').option('--install [boolean]', 'whether or not to install the dependencies after creating the project (enabled by default)', parseOptionalBoolean, true).action(async function(pathOrRemoteUrl, { template, install }) {
1100
+ const startedAt = Date.now();
1101
+ const templateValue = String(template || 'default');
1102
+ const isRemoteTemplate = /^https?:/i.test(templateValue);
1103
+ const workflowProfile = collectWorkflowProfile({
1104
+ command: 'create',
1105
+ isRemoteInput: isRemoteTemplate
1106
+ });
1107
+ telemetry.track('workflow_profile', {
1108
+ command: 'create',
1109
+ ...workflowProfile
1110
+ });
1111
+ telemetry.track('cli_command_start', {
1112
+ command: 'create',
1113
+ template: templateValue,
1114
+ template_source: isRemoteTemplate ? 'remote' : 'built_in',
1115
+ install: Boolean(install),
1116
+ ...workflowProfile
1117
+ });
1118
+ try {
1119
+ if (!process.env.EXTENSION_CREATE_DEVELOP_ROOT) try {
1120
+ process.env.EXTENSION_CREATE_DEVELOP_ROOT = resolveExtensionDevelopRoot();
1121
+ } catch {
1122
+ try {
1041
1123
  const developPkg = create_require.resolve('extension-develop/package.json');
1042
1124
  process.env.EXTENSION_CREATE_DEVELOP_ROOT = external_path_namespaceObject.dirname(developPkg);
1043
1125
  } catch {
@@ -1046,965 +1128,957 @@ Cross-Browser Compatibility
1046
1128
  process.env.EXTENSION_CREATE_DEVELOP_ROOT = external_path_namespaceObject.dirname(external_path_namespaceObject.dirname(developEntry));
1047
1129
  } catch {}
1048
1130
  }
1049
- const { extensionCreate } = await import("extension-create");
1050
- await extensionCreate(pathOrRemoteUrl, {
1051
- template,
1052
- install,
1053
- cliVersion: getCliPackageJson().version
1054
- });
1055
- telemetry.track('cli_command_finish', {
1056
- command: 'create',
1057
- duration_ms: Date.now() - startedAt,
1058
- success: true,
1059
- exit_code: 0,
1060
- ...workflowProfile
1061
- });
1062
- } catch (err) {
1063
- telemetry.track('cli_command_finish', {
1064
- command: 'create',
1065
- duration_ms: Date.now() - startedAt,
1066
- success: false,
1067
- exit_code: 1,
1068
- ...workflowProfile
1069
- });
1070
- throw err;
1071
1131
  }
1072
- });
1073
- }
1074
- function isHttpUrl(value) {
1075
- if (!value) return false;
1076
- return /^https?:\/\//i.test(value);
1077
- }
1078
- function resolveProjectPath(pathOrRemoteUrl) {
1079
- if (!pathOrRemoteUrl) return process.cwd();
1080
- return external_node_path_namespaceObject.isAbsolute(pathOrRemoteUrl) ? pathOrRemoteUrl : external_node_path_namespaceObject.join(process.cwd(), pathOrRemoteUrl);
1081
- }
1082
- function parseWaitTimeoutMs(value) {
1083
- const fallback = 60000;
1084
- if ('number' == typeof value && Number.isFinite(value) && value > 0) return Math.floor(value);
1085
- if ('string' == typeof value && value.trim()) {
1086
- const parsed = parseInt(value, 10);
1087
- if (Number.isFinite(parsed) && parsed > 0) return parsed;
1088
- }
1089
- return fallback;
1090
- }
1091
- function parseWaitFormat(value) {
1092
- return 'json' === value ? 'json' : 'pretty';
1093
- }
1094
- function isProcessLikelyAlive(pid) {
1095
- if ('number' != typeof pid || !Number.isInteger(pid) || pid <= 0) return true;
1096
- try {
1097
- process.kill(pid, 0);
1098
- return true;
1099
- } catch {
1100
- return false;
1101
- }
1102
- }
1103
- function isFreshContractPayload(payload, maxAgeMs) {
1104
- const candidates = [
1105
- payload.ts,
1106
- payload.compiledAt,
1107
- payload.startedAt
1108
- ];
1109
- for (const candidate of candidates){
1110
- if (!candidate) continue;
1111
- const stamp = Date.parse(candidate);
1112
- if (Number.isFinite(stamp)) return Date.now() - stamp <= maxAgeMs;
1132
+ const { extensionCreate } = await import("extension-create");
1133
+ await extensionCreate(pathOrRemoteUrl, {
1134
+ template,
1135
+ install,
1136
+ cliVersion: getCliPackageJson().version
1137
+ });
1138
+ telemetry.track('cli_command_finish', {
1139
+ command: 'create',
1140
+ duration_ms: Date.now() - startedAt,
1141
+ success: true,
1142
+ exit_code: 0,
1143
+ ...workflowProfile
1144
+ });
1145
+ } catch (err) {
1146
+ telemetry.track('cli_command_finish', {
1147
+ command: 'create',
1148
+ duration_ms: Date.now() - startedAt,
1149
+ success: false,
1150
+ exit_code: 1,
1151
+ ...workflowProfile
1152
+ });
1153
+ throw err;
1113
1154
  }
1155
+ });
1156
+ }
1157
+ function isHttpUrl(value) {
1158
+ if (!value) return false;
1159
+ return /^https?:\/\//i.test(value);
1160
+ }
1161
+ function resolveProjectPath(pathOrRemoteUrl) {
1162
+ if (!pathOrRemoteUrl) return process.cwd();
1163
+ return external_node_path_namespaceObject.isAbsolute(pathOrRemoteUrl) ? pathOrRemoteUrl : external_node_path_namespaceObject.join(process.cwd(), pathOrRemoteUrl);
1164
+ }
1165
+ function parseWaitTimeoutMs(value) {
1166
+ const fallback = 60000;
1167
+ if ('number' == typeof value && Number.isFinite(value) && value > 0) return Math.floor(value);
1168
+ if ('string' == typeof value && value.trim()) {
1169
+ const parsed = parseInt(value, 10);
1170
+ if (Number.isFinite(parsed) && parsed > 0) return parsed;
1171
+ }
1172
+ return fallback;
1173
+ }
1174
+ function parseWaitFormat(value) {
1175
+ return 'json' === value ? 'json' : 'pretty';
1176
+ }
1177
+ function isProcessLikelyAlive(pid) {
1178
+ if ('number' != typeof pid || !Number.isInteger(pid) || pid <= 0) return true;
1179
+ try {
1180
+ process.kill(pid, 0);
1181
+ return true;
1182
+ } catch {
1114
1183
  return false;
1115
1184
  }
1116
- async function waitForReadyContract(options) {
1117
- const readyPath = external_node_path_namespaceObject.join(options.projectPath, 'dist', 'extension-js', options.browser, 'ready.json');
1118
- const start = Date.now();
1119
- while(Date.now() - start < options.timeoutMs){
1120
- if (external_node_fs_namespaceObject.existsSync(readyPath)) try {
1121
- const payload = JSON.parse(external_node_fs_namespaceObject.readFileSync(readyPath, 'utf8'));
1122
- const isLive = isProcessLikelyAlive(payload.pid);
1123
- const isFresh = isFreshContractPayload(payload, options.timeoutMs);
1124
- if (payload.command !== options.command) {
1185
+ }
1186
+ function isFreshContractPayload(payload, maxAgeMs) {
1187
+ const candidates = [
1188
+ payload.ts,
1189
+ payload.compiledAt,
1190
+ payload.startedAt
1191
+ ];
1192
+ for (const candidate of candidates){
1193
+ if (!candidate) continue;
1194
+ const stamp = Date.parse(candidate);
1195
+ if (Number.isFinite(stamp)) return Date.now() - stamp <= maxAgeMs;
1196
+ }
1197
+ return false;
1198
+ }
1199
+ async function waitForReadyContract(options) {
1200
+ const readyPath = external_node_path_namespaceObject.join(options.projectPath, 'dist', 'extension-js', options.browser, 'ready.json');
1201
+ const start = Date.now();
1202
+ while(Date.now() - start < options.timeoutMs){
1203
+ if (external_node_fs_namespaceObject.existsSync(readyPath)) try {
1204
+ const payload = JSON.parse(external_node_fs_namespaceObject.readFileSync(readyPath, 'utf8'));
1205
+ const isLive = isProcessLikelyAlive(payload.pid);
1206
+ const isFresh = isFreshContractPayload(payload, options.timeoutMs);
1207
+ if (payload.command !== options.command) {
1208
+ await new Promise((resolve)=>setTimeout(resolve, 250));
1209
+ continue;
1210
+ }
1211
+ if (!isLive) {
1212
+ if ('start' !== options.command || !isFresh) {
1125
1213
  await new Promise((resolve)=>setTimeout(resolve, 250));
1126
1214
  continue;
1127
1215
  }
1128
- if (!isLive) {
1129
- if ('start' !== options.command || !isFresh) {
1130
- await new Promise((resolve)=>setTimeout(resolve, 250));
1131
- continue;
1132
- }
1133
- }
1134
- if ('ready' === payload.status) return payload;
1135
- if ('error' === payload.status) {
1136
- if (!isLive && 'start' !== options.command) {
1137
- await new Promise((resolve)=>setTimeout(resolve, 250));
1138
- continue;
1139
- }
1140
- const detail = payload.message || payload.errors?.[0] || 'unknown error';
1141
- throw new Error(String(detail));
1216
+ }
1217
+ if ('ready' === payload.status) return payload;
1218
+ if ('error' === payload.status) {
1219
+ if (!isLive && 'start' !== options.command) {
1220
+ await new Promise((resolve)=>setTimeout(resolve, 250));
1221
+ continue;
1142
1222
  }
1143
- } catch (error) {
1144
- if (error instanceof Error) throw error;
1145
- throw new Error(String(error));
1223
+ const detail = payload.message || payload.errors?.[0] || 'unknown error';
1224
+ throw new Error(String(detail));
1146
1225
  }
1147
- await new Promise((resolve)=>setTimeout(resolve, 250));
1226
+ } catch (error) {
1227
+ if (error instanceof Error) throw error;
1228
+ throw new Error(String(error));
1148
1229
  }
1149
- throw new Error(`Timed out waiting for ready contract at ${readyPath} (${options.timeoutMs} ms)`);
1230
+ await new Promise((resolve)=>setTimeout(resolve, 250));
1150
1231
  }
1151
- async function runWaitMode(options) {
1152
- if (isHttpUrl(options.pathOrRemoteUrl)) throw new Error('--wait requires a local project path (remote URLs are not supported)');
1153
- const projectPath = resolveProjectPath(options.pathOrRemoteUrl);
1154
- const timeoutMs = parseWaitTimeoutMs(options.waitTimeout);
1155
- const format = parseWaitFormat(options.waitFormat);
1156
- const results = [];
1157
- for (const browser of options.browsers){
1158
- const payload = await waitForReadyContract({
1159
- command: options.command,
1160
- projectPath,
1161
- browser,
1162
- timeoutMs
1163
- });
1164
- results.push({
1165
- ...payload,
1166
- browser
1167
- });
1168
- }
1169
- return {
1170
- projectPath,
1232
+ throw new Error(`Timed out waiting for ready contract at ${readyPath} (${options.timeoutMs} ms)`);
1233
+ }
1234
+ async function runWaitMode(options) {
1235
+ if (isHttpUrl(options.pathOrRemoteUrl)) throw new Error('--wait requires a local project path (remote URLs are not supported)');
1236
+ const projectPath = resolveProjectPath(options.pathOrRemoteUrl);
1237
+ const timeoutMs = parseWaitTimeoutMs(options.waitTimeout);
1238
+ const format = parseWaitFormat(options.waitFormat);
1239
+ const results = [];
1240
+ for (const browser of options.browsers){
1241
+ const payload = await waitForReadyContract({
1171
1242
  command: options.command,
1172
- timeoutMs,
1173
- format,
1174
- browsers: options.browsers,
1175
- results
1176
- };
1177
- }
1178
- function normalizeSourceOption(source, startingUrl) {
1179
- if (!source) return;
1180
- const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
1181
- const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
1182
- if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
1183
- return String(source);
1184
- }
1185
- function normalizeEnum(value, allowed) {
1186
- if (null == value) return;
1187
- const normalized = String(value).trim().toLowerCase();
1188
- if (!normalized) return;
1189
- return allowed.includes(normalized) ? normalized : void 0;
1190
- }
1191
- function normalizeSourceFormatOption(params) {
1192
- const allowed = [
1193
- 'pretty',
1194
- 'json',
1195
- 'ndjson'
1196
- ];
1197
- const sourceFormat = normalizeEnum(params.sourceFormat, allowed);
1198
- if (sourceFormat) return sourceFormat;
1199
- const logFormat = normalizeEnum(params.logFormat, allowed);
1200
- if (logFormat) return logFormat;
1201
- if (params.sourceEnabled) return 'json';
1202
- }
1203
- function normalizeSourceRedactOption(sourceRedact, sourceFormat) {
1204
- const allowed = [
1205
- 'off',
1206
- 'safe',
1207
- 'strict'
1208
- ];
1209
- const normalized = normalizeEnum(sourceRedact, allowed);
1210
- if (normalized) return normalized;
1211
- if (sourceFormat && 'pretty' !== sourceFormat) return 'safe';
1212
- return 'off';
1213
- }
1214
- function normalizeSourceMaxBytesOption(value) {
1215
- if (null == value) return;
1216
- const parsed = 'number' == typeof value ? value : Number(String(value).trim());
1217
- if (!Number.isFinite(parsed) || parsed < 0) return;
1218
- return Math.floor(parsed);
1219
- }
1220
- function normalizeSourceIncludeShadowOption(value, sourceEnabled) {
1221
- const allowed = [
1222
- 'off',
1223
- 'open-only',
1224
- 'all'
1225
- ];
1226
- const normalized = normalizeEnum(value, allowed);
1227
- if (normalized) return normalized;
1228
- if (sourceEnabled) return 'open-only';
1229
- }
1230
- function normalizeSourceMetaOption(value, sourceEnabled) {
1231
- if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1232
- if (sourceEnabled) return true;
1233
- }
1234
- function normalizeSourceTreeOption(value, sourceEnabled) {
1235
- const allowed = [
1236
- 'off',
1237
- 'root-only'
1238
- ];
1239
- const normalized = normalizeEnum(value, allowed);
1240
- if (normalized) return normalized;
1241
- }
1242
- function normalizeSourceConsoleOption(value, sourceEnabled) {
1243
- if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1244
- }
1245
- function normalizeSourceDomOption(value, watchSource) {
1246
- if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1247
- if (watchSource) return true;
1248
- }
1249
- function normalizeSourceProbeOption(raw) {
1250
- if (null == raw) return;
1251
- if (Array.isArray(raw)) {
1252
- const values = raw.map((value)=>String(value).trim()).filter((value)=>value.length > 0);
1253
- return values.length > 0 ? values : void 0;
1254
- }
1255
- if (0 === String(raw).trim().length) return;
1256
- const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
1257
- return values.length > 0 ? values : void 0;
1258
- }
1259
- function normalizeSourceDiffOption(value, watchSource) {
1260
- if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1261
- if (watchSource) return true;
1262
- }
1263
- function parseLogContexts(raw) {
1264
- if (!raw || 0 === String(raw).trim().length) return;
1265
- if ('all' === String(raw).trim().toLowerCase()) return;
1266
- const allowed = [
1267
- 'background',
1268
- 'content',
1269
- 'page',
1270
- 'sidebar',
1271
- 'popup',
1272
- 'options',
1273
- 'devtools'
1274
- ];
1275
- const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
1276
- return values.length > 0 ? values : void 0;
1243
+ projectPath,
1244
+ browser,
1245
+ timeoutMs
1246
+ });
1247
+ results.push({
1248
+ ...payload,
1249
+ browser
1250
+ });
1277
1251
  }
1278
- function parseExtensionsList(raw) {
1279
- if (!raw || 0 === String(raw).trim().length) return;
1280
- const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
1252
+ return {
1253
+ projectPath,
1254
+ command: options.command,
1255
+ timeoutMs,
1256
+ format,
1257
+ browsers: options.browsers,
1258
+ results
1259
+ };
1260
+ }
1261
+ function normalizeSourceOption(source, startingUrl) {
1262
+ if (!source) return;
1263
+ const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
1264
+ const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
1265
+ if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
1266
+ return String(source);
1267
+ }
1268
+ function normalizeEnum(value, allowed) {
1269
+ if (null == value) return;
1270
+ const normalized = String(value).trim().toLowerCase();
1271
+ if (!normalized) return;
1272
+ return allowed.includes(normalized) ? normalized : void 0;
1273
+ }
1274
+ function normalizeSourceFormatOption(params) {
1275
+ const allowed = [
1276
+ 'pretty',
1277
+ 'json',
1278
+ 'ndjson'
1279
+ ];
1280
+ const sourceFormat = normalizeEnum(params.sourceFormat, allowed);
1281
+ if (sourceFormat) return sourceFormat;
1282
+ const logFormat = normalizeEnum(params.logFormat, allowed);
1283
+ if (logFormat) return logFormat;
1284
+ if (params.sourceEnabled) return 'json';
1285
+ }
1286
+ function normalizeSourceRedactOption(sourceRedact, sourceFormat) {
1287
+ const allowed = [
1288
+ 'off',
1289
+ 'safe',
1290
+ 'strict'
1291
+ ];
1292
+ const normalized = normalizeEnum(sourceRedact, allowed);
1293
+ if (normalized) return normalized;
1294
+ if (sourceFormat && 'pretty' !== sourceFormat) return 'safe';
1295
+ return 'off';
1296
+ }
1297
+ function normalizeSourceMaxBytesOption(value) {
1298
+ if (null == value) return;
1299
+ const parsed = 'number' == typeof value ? value : Number(String(value).trim());
1300
+ if (!Number.isFinite(parsed) || parsed < 0) return;
1301
+ return Math.floor(parsed);
1302
+ }
1303
+ function normalizeSourceIncludeShadowOption(value, sourceEnabled) {
1304
+ const allowed = [
1305
+ 'off',
1306
+ 'open-only',
1307
+ 'all'
1308
+ ];
1309
+ const normalized = normalizeEnum(value, allowed);
1310
+ if (normalized) return normalized;
1311
+ if (sourceEnabled) return 'open-only';
1312
+ }
1313
+ function normalizeSourceMetaOption(value, sourceEnabled) {
1314
+ if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1315
+ if (sourceEnabled) return true;
1316
+ }
1317
+ function normalizeSourceTreeOption(value, sourceEnabled) {
1318
+ const allowed = [
1319
+ 'off',
1320
+ 'root-only'
1321
+ ];
1322
+ const normalized = normalizeEnum(value, allowed);
1323
+ if (normalized) return normalized;
1324
+ }
1325
+ function normalizeSourceConsoleOption(value, sourceEnabled) {
1326
+ if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1327
+ }
1328
+ function normalizeSourceDomOption(value, watchSource) {
1329
+ if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1330
+ if (watchSource) return true;
1331
+ }
1332
+ function normalizeSourceProbeOption(raw) {
1333
+ if (null == raw) return;
1334
+ if (Array.isArray(raw)) {
1335
+ const values = raw.map((value)=>String(value).trim()).filter((value)=>value.length > 0);
1281
1336
  return values.length > 0 ? values : void 0;
1282
1337
  }
1283
- const dev_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
1284
- function registerDevCommand(program, telemetry) {
1285
- program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', '\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --wait wait for ready contract and exit\n --wait-format pretty|json output for wait mode\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('-b, --browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--no-open', 'do not open the browser automatically (default: open)').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('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes (defaults to true when --source is present)', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).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('--wait-format <pretty|json>', 'output format for --wait results (default: pretty)').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
1286
- if (devOptions.author || devOptions['authorMode']) {
1287
- process.env.EXTENSION_AUTHOR_MODE = 'true';
1288
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1289
- }
1290
- const cmdStart = Date.now();
1291
- const list = vendors(browser);
1292
- const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1293
- const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1294
- const workflowProfile = collectWorkflowProfile({
1338
+ if (0 === String(raw).trim().length) return;
1339
+ const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
1340
+ return values.length > 0 ? values : void 0;
1341
+ }
1342
+ function normalizeSourceDiffOption(value, watchSource) {
1343
+ if (void 0 !== value) return 0 === String(value).trim().length ? true : Boolean(value);
1344
+ if (watchSource) return true;
1345
+ }
1346
+ function parseLogContexts(raw) {
1347
+ if (!raw || 0 === String(raw).trim().length) return;
1348
+ if ('all' === String(raw).trim().toLowerCase()) return;
1349
+ const allowed = [
1350
+ 'background',
1351
+ 'content',
1352
+ 'page',
1353
+ 'sidebar',
1354
+ 'popup',
1355
+ 'options',
1356
+ 'devtools'
1357
+ ];
1358
+ const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
1359
+ return values.length > 0 ? values : void 0;
1360
+ }
1361
+ function parseExtensionsList(raw) {
1362
+ if (!raw || 0 === String(raw).trim().length) return;
1363
+ const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
1364
+ return values.length > 0 ? values : void 0;
1365
+ }
1366
+ function registerDevCommand(program, telemetry) {
1367
+ program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', '\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --wait wait for ready contract and exit\n --wait-format pretty|json output for wait mode\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('-b, --browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--no-open', 'do not open the browser automatically (default: open)').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('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes (defaults to true when --source is present)', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).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('--wait-format <pretty|json>', 'output format for --wait results (default: pretty)').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
1368
+ if (devOptions.author || devOptions['authorMode']) {
1369
+ process.env.EXTENSION_AUTHOR_MODE = 'true';
1370
+ if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1371
+ }
1372
+ const cmdStart = Date.now();
1373
+ const list = vendors(browser);
1374
+ const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1375
+ const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1376
+ const workflowProfile = collectWorkflowProfile({
1377
+ command: 'dev',
1378
+ isMultiBrowser: list.length > 1,
1379
+ isRemoteInput: isRemoteInput,
1380
+ isWaitMode: Boolean(devOptions.wait),
1381
+ isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1382
+ usesMachineReadableOutput: 'json' === devOptions.waitFormat || 'json' === devOptions.logFormat || 'ndjson' === devOptions.logFormat || 'json' === devOptions.sourceFormat || 'ndjson' === devOptions.sourceFormat,
1383
+ sourceInspectionRequested: Boolean(devOptions.source || devOptions.watchSource),
1384
+ companionExtensionsProvided: Boolean(devOptions.extensions),
1385
+ packageManager: projectProfile?.package_manager,
1386
+ frameworkPrimary: projectProfile?.framework_primary,
1387
+ hasNextDependency: projectProfile?.has_next_dependency,
1388
+ hasTurboDependency: projectProfile?.has_turbo_dependency
1389
+ });
1390
+ telemetry.track('workflow_profile', {
1391
+ command: 'dev',
1392
+ ...workflowProfile
1393
+ });
1394
+ telemetry.track('cli_command_start', {
1395
+ command: 'dev',
1396
+ vendors: list,
1397
+ browser_count: list.length,
1398
+ is_multi_browser: list.length > 1,
1399
+ is_remote_input: isRemoteInput,
1400
+ is_wait_mode: Boolean(devOptions.wait),
1401
+ is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1402
+ polyfill_used: devOptions.polyfill?.toString() !== 'false',
1403
+ source_inspection_requested: Boolean(devOptions.source || devOptions.watchSource),
1404
+ companion_extensions_provided: Boolean(devOptions.extensions),
1405
+ log_level: devOptions.logLevel || 'off',
1406
+ log_format: devOptions.logFormat || 'pretty',
1407
+ custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary),
1408
+ ...workflowProfile
1409
+ });
1410
+ validateVendorsOrExit(list, (invalid, supported)=>{
1411
+ console.error(unsupportedBrowserFlag(invalid, supported));
1412
+ });
1413
+ if (devOptions.wait) {
1414
+ const waitResult = await runWaitMode({
1295
1415
  command: 'dev',
1296
- isMultiBrowser: list.length > 1,
1297
- isRemoteInput: isRemoteInput,
1298
- isWaitMode: Boolean(devOptions.wait),
1299
- isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1300
- usesMachineReadableOutput: 'json' === devOptions.waitFormat || 'json' === devOptions.logFormat || 'ndjson' === devOptions.logFormat || 'json' === devOptions.sourceFormat || 'ndjson' === devOptions.sourceFormat,
1301
- sourceInspectionRequested: Boolean(devOptions.source || devOptions.watchSource),
1302
- companionExtensionsProvided: Boolean(devOptions.extensions),
1303
- packageManager: projectProfile?.package_manager,
1304
- frameworkPrimary: projectProfile?.framework_primary,
1305
- hasNextDependency: projectProfile?.has_next_dependency,
1306
- hasTurboDependency: projectProfile?.has_turbo_dependency
1416
+ pathOrRemoteUrl,
1417
+ browsers: list,
1418
+ waitTimeout: devOptions.waitTimeout,
1419
+ waitFormat: devOptions.waitFormat
1307
1420
  });
1308
- telemetry.track('workflow_profile', {
1421
+ if ('json' === waitResult.format) console.log(JSON.stringify({
1422
+ ok: true,
1423
+ mode: 'wait',
1309
1424
  command: 'dev',
1310
- ...workflowProfile
1311
- });
1312
- telemetry.track('cli_command_start', {
1425
+ browsers: waitResult.browsers,
1426
+ results: waitResult.results
1427
+ }));
1428
+ telemetry.track('cli_command_finish', {
1313
1429
  command: 'dev',
1314
- vendors: list,
1315
- browser_count: list.length,
1316
- is_multi_browser: list.length > 1,
1317
- is_remote_input: isRemoteInput,
1318
- is_wait_mode: Boolean(devOptions.wait),
1319
- is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1320
- polyfill_used: devOptions.polyfill?.toString() !== 'false',
1321
- source_inspection_requested: Boolean(devOptions.source || devOptions.watchSource),
1322
- companion_extensions_provided: Boolean(devOptions.extensions),
1323
- log_level: devOptions.logLevel || 'off',
1324
- log_format: devOptions.logFormat || 'pretty',
1325
- custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary),
1430
+ duration_ms: Date.now() - cmdStart,
1431
+ success: true,
1432
+ exit_code: 0,
1326
1433
  ...workflowProfile
1327
1434
  });
1328
- validateVendorsOrExit(list, (invalid, supported)=>{
1329
- console.error(unsupportedBrowserFlag(invalid, supported));
1435
+ return;
1436
+ }
1437
+ const normalizedSource = normalizeSourceOption(devOptions.source, devOptions.startingUrl);
1438
+ if (normalizedSource) {
1439
+ devOptions.source = normalizedSource;
1440
+ if (void 0 === devOptions.watchSource) devOptions.watchSource = true;
1441
+ }
1442
+ const sourceEnabled = Boolean(devOptions.source || devOptions.watchSource);
1443
+ const normalizedSourceFormat = normalizeSourceFormatOption({
1444
+ sourceFormat: devOptions.sourceFormat,
1445
+ logFormat: devOptions.logFormat,
1446
+ sourceEnabled
1447
+ });
1448
+ devOptions.sourceFormat = normalizedSourceFormat;
1449
+ if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1450
+ devOptions.sourceRedact = normalizeSourceRedactOption(devOptions.sourceRedact, normalizedSourceFormat);
1451
+ devOptions.sourceMeta = normalizeSourceMetaOption(devOptions.sourceMeta, sourceEnabled);
1452
+ devOptions.sourceProbe = normalizeSourceProbeOption(devOptions.sourceProbe);
1453
+ devOptions.sourceTree = normalizeSourceTreeOption(devOptions.sourceTree, sourceEnabled);
1454
+ devOptions.sourceConsole = normalizeSourceConsoleOption(devOptions.sourceConsole, sourceEnabled);
1455
+ devOptions.sourceDom = normalizeSourceDomOption(devOptions.sourceDom, devOptions.watchSource);
1456
+ devOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(devOptions.sourceMaxBytes);
1457
+ devOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(devOptions.sourceIncludeShadow, sourceEnabled);
1458
+ devOptions.sourceDiff = normalizeSourceDiffOption(devOptions.sourceDiff, devOptions.watchSource);
1459
+ const { extensionDev } = loadExtensionDevelopModule();
1460
+ for (const vendor of list){
1461
+ const vendorStart = Date.now();
1462
+ telemetry.track('cli_vendor_start', {
1463
+ command: 'dev',
1464
+ vendor
1330
1465
  });
1331
- if (devOptions.wait) {
1332
- const waitResult = await runWaitMode({
1333
- command: 'dev',
1334
- pathOrRemoteUrl,
1335
- browsers: list,
1336
- waitTimeout: devOptions.waitTimeout,
1337
- waitFormat: devOptions.waitFormat
1338
- });
1339
- if ('json' === waitResult.format) console.log(JSON.stringify({
1340
- ok: true,
1341
- mode: 'wait',
1342
- command: 'dev',
1343
- browsers: waitResult.browsers,
1344
- results: waitResult.results
1345
- }));
1346
- telemetry.track('cli_command_finish', {
1347
- command: 'dev',
1348
- duration_ms: Date.now() - cmdStart,
1349
- success: true,
1350
- exit_code: 0,
1351
- ...workflowProfile
1352
- });
1353
- return;
1354
- }
1355
- const normalizedSource = normalizeSourceOption(devOptions.source, devOptions.startingUrl);
1356
- if (normalizedSource) {
1357
- devOptions.source = normalizedSource;
1358
- if (void 0 === devOptions.watchSource) devOptions.watchSource = true;
1359
- }
1360
- const sourceEnabled = Boolean(devOptions.source || devOptions.watchSource);
1361
- const normalizedSourceFormat = normalizeSourceFormatOption({
1466
+ const logsOption = devOptions.logs;
1467
+ const logContextOption = devOptions.logContext;
1468
+ const devArgs = {
1469
+ ...devOptions,
1470
+ profile: devOptions.profile,
1471
+ browser: vendor,
1472
+ chromiumBinary: devOptions.chromiumBinary,
1473
+ geckoBinary: devOptions.geckoBinary,
1474
+ polyfill: devOptions.polyfill?.toString() !== 'false',
1475
+ open: devOptions.open,
1476
+ startingUrl: devOptions.startingUrl,
1477
+ source: devOptions.source,
1478
+ watchSource: devOptions.watchSource,
1362
1479
  sourceFormat: devOptions.sourceFormat,
1363
- logFormat: devOptions.logFormat,
1364
- sourceEnabled
1365
- });
1366
- devOptions.sourceFormat = normalizedSourceFormat;
1367
- if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1368
- devOptions.sourceRedact = normalizeSourceRedactOption(devOptions.sourceRedact, normalizedSourceFormat);
1369
- devOptions.sourceMeta = normalizeSourceMetaOption(devOptions.sourceMeta, sourceEnabled);
1370
- devOptions.sourceProbe = normalizeSourceProbeOption(devOptions.sourceProbe);
1371
- devOptions.sourceTree = normalizeSourceTreeOption(devOptions.sourceTree, sourceEnabled);
1372
- devOptions.sourceConsole = normalizeSourceConsoleOption(devOptions.sourceConsole, sourceEnabled);
1373
- devOptions.sourceDom = normalizeSourceDomOption(devOptions.sourceDom, devOptions.watchSource);
1374
- devOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(devOptions.sourceMaxBytes);
1375
- devOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(devOptions.sourceIncludeShadow, sourceEnabled);
1376
- devOptions.sourceDiff = normalizeSourceDiffOption(devOptions.sourceDiff, devOptions.watchSource);
1377
- const { extensionDev } = dev_require('extension-develop');
1378
- for (const vendor of list){
1379
- const vendorStart = Date.now();
1380
- telemetry.track('cli_vendor_start', {
1381
- command: 'dev',
1382
- vendor
1383
- });
1384
- const logsOption = devOptions.logs;
1385
- const logContextOption = devOptions.logContext;
1386
- const devArgs = {
1387
- ...devOptions,
1388
- profile: devOptions.profile,
1389
- browser: vendor,
1390
- chromiumBinary: devOptions.chromiumBinary,
1391
- geckoBinary: devOptions.geckoBinary,
1392
- polyfill: devOptions.polyfill?.toString() !== 'false',
1393
- open: devOptions.open,
1394
- startingUrl: devOptions.startingUrl,
1395
- source: devOptions.source,
1396
- watchSource: devOptions.watchSource,
1397
- sourceFormat: devOptions.sourceFormat,
1398
- sourceSummary: devOptions.sourceSummary,
1399
- sourceMeta: devOptions.sourceMeta,
1400
- sourceProbe: devOptions.sourceProbe,
1401
- sourceTree: devOptions.sourceTree,
1402
- sourceConsole: devOptions.sourceConsole,
1403
- sourceDom: devOptions.sourceDom,
1404
- sourceMaxBytes: devOptions.sourceMaxBytes,
1405
- sourceRedact: devOptions.sourceRedact,
1406
- sourceIncludeShadow: devOptions.sourceIncludeShadow,
1407
- sourceDiff: devOptions.sourceDiff,
1408
- install: devOptions.install,
1409
- noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1410
- extensions: parseExtensionsList(devOptions.extensions),
1411
- logLevel: logsOption || devOptions.logLevel || 'off',
1412
- logContexts: parseLogContexts(logContextOption),
1413
- logFormat: devOptions.logFormat || 'pretty',
1414
- logTimestamps: false !== devOptions.logTimestamps,
1415
- logColor: false !== devOptions.logColor,
1416
- logUrl: devOptions.logUrl,
1417
- logTab: devOptions.logTab
1418
- };
1419
- await extensionDev(pathOrRemoteUrl, devArgs);
1420
- telemetry.track('cli_vendor_finish', {
1421
- command: 'dev',
1422
- vendor,
1423
- duration_ms: Date.now() - vendorStart
1424
- });
1425
- }
1426
- telemetry.track('cli_command_finish', {
1480
+ sourceSummary: devOptions.sourceSummary,
1481
+ sourceMeta: devOptions.sourceMeta,
1482
+ sourceProbe: devOptions.sourceProbe,
1483
+ sourceTree: devOptions.sourceTree,
1484
+ sourceConsole: devOptions.sourceConsole,
1485
+ sourceDom: devOptions.sourceDom,
1486
+ sourceMaxBytes: devOptions.sourceMaxBytes,
1487
+ sourceRedact: devOptions.sourceRedact,
1488
+ sourceIncludeShadow: devOptions.sourceIncludeShadow,
1489
+ sourceDiff: devOptions.sourceDiff,
1490
+ install: devOptions.install,
1491
+ noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1492
+ extensions: parseExtensionsList(devOptions.extensions),
1493
+ logLevel: logsOption || devOptions.logLevel || 'off',
1494
+ logContexts: parseLogContexts(logContextOption),
1495
+ logFormat: devOptions.logFormat || 'pretty',
1496
+ logTimestamps: false !== devOptions.logTimestamps,
1497
+ logColor: false !== devOptions.logColor,
1498
+ logUrl: devOptions.logUrl,
1499
+ logTab: devOptions.logTab
1500
+ };
1501
+ await extensionDev(pathOrRemoteUrl, devArgs);
1502
+ telemetry.track('cli_vendor_finish', {
1427
1503
  command: 'dev',
1428
- duration_ms: Date.now() - cmdStart,
1429
- success: 0 === process.exitCode || null == process.exitCode,
1430
- exit_code: process.exitCode ?? 0,
1431
- ...workflowProfile
1504
+ vendor,
1505
+ duration_ms: Date.now() - vendorStart
1432
1506
  });
1507
+ }
1508
+ telemetry.track('cli_command_finish', {
1509
+ command: 'dev',
1510
+ duration_ms: Date.now() - cmdStart,
1511
+ success: 0 === process.exitCode || null == process.exitCode,
1512
+ exit_code: process.exitCode ?? 0,
1513
+ ...workflowProfile
1433
1514
  });
1434
- }
1435
- const start_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
1436
- function registerStartCommand(program, telemetry) {
1437
- program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after', '\nAdditional options:\n --no-browser do not launch the browser (build still runs)\n --wait wait for ready contract and exit\n --wait-format pretty|json output for wait mode\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[experimental] 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('--wait-format <pretty|json>', 'output format for --wait results (default: pretty)').option('--author, --author-mode', '[experimental] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
1438
- const hasSourceInspectionFlags = void 0 !== startOptions.source || void 0 !== startOptions.watchSource || void 0 !== startOptions.sourceFormat || void 0 !== startOptions.sourceSummary || void 0 !== startOptions.sourceMeta || void 0 !== startOptions.sourceProbe || void 0 !== startOptions.sourceTree || void 0 !== startOptions.sourceConsole || void 0 !== startOptions.sourceDom || void 0 !== startOptions.sourceMaxBytes || void 0 !== startOptions.sourceRedact || void 0 !== startOptions.sourceIncludeShadow || void 0 !== startOptions.sourceDiff;
1439
- if (hasSourceInspectionFlags) {
1440
- console.error(sourceInspectionNotSupported('start'));
1441
- process.exit(1);
1442
- }
1443
- if (startOptions.author || startOptions.authorMode) {
1444
- process.env.EXTENSION_AUTHOR_MODE = 'true';
1445
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1446
- }
1447
- const cmdStart = Date.now();
1448
- const list = vendors(browser);
1449
- const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1450
- const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1451
- const workflowProfile = collectWorkflowProfile({
1515
+ });
1516
+ }
1517
+ function registerStartCommand(program, telemetry) {
1518
+ program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after', '\nAdditional options:\n --no-browser do not launch the browser (build still runs)\n --wait wait for ready contract and exit\n --wait-format pretty|json output for wait mode\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[experimental] 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('--wait-format <pretty|json>', 'output format for --wait results (default: pretty)').option('--author, --author-mode', '[experimental] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
1519
+ const hasSourceInspectionFlags = void 0 !== startOptions.source || void 0 !== startOptions.watchSource || void 0 !== startOptions.sourceFormat || void 0 !== startOptions.sourceSummary || void 0 !== startOptions.sourceMeta || void 0 !== startOptions.sourceProbe || void 0 !== startOptions.sourceTree || void 0 !== startOptions.sourceConsole || void 0 !== startOptions.sourceDom || void 0 !== startOptions.sourceMaxBytes || void 0 !== startOptions.sourceRedact || void 0 !== startOptions.sourceIncludeShadow || void 0 !== startOptions.sourceDiff;
1520
+ if (hasSourceInspectionFlags) {
1521
+ console.error(sourceInspectionNotSupported('start'));
1522
+ process.exit(1);
1523
+ }
1524
+ if (startOptions.author || startOptions.authorMode) {
1525
+ process.env.EXTENSION_AUTHOR_MODE = 'true';
1526
+ if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1527
+ }
1528
+ const cmdStart = Date.now();
1529
+ const list = vendors(browser);
1530
+ const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1531
+ const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1532
+ const workflowProfile = collectWorkflowProfile({
1533
+ command: 'start',
1534
+ isMultiBrowser: list.length > 1,
1535
+ isRemoteInput: isRemoteInput,
1536
+ isWaitMode: Boolean(startOptions.wait),
1537
+ isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1538
+ usesMachineReadableOutput: 'json' === startOptions.waitFormat || 'json' === startOptions.logFormat || 'ndjson' === startOptions.logFormat,
1539
+ companionExtensionsProvided: Boolean(startOptions.extensions),
1540
+ packageManager: projectProfile?.package_manager,
1541
+ frameworkPrimary: projectProfile?.framework_primary,
1542
+ hasNextDependency: projectProfile?.has_next_dependency,
1543
+ hasTurboDependency: projectProfile?.has_turbo_dependency
1544
+ });
1545
+ telemetry.track('workflow_profile', {
1546
+ command: 'start',
1547
+ ...workflowProfile
1548
+ });
1549
+ telemetry.track('cli_command_start', {
1550
+ command: 'start',
1551
+ vendors: list,
1552
+ browser_count: list.length,
1553
+ is_multi_browser: list.length > 1,
1554
+ is_remote_input: isRemoteInput,
1555
+ is_wait_mode: Boolean(startOptions.wait),
1556
+ is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1557
+ companion_extensions_provided: Boolean(startOptions.extensions),
1558
+ polyfill_used: startOptions.polyfill?.toString() !== 'false',
1559
+ ...workflowProfile
1560
+ });
1561
+ validateVendorsOrExit(list, (invalid, supported)=>{
1562
+ console.error(unsupportedBrowserFlag(invalid, supported));
1563
+ });
1564
+ if (startOptions.wait) {
1565
+ const waitResult = await runWaitMode({
1452
1566
  command: 'start',
1453
- isMultiBrowser: list.length > 1,
1454
- isRemoteInput: isRemoteInput,
1455
- isWaitMode: Boolean(startOptions.wait),
1456
- isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1457
- usesMachineReadableOutput: 'json' === startOptions.waitFormat || 'json' === startOptions.logFormat || 'ndjson' === startOptions.logFormat,
1458
- companionExtensionsProvided: Boolean(startOptions.extensions),
1459
- packageManager: projectProfile?.package_manager,
1460
- frameworkPrimary: projectProfile?.framework_primary,
1461
- hasNextDependency: projectProfile?.has_next_dependency,
1462
- hasTurboDependency: projectProfile?.has_turbo_dependency
1567
+ pathOrRemoteUrl,
1568
+ browsers: list,
1569
+ waitTimeout: startOptions.waitTimeout,
1570
+ waitFormat: startOptions.waitFormat
1463
1571
  });
1464
- telemetry.track('workflow_profile', {
1572
+ if ('json' === waitResult.format) console.log(JSON.stringify({
1573
+ ok: true,
1574
+ mode: 'wait',
1465
1575
  command: 'start',
1466
- ...workflowProfile
1467
- });
1468
- telemetry.track('cli_command_start', {
1576
+ browsers: waitResult.browsers,
1577
+ results: waitResult.results
1578
+ }));
1579
+ telemetry.track('cli_command_finish', {
1469
1580
  command: 'start',
1470
- vendors: list,
1471
- browser_count: list.length,
1472
- is_multi_browser: list.length > 1,
1473
- is_remote_input: isRemoteInput,
1474
- is_wait_mode: Boolean(startOptions.wait),
1475
- is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1476
- companion_extensions_provided: Boolean(startOptions.extensions),
1477
- polyfill_used: startOptions.polyfill?.toString() !== 'false',
1581
+ duration_ms: Date.now() - cmdStart,
1582
+ success: true,
1583
+ exit_code: 0,
1478
1584
  ...workflowProfile
1479
1585
  });
1480
- validateVendorsOrExit(list, (invalid, supported)=>{
1481
- console.error(unsupportedBrowserFlag(invalid, supported));
1586
+ return;
1587
+ }
1588
+ const normalizedSource = normalizeSourceOption(startOptions.source, startOptions.startingUrl);
1589
+ if (normalizedSource) startOptions.source = normalizedSource;
1590
+ const sourceEnabled = Boolean(startOptions.source || startOptions.watchSource);
1591
+ const normalizedSourceFormat = normalizeSourceFormatOption({
1592
+ sourceFormat: startOptions.sourceFormat,
1593
+ logFormat: startOptions.logFormat,
1594
+ sourceEnabled
1595
+ });
1596
+ startOptions.sourceFormat = normalizedSourceFormat;
1597
+ if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1598
+ startOptions.sourceRedact = normalizeSourceRedactOption(startOptions.sourceRedact, normalizedSourceFormat);
1599
+ startOptions.sourceMeta = normalizeSourceMetaOption(startOptions.sourceMeta, sourceEnabled);
1600
+ startOptions.sourceProbe = normalizeSourceProbeOption(startOptions.sourceProbe);
1601
+ startOptions.sourceTree = normalizeSourceTreeOption(startOptions.sourceTree, sourceEnabled);
1602
+ startOptions.sourceConsole = normalizeSourceConsoleOption(startOptions.sourceConsole, sourceEnabled);
1603
+ startOptions.sourceDom = normalizeSourceDomOption(startOptions.sourceDom, startOptions.watchSource);
1604
+ startOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(startOptions.sourceMaxBytes);
1605
+ startOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(startOptions.sourceIncludeShadow, sourceEnabled);
1606
+ startOptions.sourceDiff = normalizeSourceDiffOption(startOptions.sourceDiff, startOptions.watchSource);
1607
+ const { extensionStart } = loadExtensionDevelopModule();
1608
+ for (const vendor of list){
1609
+ const vendorStart = Date.now();
1610
+ telemetry.track('cli_vendor_start', {
1611
+ command: 'start',
1612
+ vendor
1482
1613
  });
1483
- if (startOptions.wait) {
1484
- const waitResult = await runWaitMode({
1485
- command: 'start',
1486
- pathOrRemoteUrl,
1487
- browsers: list,
1488
- waitTimeout: startOptions.waitTimeout,
1489
- waitFormat: startOptions.waitFormat
1490
- });
1491
- if ('json' === waitResult.format) console.log(JSON.stringify({
1492
- ok: true,
1493
- mode: 'wait',
1494
- command: 'start',
1495
- browsers: waitResult.browsers,
1496
- results: waitResult.results
1497
- }));
1498
- telemetry.track('cli_command_finish', {
1499
- command: 'start',
1500
- duration_ms: Date.now() - cmdStart,
1501
- success: true,
1502
- exit_code: 0,
1503
- ...workflowProfile
1504
- });
1505
- return;
1506
- }
1507
- const normalizedSource = normalizeSourceOption(startOptions.source, startOptions.startingUrl);
1508
- if (normalizedSource) startOptions.source = normalizedSource;
1509
- const sourceEnabled = Boolean(startOptions.source || startOptions.watchSource);
1510
- const normalizedSourceFormat = normalizeSourceFormatOption({
1614
+ const logsOption = startOptions.logs;
1615
+ const logContextOption = startOptions.logContext;
1616
+ const logContexts = parseLogContexts(logContextOption);
1617
+ await extensionStart(pathOrRemoteUrl, {
1618
+ mode: 'production',
1619
+ profile: startOptions.profile,
1620
+ browser: vendor,
1621
+ chromiumBinary: startOptions.chromiumBinary,
1622
+ geckoBinary: startOptions.geckoBinary,
1623
+ startingUrl: startOptions.startingUrl,
1624
+ port: startOptions.port,
1625
+ install: startOptions.install,
1626
+ noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1627
+ extensions: parseExtensionsList(startOptions.extensions),
1628
+ source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
1629
+ watchSource: startOptions.watchSource,
1511
1630
  sourceFormat: startOptions.sourceFormat,
1512
- logFormat: startOptions.logFormat,
1513
- sourceEnabled
1631
+ sourceSummary: startOptions.sourceSummary,
1632
+ sourceMeta: startOptions.sourceMeta,
1633
+ sourceProbe: startOptions.sourceProbe,
1634
+ sourceTree: startOptions.sourceTree,
1635
+ sourceConsole: startOptions.sourceConsole,
1636
+ sourceDom: startOptions.sourceDom,
1637
+ sourceMaxBytes: startOptions.sourceMaxBytes,
1638
+ sourceRedact: startOptions.sourceRedact,
1639
+ sourceIncludeShadow: startOptions.sourceIncludeShadow,
1640
+ sourceDiff: startOptions.sourceDiff,
1641
+ logLevel: logsOption || startOptions.logLevel || 'off',
1642
+ logContexts,
1643
+ logFormat: startOptions.logFormat || 'pretty',
1644
+ logTimestamps: false !== startOptions.logTimestamps,
1645
+ logColor: false !== startOptions.logColor,
1646
+ logUrl: startOptions.logUrl,
1647
+ logTab: startOptions.logTab
1514
1648
  });
1515
- startOptions.sourceFormat = normalizedSourceFormat;
1516
- if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1517
- startOptions.sourceRedact = normalizeSourceRedactOption(startOptions.sourceRedact, normalizedSourceFormat);
1518
- startOptions.sourceMeta = normalizeSourceMetaOption(startOptions.sourceMeta, sourceEnabled);
1519
- startOptions.sourceProbe = normalizeSourceProbeOption(startOptions.sourceProbe);
1520
- startOptions.sourceTree = normalizeSourceTreeOption(startOptions.sourceTree, sourceEnabled);
1521
- startOptions.sourceConsole = normalizeSourceConsoleOption(startOptions.sourceConsole, sourceEnabled);
1522
- startOptions.sourceDom = normalizeSourceDomOption(startOptions.sourceDom, startOptions.watchSource);
1523
- startOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(startOptions.sourceMaxBytes);
1524
- startOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(startOptions.sourceIncludeShadow, sourceEnabled);
1525
- startOptions.sourceDiff = normalizeSourceDiffOption(startOptions.sourceDiff, startOptions.watchSource);
1526
- const { extensionStart } = start_require('extension-develop');
1527
- for (const vendor of list){
1528
- const vendorStart = Date.now();
1529
- telemetry.track('cli_vendor_start', {
1530
- command: 'start',
1531
- vendor
1532
- });
1533
- const logsOption = startOptions.logs;
1534
- const logContextOption = startOptions.logContext;
1535
- const logContexts = parseLogContexts(logContextOption);
1536
- await extensionStart(pathOrRemoteUrl, {
1537
- mode: 'production',
1538
- profile: startOptions.profile,
1539
- browser: vendor,
1540
- chromiumBinary: startOptions.chromiumBinary,
1541
- geckoBinary: startOptions.geckoBinary,
1542
- startingUrl: startOptions.startingUrl,
1543
- port: startOptions.port,
1544
- install: startOptions.install,
1545
- noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1546
- extensions: parseExtensionsList(startOptions.extensions),
1547
- source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
1548
- watchSource: startOptions.watchSource,
1549
- sourceFormat: startOptions.sourceFormat,
1550
- sourceSummary: startOptions.sourceSummary,
1551
- sourceMeta: startOptions.sourceMeta,
1552
- sourceProbe: startOptions.sourceProbe,
1553
- sourceTree: startOptions.sourceTree,
1554
- sourceConsole: startOptions.sourceConsole,
1555
- sourceDom: startOptions.sourceDom,
1556
- sourceMaxBytes: startOptions.sourceMaxBytes,
1557
- sourceRedact: startOptions.sourceRedact,
1558
- sourceIncludeShadow: startOptions.sourceIncludeShadow,
1559
- sourceDiff: startOptions.sourceDiff,
1560
- logLevel: logsOption || startOptions.logLevel || 'off',
1561
- logContexts,
1562
- logFormat: startOptions.logFormat || 'pretty',
1563
- logTimestamps: false !== startOptions.logTimestamps,
1564
- logColor: false !== startOptions.logColor,
1565
- logUrl: startOptions.logUrl,
1566
- logTab: startOptions.logTab
1567
- });
1568
- telemetry.track('cli_vendor_finish', {
1569
- command: 'start',
1570
- vendor,
1571
- duration_ms: Date.now() - vendorStart
1572
- });
1573
- }
1574
- telemetry.track('cli_command_finish', {
1649
+ telemetry.track('cli_vendor_finish', {
1575
1650
  command: 'start',
1576
- duration_ms: Date.now() - cmdStart,
1577
- success: 0 === process.exitCode || null == process.exitCode,
1578
- exit_code: process.exitCode ?? 0,
1579
- ...workflowProfile
1651
+ vendor,
1652
+ duration_ms: Date.now() - vendorStart
1580
1653
  });
1654
+ }
1655
+ telemetry.track('cli_command_finish', {
1656
+ command: 'start',
1657
+ duration_ms: Date.now() - cmdStart,
1658
+ success: 0 === process.exitCode || null == process.exitCode,
1659
+ exit_code: process.exitCode ?? 0,
1660
+ ...workflowProfile
1581
1661
  });
1582
- }
1583
- const preview_require = (0, external_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
1584
- function registerPreviewCommand(program, telemetry) {
1585
- program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', '\nAdditional option:\n --no-browser do not launch the browser\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
1586
- const hasSourceInspectionFlags = void 0 !== previewOptions.source || void 0 !== previewOptions.watchSource || void 0 !== previewOptions.sourceFormat || void 0 !== previewOptions.sourceSummary || void 0 !== previewOptions.sourceMeta || void 0 !== previewOptions.sourceProbe || void 0 !== previewOptions.sourceTree || void 0 !== previewOptions.sourceConsole || void 0 !== previewOptions.sourceDom || void 0 !== previewOptions.sourceMaxBytes || void 0 !== previewOptions.sourceRedact || void 0 !== previewOptions.sourceIncludeShadow || void 0 !== previewOptions.sourceDiff;
1587
- if (hasSourceInspectionFlags) {
1588
- console.error(sourceInspectionNotSupported('preview'));
1589
- process.exit(1);
1590
- }
1591
- if (previewOptions.author || previewOptions['authorMode']) {
1592
- process.env.EXTENSION_AUTHOR_MODE = 'true';
1593
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1594
- }
1595
- const cmdStart = Date.now();
1596
- const list = vendors(browser);
1597
- const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1598
- const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1599
- const workflowProfile = collectWorkflowProfile({
1600
- command: 'preview',
1601
- isMultiBrowser: list.length > 1,
1602
- isRemoteInput: isRemoteInput,
1603
- isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1604
- usesMachineReadableOutput: 'json' === previewOptions.logFormat || 'ndjson' === previewOptions.logFormat,
1605
- companionExtensionsProvided: Boolean(previewOptions.extensions),
1606
- packageManager: projectProfile?.package_manager,
1607
- frameworkPrimary: projectProfile?.framework_primary,
1608
- hasNextDependency: projectProfile?.has_next_dependency,
1609
- hasTurboDependency: projectProfile?.has_turbo_dependency
1610
- });
1611
- telemetry.track('workflow_profile', {
1612
- command: 'preview',
1613
- ...workflowProfile
1614
- });
1615
- telemetry.track('cli_command_start', {
1662
+ });
1663
+ }
1664
+ function registerPreviewCommand(program, telemetry) {
1665
+ program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', '\nAdditional option:\n --no-browser do not launch the browser\n').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--watch-source [boolean]', '[experimental] re-print HTML on rebuilds or file changes', parseOptionalBoolean).option('--source-format <pretty|json|ndjson>', '[experimental] output format for source HTML (defaults to --log-format when present, otherwise JSON when --source is used)').option('--source-summary [boolean]', '[experimental] output a compact summary instead of full HTML', parseOptionalBoolean).option('--source-meta [boolean]', '[experimental] output page metadata (readyState, viewport, frames)', parseOptionalBoolean).option('--source-probe <selectors>', '[experimental] comma-separated CSS selectors to probe').option('--source-tree <off|root-only>', '[experimental] output a compact extension root tree').option('--source-console [boolean]', '[experimental] output console summary (best-effort)', parseOptionalBoolean).option('--source-dom [boolean]', '[experimental] output DOM snapshots and diffs (default: true when watch is enabled)', parseOptionalBoolean).option('--source-max-bytes <bytes>', '[experimental] limit HTML output size in bytes (0 disables truncation)').option('--source-redact <off|safe|strict>', '[experimental] redact sensitive content in HTML output (default: safe for JSON/NDJSON)').option('--source-include-shadow <off|open-only|all>', '[experimental] control Shadow DOM inclusion in HTML output (default: open-only)').option('--source-diff [boolean]', '[experimental] include diff metadata on watch updates (default: true when watch is enabled)', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
1666
+ const hasSourceInspectionFlags = void 0 !== previewOptions.source || void 0 !== previewOptions.watchSource || void 0 !== previewOptions.sourceFormat || void 0 !== previewOptions.sourceSummary || void 0 !== previewOptions.sourceMeta || void 0 !== previewOptions.sourceProbe || void 0 !== previewOptions.sourceTree || void 0 !== previewOptions.sourceConsole || void 0 !== previewOptions.sourceDom || void 0 !== previewOptions.sourceMaxBytes || void 0 !== previewOptions.sourceRedact || void 0 !== previewOptions.sourceIncludeShadow || void 0 !== previewOptions.sourceDiff;
1667
+ if (hasSourceInspectionFlags) {
1668
+ console.error(sourceInspectionNotSupported('preview'));
1669
+ process.exit(1);
1670
+ }
1671
+ if (previewOptions.author || previewOptions['authorMode']) {
1672
+ process.env.EXTENSION_AUTHOR_MODE = 'true';
1673
+ if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1674
+ }
1675
+ const cmdStart = Date.now();
1676
+ const list = vendors(browser);
1677
+ const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1678
+ const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1679
+ const workflowProfile = collectWorkflowProfile({
1680
+ command: 'preview',
1681
+ isMultiBrowser: list.length > 1,
1682
+ isRemoteInput: isRemoteInput,
1683
+ isNoBrowserMode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1684
+ usesMachineReadableOutput: 'json' === previewOptions.logFormat || 'ndjson' === previewOptions.logFormat,
1685
+ companionExtensionsProvided: Boolean(previewOptions.extensions),
1686
+ packageManager: projectProfile?.package_manager,
1687
+ frameworkPrimary: projectProfile?.framework_primary,
1688
+ hasNextDependency: projectProfile?.has_next_dependency,
1689
+ hasTurboDependency: projectProfile?.has_turbo_dependency
1690
+ });
1691
+ telemetry.track('workflow_profile', {
1692
+ command: 'preview',
1693
+ ...workflowProfile
1694
+ });
1695
+ telemetry.track('cli_command_start', {
1696
+ command: 'preview',
1697
+ vendors: list,
1698
+ browser_count: list.length,
1699
+ is_multi_browser: list.length > 1,
1700
+ is_remote_input: isRemoteInput,
1701
+ is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1702
+ companion_extensions_provided: Boolean(previewOptions.extensions),
1703
+ ...workflowProfile
1704
+ });
1705
+ validateVendorsOrExit(list, (invalid, supported)=>{
1706
+ console.error(unsupportedBrowserFlag(invalid, supported));
1707
+ });
1708
+ if (!process.env.EXTJS_LIGHT) {
1709
+ const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1710
+ if (isRemote) process.env.EXTJS_LIGHT = '1';
1711
+ }
1712
+ const normalizedSource = normalizeSourceOption(previewOptions.source, previewOptions.startingUrl);
1713
+ if (normalizedSource) previewOptions.source = normalizedSource;
1714
+ const sourceEnabled = Boolean(previewOptions.source || previewOptions.watchSource);
1715
+ const normalizedSourceFormat = normalizeSourceFormatOption({
1716
+ sourceFormat: previewOptions.sourceFormat,
1717
+ logFormat: previewOptions.logFormat,
1718
+ sourceEnabled
1719
+ });
1720
+ previewOptions.sourceFormat = normalizedSourceFormat;
1721
+ if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1722
+ previewOptions.sourceRedact = normalizeSourceRedactOption(previewOptions.sourceRedact, normalizedSourceFormat);
1723
+ previewOptions.sourceMeta = normalizeSourceMetaOption(previewOptions.sourceMeta, sourceEnabled);
1724
+ previewOptions.sourceProbe = normalizeSourceProbeOption(previewOptions.sourceProbe);
1725
+ previewOptions.sourceTree = normalizeSourceTreeOption(previewOptions.sourceTree, sourceEnabled);
1726
+ previewOptions.sourceConsole = normalizeSourceConsoleOption(previewOptions.sourceConsole, sourceEnabled);
1727
+ previewOptions.sourceDom = normalizeSourceDomOption(previewOptions.sourceDom, previewOptions.watchSource);
1728
+ previewOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(previewOptions.sourceMaxBytes);
1729
+ previewOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(previewOptions.sourceIncludeShadow, sourceEnabled);
1730
+ previewOptions.sourceDiff = normalizeSourceDiffOption(previewOptions.sourceDiff, previewOptions.watchSource);
1731
+ const { extensionPreview } = loadExtensionDevelopModule();
1732
+ for (const vendor of list){
1733
+ const vendorStart = Date.now();
1734
+ telemetry.track('cli_vendor_start', {
1616
1735
  command: 'preview',
1617
- vendors: list,
1618
- browser_count: list.length,
1619
- is_multi_browser: list.length > 1,
1620
- is_remote_input: isRemoteInput,
1621
- is_no_browser_mode: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1622
- companion_extensions_provided: Boolean(previewOptions.extensions),
1623
- ...workflowProfile
1736
+ vendor
1624
1737
  });
1625
- validateVendorsOrExit(list, (invalid, supported)=>{
1626
- console.error(unsupportedBrowserFlag(invalid, supported));
1627
- });
1628
- if (!process.env.EXTJS_LIGHT) {
1629
- const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1630
- if (isRemote) process.env.EXTJS_LIGHT = '1';
1631
- }
1632
- const normalizedSource = normalizeSourceOption(previewOptions.source, previewOptions.startingUrl);
1633
- if (normalizedSource) previewOptions.source = normalizedSource;
1634
- const sourceEnabled = Boolean(previewOptions.source || previewOptions.watchSource);
1635
- const normalizedSourceFormat = normalizeSourceFormatOption({
1738
+ const logsOption = previewOptions.logs;
1739
+ const logContextOption = previewOptions.logContext;
1740
+ const logContexts = parseLogContexts(logContextOption);
1741
+ await extensionPreview(pathOrRemoteUrl, {
1742
+ mode: 'production',
1743
+ profile: previewOptions.profile,
1744
+ browser: vendor,
1745
+ chromiumBinary: previewOptions.chromiumBinary,
1746
+ geckoBinary: previewOptions.geckoBinary,
1747
+ startingUrl: previewOptions.startingUrl,
1748
+ port: previewOptions.port,
1749
+ noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1750
+ extensions: parseExtensionsList(previewOptions.extensions),
1751
+ source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
1752
+ watchSource: previewOptions.watchSource,
1636
1753
  sourceFormat: previewOptions.sourceFormat,
1637
- logFormat: previewOptions.logFormat,
1638
- sourceEnabled
1754
+ sourceSummary: previewOptions.sourceSummary,
1755
+ sourceMeta: previewOptions.sourceMeta,
1756
+ sourceProbe: previewOptions.sourceProbe,
1757
+ sourceTree: previewOptions.sourceTree,
1758
+ sourceConsole: previewOptions.sourceConsole,
1759
+ sourceDom: previewOptions.sourceDom,
1760
+ sourceMaxBytes: previewOptions.sourceMaxBytes,
1761
+ sourceRedact: previewOptions.sourceRedact,
1762
+ sourceIncludeShadow: previewOptions.sourceIncludeShadow,
1763
+ sourceDiff: previewOptions.sourceDiff,
1764
+ logLevel: logsOption || previewOptions.logLevel || 'off',
1765
+ logContexts,
1766
+ logFormat: previewOptions.logFormat || 'pretty',
1767
+ logTimestamps: false !== previewOptions.logTimestamps,
1768
+ logColor: false !== previewOptions.logColor,
1769
+ logUrl: previewOptions.logUrl,
1770
+ logTab: previewOptions.logTab
1639
1771
  });
1640
- previewOptions.sourceFormat = normalizedSourceFormat;
1641
- if (sourceEnabled && normalizedSourceFormat) process.env.EXTENSION_SOURCE_FORMAT = normalizedSourceFormat;
1642
- previewOptions.sourceRedact = normalizeSourceRedactOption(previewOptions.sourceRedact, normalizedSourceFormat);
1643
- previewOptions.sourceMeta = normalizeSourceMetaOption(previewOptions.sourceMeta, sourceEnabled);
1644
- previewOptions.sourceProbe = normalizeSourceProbeOption(previewOptions.sourceProbe);
1645
- previewOptions.sourceTree = normalizeSourceTreeOption(previewOptions.sourceTree, sourceEnabled);
1646
- previewOptions.sourceConsole = normalizeSourceConsoleOption(previewOptions.sourceConsole, sourceEnabled);
1647
- previewOptions.sourceDom = normalizeSourceDomOption(previewOptions.sourceDom, previewOptions.watchSource);
1648
- previewOptions.sourceMaxBytes = normalizeSourceMaxBytesOption(previewOptions.sourceMaxBytes);
1649
- previewOptions.sourceIncludeShadow = normalizeSourceIncludeShadowOption(previewOptions.sourceIncludeShadow, sourceEnabled);
1650
- previewOptions.sourceDiff = normalizeSourceDiffOption(previewOptions.sourceDiff, previewOptions.watchSource);
1651
- const { extensionPreview } = preview_require('extension-develop');
1652
- for (const vendor of list){
1653
- const vendorStart = Date.now();
1654
- telemetry.track('cli_vendor_start', {
1655
- command: 'preview',
1656
- vendor
1657
- });
1658
- const logsOption = previewOptions.logs;
1659
- const logContextOption = previewOptions.logContext;
1660
- const logContexts = parseLogContexts(logContextOption);
1661
- await extensionPreview(pathOrRemoteUrl, {
1662
- mode: 'production',
1663
- profile: previewOptions.profile,
1664
- browser: vendor,
1665
- chromiumBinary: previewOptions.chromiumBinary,
1666
- geckoBinary: previewOptions.geckoBinary,
1667
- startingUrl: previewOptions.startingUrl,
1668
- port: previewOptions.port,
1669
- noBrowser: '1' === process.env.EXTENSION_CLI_NO_BROWSER,
1670
- extensions: parseExtensionsList(previewOptions.extensions),
1671
- source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
1672
- watchSource: previewOptions.watchSource,
1673
- sourceFormat: previewOptions.sourceFormat,
1674
- sourceSummary: previewOptions.sourceSummary,
1675
- sourceMeta: previewOptions.sourceMeta,
1676
- sourceProbe: previewOptions.sourceProbe,
1677
- sourceTree: previewOptions.sourceTree,
1678
- sourceConsole: previewOptions.sourceConsole,
1679
- sourceDom: previewOptions.sourceDom,
1680
- sourceMaxBytes: previewOptions.sourceMaxBytes,
1681
- sourceRedact: previewOptions.sourceRedact,
1682
- sourceIncludeShadow: previewOptions.sourceIncludeShadow,
1683
- sourceDiff: previewOptions.sourceDiff,
1684
- logLevel: logsOption || previewOptions.logLevel || 'off',
1685
- logContexts,
1686
- logFormat: previewOptions.logFormat || 'pretty',
1687
- logTimestamps: false !== previewOptions.logTimestamps,
1688
- logColor: false !== previewOptions.logColor,
1689
- logUrl: previewOptions.logUrl,
1690
- logTab: previewOptions.logTab
1691
- });
1692
- telemetry.track('cli_vendor_finish', {
1693
- command: 'preview',
1694
- vendor,
1695
- duration_ms: Date.now() - vendorStart
1696
- });
1697
- }
1698
- telemetry.track('cli_command_finish', {
1772
+ telemetry.track('cli_vendor_finish', {
1699
1773
  command: 'preview',
1700
- duration_ms: Date.now() - cmdStart,
1701
- success: 0 === process.exitCode || null == process.exitCode,
1702
- exit_code: process.exitCode ?? 0,
1703
- ...workflowProfile
1774
+ vendor,
1775
+ duration_ms: Date.now() - vendorStart
1704
1776
  });
1777
+ }
1778
+ telemetry.track('cli_command_finish', {
1779
+ command: 'preview',
1780
+ duration_ms: Date.now() - cmdStart,
1781
+ success: 0 === process.exitCode || null == process.exitCode,
1782
+ exit_code: process.exitCode ?? 0,
1783
+ ...workflowProfile
1705
1784
  });
1706
- }
1707
- function registerBuildCommand(program, telemetry) {
1708
- program.command('build').arguments('[project-name]').usage('build [path-to-remote-extension] [options]').description(commandDescriptions.build).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`').option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`').option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'whether or not to open the browser automatically. Defaults to `false`').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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
1709
- if (buildOptions.author || buildOptions['authorMode']) {
1710
- process.env.EXTENSION_AUTHOR_MODE = 'true';
1711
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1712
- }
1713
- const cmdStart = Date.now();
1714
- const list = vendors(browser);
1715
- const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1716
- const artifactKind = buildOptions.zipSource ? buildOptions.zip ? 'zip_and_source' : 'source_zip' : buildOptions.zip ? 'zip' : 'directory';
1717
- const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1718
- const workflowProfile = collectWorkflowProfile({
1785
+ });
1786
+ }
1787
+ function registerBuildCommand(program, telemetry) {
1788
+ program.command('build').arguments('[project-name]').usage('build [path-to-remote-extension] [options]').description(commandDescriptions.build).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`').option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`').option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'whether or not to open the browser automatically. Defaults to `false`').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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
1789
+ if (buildOptions.author || buildOptions['authorMode']) {
1790
+ process.env.EXTENSION_AUTHOR_MODE = 'true';
1791
+ if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
1792
+ }
1793
+ const cmdStart = Date.now();
1794
+ const list = vendors(browser);
1795
+ const isRemoteInput = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
1796
+ const artifactKind = buildOptions.zipSource ? buildOptions.zip ? 'zip_and_source' : 'source_zip' : buildOptions.zip ? 'zip' : 'directory';
1797
+ const projectProfile = collectProjectProfile(!isRemoteInput && pathOrRemoteUrl ? pathOrRemoteUrl : process.cwd());
1798
+ const workflowProfile = collectWorkflowProfile({
1799
+ command: 'build',
1800
+ isMultiBrowser: list.length > 1,
1801
+ isRemoteInput: isRemoteInput,
1802
+ companionExtensionsProvided: Boolean(buildOptions.extensions),
1803
+ artifactKind,
1804
+ packageManager: projectProfile?.package_manager,
1805
+ frameworkPrimary: projectProfile?.framework_primary,
1806
+ hasNextDependency: projectProfile?.has_next_dependency,
1807
+ hasTurboDependency: projectProfile?.has_turbo_dependency
1808
+ });
1809
+ telemetry.track('workflow_profile', {
1810
+ command: 'build',
1811
+ ...workflowProfile
1812
+ });
1813
+ telemetry.track('cli_command_start', {
1814
+ command: 'build',
1815
+ vendors: list,
1816
+ browser_count: list.length,
1817
+ is_multi_browser: list.length > 1,
1818
+ is_remote_input: isRemoteInput,
1819
+ polyfill_used: buildOptions.polyfill || false,
1820
+ zip: buildOptions.zip || false,
1821
+ zip_source: buildOptions.zipSource || false,
1822
+ artifact_kind: artifactKind,
1823
+ ...workflowProfile
1824
+ });
1825
+ validateVendorsOrExit(list, (invalid, supported)=>{
1826
+ console.error(unsupportedBrowserFlag(invalid, supported));
1827
+ });
1828
+ const { extensionBuild } = loadExtensionDevelopModule();
1829
+ for (const vendor of list){
1830
+ const vendorStart = Date.now();
1831
+ telemetry.track('cli_vendor_start', {
1719
1832
  command: 'build',
1720
- isMultiBrowser: list.length > 1,
1721
- isRemoteInput: isRemoteInput,
1722
- companionExtensionsProvided: Boolean(buildOptions.extensions),
1723
- artifactKind,
1724
- packageManager: projectProfile?.package_manager,
1725
- frameworkPrimary: projectProfile?.framework_primary,
1726
- hasNextDependency: projectProfile?.has_next_dependency,
1727
- hasTurboDependency: projectProfile?.has_turbo_dependency
1833
+ vendor
1728
1834
  });
1729
- telemetry.track('workflow_profile', {
1730
- command: 'build',
1731
- ...workflowProfile
1835
+ const buildSummary = await extensionBuild(pathOrRemoteUrl, {
1836
+ browser: vendor,
1837
+ polyfill: buildOptions.polyfill,
1838
+ zip: buildOptions.zip,
1839
+ zipSource: buildOptions.zipSource,
1840
+ zipFilename: buildOptions.zipFilename,
1841
+ silent: buildOptions.silent,
1842
+ install: buildOptions.install,
1843
+ extensions: parseExtensionsList(buildOptions.extensions)
1732
1844
  });
1733
- telemetry.track('cli_command_start', {
1734
- command: 'build',
1735
- vendors: list,
1845
+ telemetry.track('cli_build_summary', {
1846
+ ...buildSummary,
1736
1847
  browser_count: list.length,
1737
1848
  is_multi_browser: list.length > 1,
1738
1849
  is_remote_input: isRemoteInput,
1739
- polyfill_used: buildOptions.polyfill || false,
1740
- zip: buildOptions.zip || false,
1741
- zip_source: buildOptions.zipSource || false,
1742
1850
  artifact_kind: artifactKind,
1743
1851
  ...workflowProfile
1744
1852
  });
1745
- validateVendorsOrExit(list, (invalid, supported)=>{
1746
- console.error(unsupportedBrowserFlag(invalid, supported));
1747
- });
1748
- const { extensionBuild } = await import("extension-develop");
1749
- for (const vendor of list){
1750
- const vendorStart = Date.now();
1751
- telemetry.track('cli_vendor_start', {
1752
- command: 'build',
1753
- vendor
1754
- });
1755
- const buildSummary = await extensionBuild(pathOrRemoteUrl, {
1756
- browser: vendor,
1757
- polyfill: buildOptions.polyfill,
1758
- zip: buildOptions.zip,
1759
- zipSource: buildOptions.zipSource,
1760
- zipFilename: buildOptions.zipFilename,
1761
- silent: buildOptions.silent,
1762
- install: buildOptions.install,
1763
- extensions: parseExtensionsList(buildOptions.extensions)
1764
- });
1765
- telemetry.track('cli_build_summary', {
1766
- ...buildSummary,
1767
- browser_count: list.length,
1768
- is_multi_browser: list.length > 1,
1769
- is_remote_input: isRemoteInput,
1770
- artifact_kind: artifactKind,
1771
- ...workflowProfile
1772
- });
1773
- telemetry.track('cli_vendor_finish', {
1774
- command: 'build',
1775
- vendor,
1776
- duration_ms: Date.now() - vendorStart
1777
- });
1778
- }
1779
- telemetry.track('cli_command_finish', {
1853
+ telemetry.track('cli_vendor_finish', {
1780
1854
  command: 'build',
1781
- duration_ms: Date.now() - cmdStart,
1782
- success: 0 === process.exitCode || null == process.exitCode,
1783
- exit_code: process.exitCode ?? 0,
1784
- ...workflowProfile
1855
+ vendor,
1856
+ duration_ms: Date.now() - vendorStart
1785
1857
  });
1858
+ }
1859
+ telemetry.track('cli_command_finish', {
1860
+ command: 'build',
1861
+ duration_ms: Date.now() - cmdStart,
1862
+ success: 0 === process.exitCode || null == process.exitCode,
1863
+ exit_code: process.exitCode ?? 0,
1864
+ ...workflowProfile
1786
1865
  });
1866
+ });
1867
+ }
1868
+ function resolveManagedBrowsersCacheRoot() {
1869
+ const explicit = String(process.env.EXT_BROWSERS_CACHE_DIR || '').trim();
1870
+ if (explicit) return external_node_path_default().resolve(explicit);
1871
+ const isWin = 'win32' === process.platform;
1872
+ const isMac = 'darwin' === process.platform;
1873
+ if (isWin) {
1874
+ const local = String(process.env.LOCALAPPDATA || '').trim();
1875
+ if (local) return external_node_path_default().join(local, 'extension.js', 'browsers');
1876
+ const userProfile = String(process.env.USERPROFILE || '').trim();
1877
+ if (userProfile) return external_node_path_default().join(userProfile, 'AppData', 'Local', 'extension.js', 'browsers');
1878
+ return external_node_path_default().resolve(process.cwd(), '.cache', 'extension.js', 'browsers');
1787
1879
  }
1788
- function resolveManagedBrowsersCacheRoot() {
1789
- const explicit = String(process.env.EXT_BROWSERS_CACHE_DIR || '').trim();
1790
- if (explicit) return external_node_path_default().resolve(explicit);
1791
- const isWin = 'win32' === process.platform;
1792
- const isMac = 'darwin' === process.platform;
1793
- if (isWin) {
1794
- const local = String(process.env.LOCALAPPDATA || '').trim();
1795
- if (local) return external_node_path_default().join(local, 'extension.js', 'browsers');
1796
- const userProfile = String(process.env.USERPROFILE || '').trim();
1797
- if (userProfile) return external_node_path_default().join(userProfile, 'AppData', 'Local', 'extension.js', 'browsers');
1798
- return external_node_path_default().resolve(process.cwd(), '.cache', 'extension.js', 'browsers');
1799
- }
1800
- if (isMac) {
1801
- const home = String(process.env.HOME || '').trim();
1802
- if (home) return external_node_path_default().join(home, 'Library', 'Caches', 'extension.js', 'browsers');
1803
- return external_node_path_default().resolve(process.cwd(), '.cache', 'extension.js', 'browsers');
1804
- }
1805
- const xdg = String(process.env.XDG_CACHE_HOME || '').trim();
1806
- if (xdg) return external_node_path_default().join(xdg, 'extension.js', 'browsers');
1880
+ if (isMac) {
1807
1881
  const home = String(process.env.HOME || '').trim();
1808
- if (home) return external_node_path_default().join(home, '.cache', 'extension.js', 'browsers');
1882
+ if (home) return external_node_path_default().join(home, 'Library', 'Caches', 'extension.js', 'browsers');
1809
1883
  return external_node_path_default().resolve(process.cwd(), '.cache', 'extension.js', 'browsers');
1810
1884
  }
1811
- function normalizeInstallVendor(vendor) {
1812
- const value = String(vendor).trim().toLowerCase();
1813
- if ('chromium-based' === value) return 'chromium';
1814
- if ('gecko-based' === value || 'firefox-based' === value) return 'firefox';
1815
- if ('chrome' === value || 'chromium' === value || 'edge' === value || 'firefox' === value) return value;
1816
- return 'chromium';
1817
- }
1818
- function registerInstallCommand(program, telemetry) {
1819
- program.command('install').arguments('[browser-name]').usage('[browser-name] [options]').description(commandDescriptions.install).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | all>', 'override the positional browser name. Supports comma-separated values and `all`.').option('--where', 'print the resolved managed browser cache root').action(async function(browserArg, options) {
1820
- const startedAt = Date.now();
1821
- const selectedBrowser = options.browser || browserArg || 'chromium';
1822
- const browserList = vendors(selectedBrowser);
1823
- const workflowProfile = collectWorkflowProfile({
1824
- command: 'install',
1825
- isMultiBrowser: browserList.length > 1,
1826
- whereMode: Boolean(options.where)
1827
- });
1828
- validateVendorsOrExit(browserList, (invalid, supported)=>{
1829
- console.error(unsupportedBrowserFlag(invalid, supported));
1830
- });
1831
- telemetry.track('workflow_profile', {
1885
+ const xdg = String(process.env.XDG_CACHE_HOME || '').trim();
1886
+ if (xdg) return external_node_path_default().join(xdg, 'extension.js', 'browsers');
1887
+ const home = String(process.env.HOME || '').trim();
1888
+ if (home) return external_node_path_default().join(home, '.cache', 'extension.js', 'browsers');
1889
+ return external_node_path_default().resolve(process.cwd(), '.cache', 'extension.js', 'browsers');
1890
+ }
1891
+ function normalizeInstallVendor(vendor) {
1892
+ const value = String(vendor).trim().toLowerCase();
1893
+ if ('chromium-based' === value) return 'chromium';
1894
+ if ('gecko-based' === value || 'firefox-based' === value) return 'firefox';
1895
+ if ('chrome' === value || 'chromium' === value || 'edge' === value || 'firefox' === value) return value;
1896
+ return 'chromium';
1897
+ }
1898
+ function registerInstallCommand(program, telemetry) {
1899
+ program.command('install').arguments('[browser-name]').usage('[browser-name] [options]').description(commandDescriptions.install).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | all>', 'override the positional browser name. Supports comma-separated values and `all`.').option('--where', 'print the resolved managed browser cache root').action(async function(browserArg, options) {
1900
+ const startedAt = Date.now();
1901
+ const selectedBrowser = options.browser || browserArg || 'chromium';
1902
+ const browserList = vendors(selectedBrowser);
1903
+ const workflowProfile = collectWorkflowProfile({
1904
+ command: 'install',
1905
+ isMultiBrowser: browserList.length > 1,
1906
+ whereMode: Boolean(options.where)
1907
+ });
1908
+ validateVendorsOrExit(browserList, (invalid, supported)=>{
1909
+ console.error(unsupportedBrowserFlag(invalid, supported));
1910
+ });
1911
+ telemetry.track('workflow_profile', {
1912
+ command: 'install',
1913
+ ...workflowProfile
1914
+ });
1915
+ telemetry.track('cli_command_start', {
1916
+ command: 'install',
1917
+ vendors: browserList,
1918
+ browser_count: browserList.length,
1919
+ is_multi_browser: browserList.length > 1,
1920
+ where: Boolean(options.where),
1921
+ ...workflowProfile
1922
+ });
1923
+ try {
1924
+ if (options.where) {
1925
+ const root = resolveManagedBrowsersCacheRoot();
1926
+ if (options.browser || browserArg) for (const browser of browserList)console.log(external_node_path_default().join(root, normalizeInstallVendor(browser)));
1927
+ else console.log(root);
1928
+ } else {
1929
+ const { extensionInstall } = await import("extension-install");
1930
+ for (const browser of browserList)await extensionInstall({
1931
+ browser
1932
+ });
1933
+ }
1934
+ telemetry.track('cli_command_finish', {
1832
1935
  command: 'install',
1936
+ duration_ms: Date.now() - startedAt,
1937
+ success: true,
1938
+ exit_code: 0,
1833
1939
  ...workflowProfile
1834
1940
  });
1835
- telemetry.track('cli_command_start', {
1941
+ } catch (err) {
1942
+ telemetry.track('cli_command_finish', {
1836
1943
  command: 'install',
1837
- vendors: browserList,
1838
- browser_count: browserList.length,
1839
- is_multi_browser: browserList.length > 1,
1840
- where: Boolean(options.where),
1944
+ duration_ms: Date.now() - startedAt,
1945
+ success: false,
1946
+ exit_code: 1,
1841
1947
  ...workflowProfile
1842
1948
  });
1843
- try {
1844
- if (options.where) {
1845
- const root = resolveManagedBrowsersCacheRoot();
1846
- if (options.browser || browserArg) for (const browser of browserList)console.log(external_node_path_default().join(root, normalizeInstallVendor(browser)));
1847
- else console.log(root);
1848
- } else {
1849
- const { extensionInstall } = await import("extension-install");
1850
- for (const browser of browserList)await extensionInstall({
1851
- browser
1949
+ throw err;
1950
+ }
1951
+ });
1952
+ program.command('uninstall').usage('uninstall <browser-name> | uninstall --all | uninstall --where').description(commandDescriptions.uninstall).option('--browser <browser-name>', 'browser to uninstall').option('--all', 'remove all managed browser binaries').option('--where', 'print the resolved managed browser cache root').argument('[browser-name]').action(async function(browserArg, { browser, all, where }) {
1953
+ const startedAt = Date.now();
1954
+ const target = browserArg || browser;
1955
+ const workflowProfile = collectWorkflowProfile({
1956
+ command: 'uninstall',
1957
+ whereMode: Boolean(where)
1958
+ });
1959
+ telemetry.track('workflow_profile', {
1960
+ command: 'uninstall',
1961
+ ...workflowProfile
1962
+ });
1963
+ telemetry.track('cli_command_start', {
1964
+ command: 'uninstall',
1965
+ browser: target,
1966
+ all: Boolean(all),
1967
+ where: Boolean(where),
1968
+ ...workflowProfile
1969
+ });
1970
+ try {
1971
+ if (where) {
1972
+ const root = resolveManagedBrowsersCacheRoot();
1973
+ if (all) for (const browser of [
1974
+ 'chrome',
1975
+ 'chromium',
1976
+ 'edge',
1977
+ 'firefox'
1978
+ ])console.log(external_node_path_default().join(root, browser));
1979
+ else if (target) {
1980
+ const list = vendors(target);
1981
+ validateVendorsOrExit(list, (invalid, supported)=>{
1982
+ console.error(unsupportedBrowserFlag(invalid, supported));
1852
1983
  });
1853
- }
1854
- telemetry.track('cli_command_finish', {
1855
- command: 'install',
1856
- duration_ms: Date.now() - startedAt,
1857
- success: true,
1858
- exit_code: 0,
1859
- ...workflowProfile
1984
+ for (const browser of list)console.log(external_node_path_default().join(root, normalizeInstallVendor(browser)));
1985
+ } else console.log(root);
1986
+ } else {
1987
+ const { extensionUninstall } = await import("extension-install");
1988
+ await extensionUninstall({
1989
+ browser: target,
1990
+ all
1860
1991
  });
1861
- } catch (err) {
1862
- telemetry.track('cli_command_finish', {
1863
- command: 'install',
1864
- duration_ms: Date.now() - startedAt,
1865
- success: false,
1866
- exit_code: 1,
1867
- ...workflowProfile
1868
- });
1869
- throw err;
1870
1992
  }
1871
- });
1872
- program.command('uninstall').usage('uninstall <browser-name> | uninstall --all | uninstall --where').description(commandDescriptions.uninstall).option('--browser <browser-name>', 'browser to uninstall').option('--all', 'remove all managed browser binaries').option('--where', 'print the resolved managed browser cache root').argument('[browser-name]').action(async function(browserArg, { browser, all, where }) {
1873
- const startedAt = Date.now();
1874
- const target = browserArg || browser;
1875
- const workflowProfile = collectWorkflowProfile({
1876
- command: 'uninstall',
1877
- whereMode: Boolean(where)
1878
- });
1879
- telemetry.track('workflow_profile', {
1993
+ telemetry.track('cli_command_finish', {
1880
1994
  command: 'uninstall',
1995
+ duration_ms: Date.now() - startedAt,
1996
+ success: true,
1997
+ exit_code: 0,
1881
1998
  ...workflowProfile
1882
1999
  });
1883
- telemetry.track('cli_command_start', {
2000
+ } catch (err) {
2001
+ telemetry.track('cli_command_finish', {
1884
2002
  command: 'uninstall',
1885
- browser: target,
1886
- all: Boolean(all),
1887
- where: Boolean(where),
2003
+ duration_ms: Date.now() - startedAt,
2004
+ success: false,
2005
+ exit_code: 1,
1888
2006
  ...workflowProfile
1889
2007
  });
1890
- try {
1891
- if (where) {
1892
- const root = resolveManagedBrowsersCacheRoot();
1893
- if (all) for (const browser of [
1894
- 'chrome',
1895
- 'chromium',
1896
- 'edge',
1897
- 'firefox'
1898
- ])console.log(external_node_path_default().join(root, browser));
1899
- else if (target) {
1900
- const list = vendors(target);
1901
- validateVendorsOrExit(list, (invalid, supported)=>{
1902
- console.error(unsupportedBrowserFlag(invalid, supported));
1903
- });
1904
- for (const browser of list)console.log(external_node_path_default().join(root, normalizeInstallVendor(browser)));
1905
- } else console.log(root);
1906
- } else {
1907
- const { extensionUninstall } = await import("extension-install");
1908
- await extensionUninstall({
1909
- browser: target,
1910
- all
1911
- });
1912
- }
1913
- telemetry.track('cli_command_finish', {
1914
- command: 'uninstall',
1915
- duration_ms: Date.now() - startedAt,
1916
- success: true,
1917
- exit_code: 0,
1918
- ...workflowProfile
1919
- });
1920
- } catch (err) {
1921
- telemetry.track('cli_command_finish', {
1922
- command: 'uninstall',
1923
- duration_ms: Date.now() - startedAt,
1924
- success: false,
1925
- exit_code: 1,
1926
- ...workflowProfile
1927
- });
1928
- throw err;
1929
- }
1930
- });
1931
- }
1932
- const cliPackageJson = getCliPackageJson();
1933
- function developVersion() {
1934
- try {
1935
- const pkg = __webpack_require__("extension-develop/package.json");
1936
- return pkg?.version || cliPackageJson.version;
1937
- } catch {
1938
- return cliPackageJson.version;
2008
+ throw err;
1939
2009
  }
2010
+ });
2011
+ }
2012
+ const cliPackageJson = getCliPackageJson();
2013
+ function developVersion() {
2014
+ return resolveExtensionDevelopVersion(__dirname, cliPackageJson.version);
2015
+ }
2016
+ process.env.EXTENSION_DEVELOP_VERSION = developVersion();
2017
+ function resolveAIHelpFormatFromArgv(argv) {
2018
+ const equalArg = argv.find((arg)=>arg.startsWith('--format='));
2019
+ if (equalArg) return equalArg.slice(9);
2020
+ const formatIndex = argv.indexOf('--format');
2021
+ if (formatIndex >= 0) return argv[formatIndex + 1] || '';
2022
+ return 'pretty';
2023
+ }
2024
+ function resolveCommandFromArgv(argv) {
2025
+ for(let i = 2; i < argv.length; i += 1){
2026
+ const arg = argv[i];
2027
+ if (!arg.startsWith('-')) return arg;
1940
2028
  }
1941
- process.env.EXTENSION_DEVELOP_VERSION = developVersion();
1942
- function resolveAIHelpFormatFromArgv(argv) {
1943
- const equalArg = argv.find((arg)=>arg.startsWith('--format='));
1944
- if (equalArg) return equalArg.slice(9);
1945
- const formatIndex = argv.indexOf('--format');
1946
- if (formatIndex >= 0) return argv[formatIndex + 1] || '';
1947
- return 'pretty';
1948
- }
1949
- function resolveCommandFromArgv(argv) {
1950
- for(let i = 2; i < argv.length; i += 1){
1951
- const arg = argv[i];
1952
- if (!arg.startsWith('-')) return arg;
1953
- }
2029
+ }
2030
+ function applyNoBrowserArgvShim(argv) {
2031
+ const hasNoRunner = argv.includes('--no-runner');
2032
+ if (hasNoRunner) {
2033
+ console.error(removedNoRunnerFlag());
2034
+ process.exit(1);
1954
2035
  }
1955
- function applyNoBrowserArgvShim(argv) {
1956
- const hasNoRunner = argv.includes('--no-runner');
1957
- if (hasNoRunner) {
1958
- console.error(removedNoRunnerFlag());
1959
- process.exit(1);
1960
- }
1961
- const hasNoBrowser = argv.includes('--no-browser');
1962
- if (!hasNoBrowser) return argv;
1963
- const command = resolveCommandFromArgv(argv);
1964
- const supportsNoBrowser = 'dev' === command || 'start' === command || 'preview' === command;
1965
- if (!supportsNoBrowser) {
1966
- console.error(noBrowserNotSupportedForCommand(command));
1967
- process.exit(1);
1968
- }
1969
- process.env.EXTENSION_CLI_NO_BROWSER = '1';
1970
- return argv.filter((arg)=>'--no-browser' !== arg);
2036
+ const hasNoBrowser = argv.includes('--no-browser');
2037
+ if (!hasNoBrowser) return argv;
2038
+ const command = resolveCommandFromArgv(argv);
2039
+ const supportsNoBrowser = 'dev' === command || 'start' === command || 'preview' === command;
2040
+ if (!supportsNoBrowser) {
2041
+ console.error(noBrowserNotSupportedForCommand(command));
2042
+ process.exit(1);
1971
2043
  }
1972
- check_updates_checkUpdates().then((updateMessage)=>{
1973
- if (!updateMessage) return;
1974
- if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) return void console.log(updateMessage.message);
1975
- process.env.EXTENSION_CLI_UPDATE_SUFFIX = updateMessage.suffix;
1976
- });
1977
- const extensionJs = external_commander_namespaceObject.program;
1978
- extensionJs.name(cliPackageJson.name).description(cliPackageJson.description).version(cliPackageJson.version).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').option('--format <pretty|json>', 'output format for --ai-help', 'pretty').addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true);
1979
- registerCreateCommand(extensionJs, telemetry_cli_telemetry);
1980
- registerDevCommand(extensionJs, telemetry_cli_telemetry);
1981
- registerStartCommand(extensionJs, telemetry_cli_telemetry);
1982
- registerPreviewCommand(extensionJs, telemetry_cli_telemetry);
1983
- registerBuildCommand(extensionJs, telemetry_cli_telemetry);
1984
- registerInstallCommand(extensionJs, telemetry_cli_telemetry);
1985
- extensionJs.on('option:ai-help', function() {
1986
- const format = resolveAIHelpFormatFromArgv(process.argv).trim().toLowerCase();
1987
- if ('json' === format) {
1988
- console.log(JSON.stringify(programAIHelpJSON(cliPackageJson.version), null, 2));
1989
- process.exit(0);
1990
- }
1991
- if ('pretty' !== format) {
1992
- console.error(invalidAIHelpFormat(format));
1993
- process.exit(1);
1994
- }
1995
- console.log(programAIHelp());
1996
- process.exit(0);
1997
- });
1998
- if (process.argv.length <= 2) {
1999
- extensionJs.outputHelp();
2044
+ process.env.EXTENSION_CLI_NO_BROWSER = '1';
2045
+ return argv.filter((arg)=>'--no-browser' !== arg);
2046
+ }
2047
+ check_updates_checkUpdates().then((updateMessage)=>{
2048
+ if (!updateMessage) return;
2049
+ if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) return void console.log(updateMessage.message);
2050
+ process.env.EXTENSION_CLI_UPDATE_SUFFIX = updateMessage.suffix;
2051
+ });
2052
+ const extensionJs = external_commander_namespaceObject.program;
2053
+ extensionJs.name(cliPackageJson.name).description(cliPackageJson.description).version(cliPackageJson.version).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').option('--format <pretty|json>', 'output format for --ai-help', 'pretty').addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true);
2054
+ registerCreateCommand(extensionJs, telemetry_cli_telemetry);
2055
+ registerDevCommand(extensionJs, telemetry_cli_telemetry);
2056
+ registerStartCommand(extensionJs, telemetry_cli_telemetry);
2057
+ registerPreviewCommand(extensionJs, telemetry_cli_telemetry);
2058
+ registerBuildCommand(extensionJs, telemetry_cli_telemetry);
2059
+ registerInstallCommand(extensionJs, telemetry_cli_telemetry);
2060
+ extensionJs.on('option:ai-help', function() {
2061
+ const format = resolveAIHelpFormatFromArgv(process.argv).trim().toLowerCase();
2062
+ if ('json' === format) {
2063
+ console.log(JSON.stringify(programAIHelpJSON(cliPackageJson.version), null, 2));
2000
2064
  process.exit(0);
2001
2065
  }
2002
- const index_argv = applyNoBrowserArgvShim(process.argv);
2003
- extensionJs.parseAsync(index_argv).catch((err)=>{
2004
- console.error(unhandledError(err));
2066
+ if ('pretty' !== format) {
2067
+ console.error(invalidAIHelpFormat(format));
2005
2068
  process.exit(1);
2006
- });
2007
- })();
2069
+ }
2070
+ console.log(programAIHelp());
2071
+ process.exit(0);
2072
+ });
2073
+ if (process.argv.length <= 2) {
2074
+ extensionJs.outputHelp();
2075
+ process.exit(0);
2076
+ }
2077
+ const index_argv = applyNoBrowserArgvShim(process.argv);
2078
+ extensionJs.parseAsync(index_argv).catch((err)=>{
2079
+ console.error(unhandledError(err));
2080
+ process.exit(1);
2081
+ });
2008
2082
  for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
2009
2083
  Object.defineProperty(exports, '__esModule', {
2010
2084
  value: true