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-lib/extension-develop-runtime.d.ts +3 -0
- package/dist/cli.cjs +1674 -1600
- package/package.json +4 -4
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
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
'
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
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
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return
|
|
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
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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
|
-
|
|
587
|
-
|
|
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().
|
|
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
|
-
|
|
729
|
+
this.disabled = true;
|
|
730
|
+
return;
|
|
596
731
|
}
|
|
597
|
-
|
|
598
|
-
|
|
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
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
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
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
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
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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
|
-
|
|
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
|
-
|
|
766
|
-
|
|
960
|
+
entries = external_fs_default().readdirSync(dir, {
|
|
961
|
+
withFileTypes: true
|
|
962
|
+
});
|
|
767
963
|
} catch {
|
|
768
|
-
|
|
964
|
+
continue;
|
|
769
965
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
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
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
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
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
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
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
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
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
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
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
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
|
-
|
|
1144
|
-
|
|
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
|
-
|
|
1226
|
+
} catch (error) {
|
|
1227
|
+
if (error instanceof Error) throw error;
|
|
1228
|
+
throw new Error(String(error));
|
|
1148
1229
|
}
|
|
1149
|
-
|
|
1230
|
+
await new Promise((resolve)=>setTimeout(resolve, 250));
|
|
1150
1231
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
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
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
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
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
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
|
-
|
|
1421
|
+
if ('json' === waitResult.format) console.log(JSON.stringify({
|
|
1422
|
+
ok: true,
|
|
1423
|
+
mode: 'wait',
|
|
1309
1424
|
command: 'dev',
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1425
|
+
browsers: waitResult.browsers,
|
|
1426
|
+
results: waitResult.results
|
|
1427
|
+
}));
|
|
1428
|
+
telemetry.track('cli_command_finish', {
|
|
1313
1429
|
command: 'dev',
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
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
|
-
|
|
1329
|
-
|
|
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
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
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
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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
|
-
|
|
1429
|
-
|
|
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
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
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
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
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
|
-
|
|
1572
|
+
if ('json' === waitResult.format) console.log(JSON.stringify({
|
|
1573
|
+
ok: true,
|
|
1574
|
+
mode: 'wait',
|
|
1465
1575
|
command: 'start',
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1576
|
+
browsers: waitResult.browsers,
|
|
1577
|
+
results: waitResult.results
|
|
1578
|
+
}));
|
|
1579
|
+
telemetry.track('cli_command_finish', {
|
|
1469
1580
|
command: 'start',
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
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
|
-
|
|
1481
|
-
|
|
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
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
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
|
-
|
|
1513
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1577
|
-
|
|
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
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
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
|
-
|
|
1638
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1701
|
-
|
|
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
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
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('
|
|
1734
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1782
|
-
|
|
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
|
-
|
|
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, '
|
|
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
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
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
|
-
|
|
1941
|
+
} catch (err) {
|
|
1942
|
+
telemetry.track('cli_command_finish', {
|
|
1836
1943
|
command: 'install',
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
where: Boolean(options.where),
|
|
1944
|
+
duration_ms: Date.now() - startedAt,
|
|
1945
|
+
success: false,
|
|
1946
|
+
exit_code: 1,
|
|
1841
1947
|
...workflowProfile
|
|
1842
1948
|
});
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
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
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
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
|
-
|
|
2000
|
+
} catch (err) {
|
|
2001
|
+
telemetry.track('cli_command_finish', {
|
|
1884
2002
|
command: 'uninstall',
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
2003
|
+
duration_ms: Date.now() - startedAt,
|
|
2004
|
+
success: false,
|
|
2005
|
+
exit_code: 1,
|
|
1888
2006
|
...workflowProfile
|
|
1889
2007
|
});
|
|
1890
|
-
|
|
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
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
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
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
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
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
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
|
-
|
|
2003
|
-
|
|
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
|