extension 3.2.0-next.9 → 3.2.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/README.md +2 -2
- package/dist/check-updates.d.ts +4 -1
- package/dist/cli-lib/messages.d.ts +4 -1
- package/dist/cli.js +733 -707
- package/package.json +4 -15
- package/dist/types/index.d.ts +0 -0
- package/types/css-content.d.ts +0 -15
- package/types/css-modules.d.ts +0 -27
- package/types/extension-create-shim.d.ts +0 -24
- package/types/extension-develop-shim.d.ts +0 -105
- package/types/images.d.ts +0 -66
- package/types/index.d.ts +0 -69
- package/types/index.ts +0 -15
- package/types/js-frameworks.d.ts +0 -11
- package/types/polyfill.d.ts +0 -15
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var
|
|
3
|
+
var __webpack_modules__ = {
|
|
4
|
+
"extension-develop/package.json" (module) {
|
|
5
|
+
module.exports = require("extension-develop/package.json");
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var __webpack_module_cache__ = {};
|
|
9
|
+
function __webpack_require__(moduleId) {
|
|
10
|
+
var cachedModule = __webpack_module_cache__[moduleId];
|
|
11
|
+
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
12
|
+
var module = __webpack_module_cache__[moduleId] = {
|
|
13
|
+
exports: {}
|
|
14
|
+
};
|
|
15
|
+
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
16
|
+
return module.exports;
|
|
17
|
+
}
|
|
4
18
|
(()=>{
|
|
5
19
|
__webpack_require__.n = (module)=>{
|
|
6
20
|
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
@@ -22,66 +36,72 @@ var __webpack_require__ = {};
|
|
|
22
36
|
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
23
37
|
})();
|
|
24
38
|
var __webpack_exports__ = {};
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const code = (text)=>external_pintor_default().blue(text);
|
|
42
|
-
const arg = (text)=>external_pintor_default().gray(text);
|
|
43
|
-
const fmt = {
|
|
44
|
-
heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
|
|
45
|
-
label: (k)=>external_pintor_default().gray(k.toUpperCase()),
|
|
46
|
-
val: (v)=>external_pintor_default().underline(v),
|
|
47
|
-
code: (v)=>external_pintor_default().blue(v),
|
|
48
|
-
bullet: (s)=>`- ${s}`,
|
|
49
|
-
block (title, rows) {
|
|
50
|
-
const head = fmt.heading(title);
|
|
51
|
-
const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
|
|
52
|
-
return `${head}\n${body}`;
|
|
53
|
-
},
|
|
54
|
-
truncate (input, max = 800) {
|
|
55
|
-
const s = (()=>{
|
|
56
|
-
try {
|
|
57
|
-
return 'string' == typeof input ? input : JSON.stringify(input);
|
|
58
|
-
} catch {
|
|
59
|
-
return String(input);
|
|
60
|
-
}
|
|
61
|
-
})();
|
|
62
|
-
return s.length > max ? s.slice(0, max) + '…' : s;
|
|
39
|
+
(()=>{
|
|
40
|
+
const external_commander_namespaceObject = require("commander");
|
|
41
|
+
const external_update_check_namespaceObject = require("update-check");
|
|
42
|
+
var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
|
|
43
|
+
const external_pintor_namespaceObject = require("pintor");
|
|
44
|
+
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
|
|
45
|
+
function getLoggingPrefix(type) {
|
|
46
|
+
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
47
|
+
if (isAuthor) {
|
|
48
|
+
const base = 'error' === type ? 'ERROR Author says' : '►►► Author says';
|
|
49
|
+
return external_pintor_default().brightMagenta(base);
|
|
50
|
+
}
|
|
51
|
+
if ('error' === type) return external_pintor_default().red('ERROR');
|
|
52
|
+
if ('warn' === type) return external_pintor_default().brightYellow('►►►');
|
|
53
|
+
if ('info' === type) return external_pintor_default().gray('►►►');
|
|
54
|
+
return external_pintor_default().green('►►►');
|
|
63
55
|
}
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
56
|
+
const code = (text)=>external_pintor_default().blue(text);
|
|
57
|
+
const arg = (text)=>external_pintor_default().gray(text);
|
|
58
|
+
const fmt = {
|
|
59
|
+
heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
|
|
60
|
+
label: (k)=>external_pintor_default().gray(k.toUpperCase()),
|
|
61
|
+
val: (v)=>external_pintor_default().underline(v),
|
|
62
|
+
code: (v)=>external_pintor_default().blue(v),
|
|
63
|
+
bullet: (s)=>`- ${s}`,
|
|
64
|
+
block (title, rows) {
|
|
65
|
+
const head = fmt.heading(title);
|
|
66
|
+
const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
|
|
67
|
+
return `${head}\n${body}`;
|
|
68
|
+
},
|
|
69
|
+
truncate (input, max = 800) {
|
|
70
|
+
const s = (()=>{
|
|
71
|
+
try {
|
|
72
|
+
return 'string' == typeof input ? input : JSON.stringify(input);
|
|
73
|
+
} catch {
|
|
74
|
+
return String(input);
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
return s.length > max ? s.slice(0, max) + '…' : s;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const commandDescriptions = {
|
|
81
|
+
create: 'Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
|
|
82
|
+
dev: 'Starts the development server with hot reloading',
|
|
83
|
+
start: 'Builds and starts the extension in production mode',
|
|
84
|
+
preview: 'Previews the extension in production mode without building',
|
|
85
|
+
build: 'Builds the extension for packaging/distribution',
|
|
86
|
+
cleanup: 'Cleans up orphaned instances and frees unused ports'
|
|
87
|
+
};
|
|
88
|
+
function unhandledError(err) {
|
|
89
|
+
const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : fmt.truncate(err);
|
|
90
|
+
return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
|
|
91
|
+
}
|
|
92
|
+
function updateFailed(err) {
|
|
93
|
+
return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String(err?.message || err))}`;
|
|
94
|
+
}
|
|
95
|
+
function checkUpdates(packageJson, update) {
|
|
96
|
+
const suffix = external_pintor_default().gray(`(version ${String(update.latest)} is available!)`);
|
|
97
|
+
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.`;
|
|
98
|
+
return {
|
|
99
|
+
suffix,
|
|
100
|
+
message
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function programUserHelp() {
|
|
104
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
|
|
85
105
|
|
|
86
106
|
Usage: extension [command] [options]
|
|
87
107
|
|
|
@@ -159,12 +179,12 @@ AI Assistants
|
|
|
159
179
|
|
|
160
180
|
Report issues
|
|
161
181
|
- ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
|
|
162
|
-
}
|
|
163
|
-
function unsupportedBrowserFlag(value, supported) {
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
function programAIHelp() {
|
|
167
|
-
|
|
182
|
+
}
|
|
183
|
+
function unsupportedBrowserFlag(value, supported) {
|
|
184
|
+
return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}. Supported: ${supported.join(', ')}.`;
|
|
185
|
+
}
|
|
186
|
+
function programAIHelp() {
|
|
187
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
|
|
168
188
|
|
|
169
189
|
Browser-Specific Configuration
|
|
170
190
|
- Use browser prefixes in manifest.json for browser-specific fields:
|
|
@@ -297,697 +317,703 @@ Cross-Browser Compatibility
|
|
|
297
317
|
- Use ${code('--polyfill')} flag to enable webextension-polyfill
|
|
298
318
|
- Automatically handles browser API differences
|
|
299
319
|
- Supports Chrome, Edge, Firefox with single codebase`;
|
|
300
|
-
}
|
|
301
|
-
const external_semver_namespaceObject = require("semver");
|
|
302
|
-
const external_node_fs_namespaceObject = require("node:fs");
|
|
303
|
-
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
304
|
-
const external_node_path_namespaceObject = require("node:path");
|
|
305
|
-
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
306
|
-
let cachedPackageJson = null;
|
|
307
|
-
function getCliPackageJson() {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
function isStableVersion(version) {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
async function check_updates_checkUpdates() {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const
|
|
339
|
-
var
|
|
340
|
-
const
|
|
341
|
-
var
|
|
342
|
-
const
|
|
343
|
-
var
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return obj;
|
|
353
|
-
}
|
|
354
|
-
function isCI() {
|
|
355
|
-
const v = process.env;
|
|
356
|
-
return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
|
|
357
|
-
}
|
|
358
|
-
function configDir() {
|
|
359
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
360
|
-
if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
|
|
361
|
-
if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
|
|
362
|
-
return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
|
|
363
|
-
}
|
|
364
|
-
function telemetry_cacheDir() {
|
|
365
|
-
const xdg = process.env.XDG_CACHE_HOME;
|
|
366
|
-
if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
|
|
367
|
-
if ('win32' === process.platform) {
|
|
368
|
-
const base = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
369
|
-
if (base) return external_node_path_default().join(base, 'extensionjs', 'Cache');
|
|
370
|
-
}
|
|
371
|
-
if ('darwin' === process.platform) return external_node_path_default().join(external_node_os_default().homedir(), 'Library', 'Caches', 'extensionjs');
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
|
-
function ensureDir(p) {
|
|
375
|
-
try {
|
|
376
|
-
if (external_node_fs_default().existsSync(p)) return true;
|
|
377
|
-
external_node_fs_default().mkdirSync(p, {
|
|
378
|
-
recursive: true
|
|
320
|
+
}
|
|
321
|
+
const external_semver_namespaceObject = require("semver");
|
|
322
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
323
|
+
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
324
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
325
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
326
|
+
let cachedPackageJson = null;
|
|
327
|
+
function getCliPackageJson() {
|
|
328
|
+
if (cachedPackageJson) return cachedPackageJson;
|
|
329
|
+
const candidates = [
|
|
330
|
+
external_node_path_default().resolve(__dirname, 'package.json'),
|
|
331
|
+
external_node_path_default().resolve(__dirname, '..', 'package.json')
|
|
332
|
+
];
|
|
333
|
+
for (const candidate of candidates)if (external_node_fs_default().existsSync(candidate)) {
|
|
334
|
+
const content = external_node_fs_default().readFileSync(candidate, 'utf8');
|
|
335
|
+
const parsed = JSON.parse(content);
|
|
336
|
+
cachedPackageJson = parsed;
|
|
337
|
+
return parsed;
|
|
338
|
+
}
|
|
339
|
+
throw new Error('Extension.js CLI package.json not found.');
|
|
340
|
+
}
|
|
341
|
+
function isStableVersion(version) {
|
|
342
|
+
const v = external_semver_namespaceObject.parse(version);
|
|
343
|
+
return Boolean(v && 0 === v.prerelease.length);
|
|
344
|
+
}
|
|
345
|
+
async function check_updates_checkUpdates() {
|
|
346
|
+
const packageJson = getCliPackageJson();
|
|
347
|
+
let update = null;
|
|
348
|
+
try {
|
|
349
|
+
update = await external_update_check_default()(packageJson);
|
|
350
|
+
} catch (err) {
|
|
351
|
+
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(updateFailed(err));
|
|
352
|
+
}
|
|
353
|
+
if (update && isStableVersion(update.latest)) {
|
|
354
|
+
if (isStableVersion(packageJson.version)) return checkUpdates(packageJson, update);
|
|
355
|
+
}
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const external_fs_namespaceObject = require("fs");
|
|
359
|
+
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
360
|
+
const external_path_namespaceObject = require("path");
|
|
361
|
+
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
362
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
363
|
+
var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
|
|
364
|
+
const external_node_crypto_namespaceObject = require("node:crypto");
|
|
365
|
+
var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
|
|
366
|
+
function _define_property(obj, key, value) {
|
|
367
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
368
|
+
value: value,
|
|
369
|
+
enumerable: true,
|
|
370
|
+
configurable: true,
|
|
371
|
+
writable: true
|
|
379
372
|
});
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
return false;
|
|
373
|
+
else obj[key] = value;
|
|
374
|
+
return obj;
|
|
383
375
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
try {
|
|
388
|
-
external_node_fs_default().accessSync(p, external_node_fs_default().constants.W_OK);
|
|
389
|
-
const probe = external_node_path_default().join(p, `.write-test-${process.pid}-${Date.now()}`);
|
|
390
|
-
external_node_fs_default().writeFileSync(probe, 'ok', 'utf8');
|
|
391
|
-
external_node_fs_default().unlinkSync(probe);
|
|
392
|
-
return true;
|
|
393
|
-
} catch {
|
|
394
|
-
return false;
|
|
376
|
+
function isCI() {
|
|
377
|
+
const v = process.env;
|
|
378
|
+
return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
|
|
395
379
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
const id = external_node_crypto_default().randomUUID();
|
|
402
|
-
if (ensureDir(external_node_path_default().dirname(file))) try {
|
|
403
|
-
external_node_fs_default().writeFileSync(file, id, 'utf8');
|
|
404
|
-
} catch {}
|
|
405
|
-
return id;
|
|
406
|
-
}
|
|
407
|
-
function telemetryCandidates() {
|
|
408
|
-
const candidates = [
|
|
409
|
-
configDir(),
|
|
410
|
-
telemetry_cacheDir(),
|
|
411
|
-
external_node_path_default().join(external_node_os_default().tmpdir(), 'extensionjs'),
|
|
412
|
-
external_node_path_default().join(process.cwd(), '.cache', 'extensionjs')
|
|
413
|
-
].filter(Boolean);
|
|
414
|
-
return Array.from(new Set(candidates));
|
|
415
|
-
}
|
|
416
|
-
function resolveTelemetryStorage() {
|
|
417
|
-
for (const base of telemetryCandidates()){
|
|
418
|
-
const telemetryDir = external_node_path_default().join(base, 'telemetry');
|
|
419
|
-
if (ensureWritableDir(telemetryDir)) return {
|
|
420
|
-
telemetryDir,
|
|
421
|
-
auditFile: external_node_path_default().join(telemetryDir, 'events.jsonl'),
|
|
422
|
-
idFile: external_node_path_default().join(telemetryDir, 'anonymous-id'),
|
|
423
|
-
consentFile: external_node_path_default().join(telemetryDir, 'consent')
|
|
424
|
-
};
|
|
380
|
+
function configDir() {
|
|
381
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
382
|
+
if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
|
|
383
|
+
if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
|
|
384
|
+
return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
|
|
425
385
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
...this.common,
|
|
438
|
-
...props,
|
|
439
|
-
$ip: null
|
|
440
|
-
},
|
|
441
|
-
distinct_id: this.anonId
|
|
442
|
-
};
|
|
386
|
+
function telemetry_cacheDir() {
|
|
387
|
+
const xdg = process.env.XDG_CACHE_HOME;
|
|
388
|
+
if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
|
|
389
|
+
if ('win32' === process.platform) {
|
|
390
|
+
const base = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
391
|
+
if (base) return external_node_path_default().join(base, 'extensionjs', 'Cache');
|
|
392
|
+
}
|
|
393
|
+
if ('darwin' === process.platform) return external_node_path_default().join(external_node_os_default().homedir(), 'Library', 'Caches', 'extensionjs');
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
function ensureDir(p) {
|
|
443
397
|
try {
|
|
444
|
-
external_node_fs_default().
|
|
398
|
+
if (external_node_fs_default().existsSync(p)) return true;
|
|
399
|
+
external_node_fs_default().mkdirSync(p, {
|
|
400
|
+
recursive: true
|
|
401
|
+
});
|
|
402
|
+
return true;
|
|
445
403
|
} catch {
|
|
446
|
-
|
|
447
|
-
return;
|
|
404
|
+
return false;
|
|
448
405
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
|
|
453
|
-
if (!this.timer) this.timer = setTimeout(()=>{
|
|
454
|
-
this.timer = null;
|
|
455
|
-
this.flush();
|
|
456
|
-
}, DEFAULT_FLUSH_INTERVAL);
|
|
457
|
-
}
|
|
458
|
-
async flush() {
|
|
459
|
-
if (this.disabled || !this.apiKey || !this.host) return;
|
|
460
|
-
if (0 === this.buffer.length) return;
|
|
461
|
-
const batch = this.buffer.splice(0, this.buffer.length);
|
|
406
|
+
}
|
|
407
|
+
function ensureWritableDir(p) {
|
|
408
|
+
if (!ensureDir(p)) return false;
|
|
462
409
|
try {
|
|
463
|
-
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
signal: ac.signal,
|
|
480
|
-
keepalive: true
|
|
481
|
-
}).catch(()=>{});
|
|
482
|
-
clearTimeout(t);
|
|
410
|
+
external_node_fs_default().accessSync(p, external_node_fs_default().constants.W_OK);
|
|
411
|
+
const probe = external_node_path_default().join(p, `.write-test-${process.pid}-${Date.now()}`);
|
|
412
|
+
external_node_fs_default().writeFileSync(probe, 'ok', 'utf8');
|
|
413
|
+
external_node_fs_default().unlinkSync(probe);
|
|
414
|
+
return true;
|
|
415
|
+
} catch {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function loadOrCreateId(file) {
|
|
420
|
+
try {
|
|
421
|
+
if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
|
|
422
|
+
} catch {}
|
|
423
|
+
const id = external_node_crypto_default().randomUUID();
|
|
424
|
+
if (ensureDir(external_node_path_default().dirname(file))) try {
|
|
425
|
+
external_node_fs_default().writeFileSync(file, id, 'utf8');
|
|
483
426
|
} catch {}
|
|
427
|
+
return id;
|
|
484
428
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
429
|
+
function telemetryCandidates() {
|
|
430
|
+
const candidates = [
|
|
431
|
+
configDir(),
|
|
432
|
+
telemetry_cacheDir(),
|
|
433
|
+
external_node_path_default().join(external_node_os_default().tmpdir(), 'extensionjs'),
|
|
434
|
+
external_node_path_default().join(process.cwd(), '.cache', 'extensionjs')
|
|
435
|
+
].filter(Boolean);
|
|
436
|
+
return Array.from(new Set(candidates));
|
|
437
|
+
}
|
|
438
|
+
function resolveTelemetryStorage() {
|
|
439
|
+
for (const base of telemetryCandidates()){
|
|
440
|
+
const telemetryDir = external_node_path_default().join(base, 'telemetry');
|
|
441
|
+
if (ensureWritableDir(telemetryDir)) return {
|
|
442
|
+
telemetryDir,
|
|
443
|
+
auditFile: external_node_path_default().join(telemetryDir, 'events.jsonl'),
|
|
444
|
+
idFile: external_node_path_default().join(telemetryDir, 'anonymous-id'),
|
|
445
|
+
consentFile: external_node_path_default().join(telemetryDir, 'consent')
|
|
446
|
+
};
|
|
503
447
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
|
|
451
|
+
const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
|
|
452
|
+
const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
|
|
453
|
+
class Telemetry {
|
|
454
|
+
track(event, props = {}) {
|
|
455
|
+
if (this.disabled || !this.storage) return;
|
|
456
|
+
const payload = {
|
|
457
|
+
event,
|
|
458
|
+
properties: {
|
|
459
|
+
...this.common,
|
|
460
|
+
...props,
|
|
461
|
+
$ip: null
|
|
462
|
+
},
|
|
463
|
+
distinct_id: this.anonId
|
|
464
|
+
};
|
|
517
465
|
try {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
466
|
+
external_node_fs_default().appendFileSync(this.storage.auditFile, JSON.stringify(payload) + '\n');
|
|
467
|
+
} catch {
|
|
468
|
+
this.disabled = true;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
|
|
472
|
+
if (!this.apiKey || !this.host) return;
|
|
473
|
+
this.buffer.push(payload);
|
|
474
|
+
if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
|
|
475
|
+
if (!this.timer) this.timer = setTimeout(()=>{
|
|
476
|
+
this.timer = null;
|
|
477
|
+
this.flush();
|
|
478
|
+
}, DEFAULT_FLUSH_INTERVAL);
|
|
479
|
+
}
|
|
480
|
+
async flush() {
|
|
481
|
+
if (this.disabled || !this.apiKey || !this.host) return;
|
|
482
|
+
if (0 === this.buffer.length) return;
|
|
483
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
484
|
+
try {
|
|
485
|
+
const ac = new AbortController();
|
|
486
|
+
const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
|
|
487
|
+
const url = new URL('/capture/', this.host);
|
|
488
|
+
await fetch(url.toString(), {
|
|
489
|
+
method: 'POST',
|
|
490
|
+
headers: {
|
|
491
|
+
'content-type': 'application/json'
|
|
492
|
+
},
|
|
493
|
+
body: JSON.stringify({
|
|
494
|
+
api_key: this.apiKey,
|
|
495
|
+
batch: batch.map((e)=>({
|
|
496
|
+
event: e.event,
|
|
497
|
+
properties: e.properties,
|
|
498
|
+
distinct_id: e.distinct_id
|
|
499
|
+
}))
|
|
500
|
+
}),
|
|
501
|
+
signal: ac.signal,
|
|
502
|
+
keepalive: true
|
|
503
|
+
}).catch(()=>{});
|
|
504
|
+
clearTimeout(t);
|
|
525
505
|
} catch {}
|
|
526
506
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (!dir) continue;
|
|
570
|
-
let entries;
|
|
571
|
-
try {
|
|
572
|
-
entries = external_fs_default().readdirSync(dir, {
|
|
573
|
-
withFileTypes: true
|
|
574
|
-
});
|
|
575
|
-
} catch {
|
|
576
|
-
continue;
|
|
507
|
+
shutdown() {}
|
|
508
|
+
constructor(init){
|
|
509
|
+
_define_property(this, "anonId", void 0);
|
|
510
|
+
_define_property(this, "common", void 0);
|
|
511
|
+
_define_property(this, "debug", void 0);
|
|
512
|
+
_define_property(this, "disabled", void 0);
|
|
513
|
+
_define_property(this, "apiKey", void 0);
|
|
514
|
+
_define_property(this, "host", void 0);
|
|
515
|
+
_define_property(this, "storage", null);
|
|
516
|
+
_define_property(this, "buffer", []);
|
|
517
|
+
_define_property(this, "timer", null);
|
|
518
|
+
this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
|
|
519
|
+
this.disabled = Boolean(init.disabled);
|
|
520
|
+
this.anonId = 'disabled';
|
|
521
|
+
if (!this.disabled) {
|
|
522
|
+
this.storage = resolveTelemetryStorage();
|
|
523
|
+
if (this.storage) this.anonId = loadOrCreateId(this.storage.idFile);
|
|
524
|
+
else this.disabled = true;
|
|
525
|
+
}
|
|
526
|
+
this.common = {
|
|
527
|
+
app: init.app,
|
|
528
|
+
version: init.version,
|
|
529
|
+
os: process.platform,
|
|
530
|
+
arch: process.arch,
|
|
531
|
+
node: process.versions.node,
|
|
532
|
+
is_ci: isCI(),
|
|
533
|
+
schema_version: 1
|
|
534
|
+
};
|
|
535
|
+
this.apiKey = init.apiKey || process.env.EXTENSION_PUBLIC_POSTHOG_KEY;
|
|
536
|
+
this.host = init.host || process.env.EXTENSION_PUBLIC_POSTHOG_HOST;
|
|
537
|
+
if (!this.disabled && this.storage) {
|
|
538
|
+
const consentPath = this.storage.consentFile;
|
|
539
|
+
try {
|
|
540
|
+
if (!external_node_fs_default().existsSync(consentPath)) {
|
|
541
|
+
external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
|
|
542
|
+
this.track('cli_telemetry_consent', {
|
|
543
|
+
value: 'implicit_opt_in'
|
|
544
|
+
});
|
|
545
|
+
console.log(`${external_pintor_default().gray('►►►')} Telemetry is enabled for Extension.js. To opt out, run with --no-telemetry. Learn more in TELEMETRY.md.`);
|
|
546
|
+
}
|
|
547
|
+
} catch {}
|
|
548
|
+
}
|
|
577
549
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
550
|
+
}
|
|
551
|
+
function summarizeManifest(manifest) {
|
|
552
|
+
const mv = manifest?.manifest_version === 2 ? 2 : 3;
|
|
553
|
+
const permissions = Array.isArray(manifest?.permissions) ? manifest.permissions : [];
|
|
554
|
+
const optionalPermissions = Array.isArray(manifest?.optional_permissions) ? manifest.optional_permissions : [];
|
|
555
|
+
const hostPermissions = Array.isArray(manifest?.host_permissions) ? manifest.host_permissions : [];
|
|
556
|
+
const usesAllUrls = [
|
|
557
|
+
...permissions,
|
|
558
|
+
...hostPermissions
|
|
559
|
+
].includes('<all_urls>');
|
|
560
|
+
const usesDeclarativeNetRequest = permissions.includes('declarativeNetRequest') || permissions.includes('declarativeNetRequestWithHostAccess');
|
|
561
|
+
const background = manifest?.background;
|
|
562
|
+
let backgroundType = 'none';
|
|
563
|
+
if (3 === mv && background?.service_worker) backgroundType = 'service_worker';
|
|
564
|
+
else if (2 === mv && (Array.isArray(background?.scripts) && background.scripts.length > 0 || background?.page)) backgroundType = 'event_page';
|
|
565
|
+
const contentScriptsCount = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts.length : 0;
|
|
566
|
+
const hasDevtoolsPage = Boolean(manifest?.devtools_page);
|
|
567
|
+
const hasActionPopup = Boolean(manifest?.action?.default_popup);
|
|
568
|
+
return {
|
|
569
|
+
mv,
|
|
570
|
+
permissions_count: permissions.length,
|
|
571
|
+
optional_permissions_count: optionalPermissions.length,
|
|
572
|
+
host_permissions_count: hostPermissions.length,
|
|
573
|
+
uses_all_urls: usesAllUrls,
|
|
574
|
+
uses_declarative_net_request: usesDeclarativeNetRequest,
|
|
575
|
+
background_type: backgroundType,
|
|
576
|
+
content_scripts_count: contentScriptsCount,
|
|
577
|
+
has_devtools_page: hasDevtoolsPage,
|
|
578
|
+
has_action_popup: hasActionPopup
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function isTelemetryDisabledFromArgs(argv) {
|
|
582
|
+
return argv.includes('--no-telemetry');
|
|
583
|
+
}
|
|
584
|
+
const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
|
|
585
|
+
function findManifestJson(projectRoot) {
|
|
586
|
+
const stack = [
|
|
587
|
+
projectRoot
|
|
588
|
+
];
|
|
589
|
+
while(stack.length > 0){
|
|
590
|
+
const dir = stack.pop();
|
|
591
|
+
if (!dir) continue;
|
|
592
|
+
let entries;
|
|
593
|
+
try {
|
|
594
|
+
entries = external_fs_default().readdirSync(dir, {
|
|
595
|
+
withFileTypes: true
|
|
596
|
+
});
|
|
597
|
+
} catch {
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
for (const entry of entries){
|
|
601
|
+
if (entry.isFile() && 'manifest.json' === entry.name) return external_path_default().join(dir, entry.name);
|
|
602
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && 'node_modules' !== entry.name && 'dist' !== entry.name) stack.push(external_path_default().join(dir, entry.name));
|
|
603
|
+
}
|
|
581
604
|
}
|
|
605
|
+
return null;
|
|
582
606
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
version: getCliPackageJson().version,
|
|
588
|
-
disabled: telemetryDisabled
|
|
589
|
-
});
|
|
590
|
-
if (!telemetryDisabled) {
|
|
591
|
-
const startedAt = Date.now();
|
|
592
|
-
const known = new Set([
|
|
593
|
-
'create',
|
|
594
|
-
'dev',
|
|
595
|
-
'start',
|
|
596
|
-
'preview',
|
|
597
|
-
'build',
|
|
598
|
-
'cleanup'
|
|
599
|
-
]);
|
|
600
|
-
const invoked = process.argv.slice(2).find((a)=>known.has(a)) || 'unknown';
|
|
601
|
-
telemetry_cli_telemetry.track('cli_boot', {
|
|
602
|
-
command_guess: invoked
|
|
603
|
-
});
|
|
604
|
-
const manifestPath = findManifestJson(process.cwd());
|
|
605
|
-
if (manifestPath) {
|
|
606
|
-
const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
|
|
607
|
-
const json = JSON.parse(raw);
|
|
608
|
-
const summary = summarizeManifest(json);
|
|
609
|
-
telemetry_cli_telemetry.track('manifest_summary', summary);
|
|
610
|
-
}
|
|
611
|
-
process.on('beforeExit', async function() {
|
|
612
|
-
telemetry_cli_telemetry.track('cli_shutdown', {
|
|
613
|
-
command_guess: invoked,
|
|
614
|
-
duration_ms: Date.now() - startedAt,
|
|
615
|
-
exit_code: process.exitCode ?? 0
|
|
616
|
-
});
|
|
617
|
-
await telemetry_cli_telemetry.flush();
|
|
618
|
-
});
|
|
619
|
-
process.on('uncaughtException', function(err) {
|
|
620
|
-
telemetry_cli_telemetry.track('cli_error', {
|
|
621
|
-
command_guess: invoked,
|
|
622
|
-
error_name: String(err?.name || 'Error').slice(0, 64)
|
|
623
|
-
});
|
|
607
|
+
const telemetry_cli_telemetry = new Telemetry({
|
|
608
|
+
app: 'extension',
|
|
609
|
+
version: getCliPackageJson().version,
|
|
610
|
+
disabled: telemetryDisabled
|
|
624
611
|
});
|
|
625
|
-
|
|
626
|
-
telemetry_cli_telemetry.track('cli_error', {
|
|
627
|
-
command_guess: invoked,
|
|
628
|
-
error_name: String(reason?.name || 'PromiseRejection').slice(0, 64)
|
|
629
|
-
});
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
require("node:url");
|
|
633
|
-
function parseOptionalBoolean(value) {
|
|
634
|
-
if (void 0 === value) return true;
|
|
635
|
-
const normalized = String(value).trim().toLowerCase();
|
|
636
|
-
return ![
|
|
637
|
-
'false',
|
|
638
|
-
'0',
|
|
639
|
-
'no',
|
|
640
|
-
'off'
|
|
641
|
-
].includes(normalized);
|
|
642
|
-
}
|
|
643
|
-
const vendors = (browser)=>{
|
|
644
|
-
const value = browser ?? 'chromium';
|
|
645
|
-
return 'all' === value ? [
|
|
646
|
-
'chrome',
|
|
647
|
-
'edge',
|
|
648
|
-
'firefox'
|
|
649
|
-
] : String(value).split(',');
|
|
650
|
-
};
|
|
651
|
-
function validateVendorsOrExit(vendorsList, onInvalid) {
|
|
652
|
-
const supported = [
|
|
653
|
-
'chrome',
|
|
654
|
-
'edge',
|
|
655
|
-
'firefox',
|
|
656
|
-
'chromium',
|
|
657
|
-
'chromium-based',
|
|
658
|
-
'gecko-based',
|
|
659
|
-
'firefox-based'
|
|
660
|
-
];
|
|
661
|
-
for (const v of vendorsList)if (!supported.includes(v)) {
|
|
662
|
-
onInvalid(v, supported);
|
|
663
|
-
process.exit(1);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
function registerCreateCommand(program, telemetry) {
|
|
667
|
-
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 }) {
|
|
612
|
+
if (!telemetryDisabled) {
|
|
668
613
|
const startedAt = Date.now();
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
614
|
+
const known = new Set([
|
|
615
|
+
'create',
|
|
616
|
+
'dev',
|
|
617
|
+
'start',
|
|
618
|
+
'preview',
|
|
619
|
+
'build',
|
|
620
|
+
'cleanup'
|
|
621
|
+
]);
|
|
622
|
+
const invoked = process.argv.slice(2).find((a)=>known.has(a)) || 'unknown';
|
|
623
|
+
telemetry_cli_telemetry.track('cli_boot', {
|
|
624
|
+
command_guess: invoked
|
|
673
625
|
});
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
const
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
skipProjectInstall: true,
|
|
685
|
-
showRunAgainMessage: false
|
|
686
|
-
});
|
|
687
|
-
telemetry.track('cli_command_finish', {
|
|
688
|
-
command: 'create',
|
|
626
|
+
const manifestPath = findManifestJson(process.cwd());
|
|
627
|
+
if (manifestPath) {
|
|
628
|
+
const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
|
|
629
|
+
const json = JSON.parse(raw);
|
|
630
|
+
const summary = summarizeManifest(json);
|
|
631
|
+
telemetry_cli_telemetry.track('manifest_summary', summary);
|
|
632
|
+
}
|
|
633
|
+
process.on('beforeExit', async function() {
|
|
634
|
+
telemetry_cli_telemetry.track('cli_shutdown', {
|
|
635
|
+
command_guess: invoked,
|
|
689
636
|
duration_ms: Date.now() - startedAt,
|
|
690
|
-
|
|
691
|
-
exit_code: 0
|
|
637
|
+
exit_code: process.exitCode ?? 0
|
|
692
638
|
});
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
639
|
+
await telemetry_cli_telemetry.flush();
|
|
640
|
+
});
|
|
641
|
+
process.on('uncaughtException', function(err) {
|
|
642
|
+
telemetry_cli_telemetry.track('cli_error', {
|
|
643
|
+
command_guess: invoked,
|
|
644
|
+
error_name: String(err?.name || 'Error').slice(0, 64)
|
|
699
645
|
});
|
|
700
|
-
throw err;
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
function normalizeSourceOption(source, startingUrl) {
|
|
705
|
-
if (!source) return;
|
|
706
|
-
const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
|
|
707
|
-
const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
|
|
708
|
-
if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
|
|
709
|
-
return String(source);
|
|
710
|
-
}
|
|
711
|
-
function parseLogContexts(raw) {
|
|
712
|
-
if (!raw || 0 === String(raw).trim().length) return;
|
|
713
|
-
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
714
|
-
const allowed = [
|
|
715
|
-
'background',
|
|
716
|
-
'content',
|
|
717
|
-
'page',
|
|
718
|
-
'sidebar',
|
|
719
|
-
'popup',
|
|
720
|
-
'options',
|
|
721
|
-
'devtools'
|
|
722
|
-
];
|
|
723
|
-
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
724
|
-
return values.length > 0 ? values : void 0;
|
|
725
|
-
}
|
|
726
|
-
function registerDevCommand(program, telemetry) {
|
|
727
|
-
program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(commandDescriptions.dev).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('--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>', '[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('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
|
|
728
|
-
if (devOptions.author || devOptions['authorMode']) {
|
|
729
|
-
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
730
|
-
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
731
|
-
}
|
|
732
|
-
const cmdStart = Date.now();
|
|
733
|
-
telemetry.track('cli_command_start', {
|
|
734
|
-
command: 'dev',
|
|
735
|
-
vendors: vendors(browser),
|
|
736
|
-
polyfill_used: devOptions.polyfill?.toString() !== 'false',
|
|
737
|
-
log_level: devOptions.logLevel || 'off',
|
|
738
|
-
log_format: devOptions.logFormat || 'pretty',
|
|
739
|
-
custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary)
|
|
740
646
|
});
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
647
|
+
process.on('unhandledRejection', function(reason) {
|
|
648
|
+
telemetry_cli_telemetry.track('cli_error', {
|
|
649
|
+
command_guess: invoked,
|
|
650
|
+
error_name: String(reason?.name || 'PromiseRejection').slice(0, 64)
|
|
651
|
+
});
|
|
744
652
|
});
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
653
|
+
}
|
|
654
|
+
require("node:url");
|
|
655
|
+
function parseOptionalBoolean(value) {
|
|
656
|
+
if (void 0 === value) return true;
|
|
657
|
+
const normalized = String(value).trim().toLowerCase();
|
|
658
|
+
return ![
|
|
659
|
+
'false',
|
|
660
|
+
'0',
|
|
661
|
+
'no',
|
|
662
|
+
'off'
|
|
663
|
+
].includes(normalized);
|
|
664
|
+
}
|
|
665
|
+
const vendors = (browser)=>{
|
|
666
|
+
const value = browser ?? 'chromium';
|
|
667
|
+
return 'all' === value ? [
|
|
668
|
+
'chrome',
|
|
669
|
+
'edge',
|
|
670
|
+
'firefox'
|
|
671
|
+
] : String(value).split(',');
|
|
672
|
+
};
|
|
673
|
+
function validateVendorsOrExit(vendorsList, onInvalid) {
|
|
674
|
+
const supported = [
|
|
675
|
+
'chrome',
|
|
676
|
+
'edge',
|
|
677
|
+
'firefox',
|
|
678
|
+
'chromium',
|
|
679
|
+
'chromium-based',
|
|
680
|
+
'gecko-based',
|
|
681
|
+
'firefox-based'
|
|
682
|
+
];
|
|
683
|
+
for (const v of vendorsList)if (!supported.includes(v)) {
|
|
684
|
+
onInvalid(v, supported);
|
|
685
|
+
process.exit(1);
|
|
749
686
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
687
|
+
}
|
|
688
|
+
function registerCreateCommand(program, telemetry) {
|
|
689
|
+
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 }) {
|
|
690
|
+
const startedAt = Date.now();
|
|
691
|
+
telemetry.track('cli_command_start', {
|
|
692
|
+
command: 'create',
|
|
693
|
+
template: template || 'default',
|
|
694
|
+
install: Boolean(install)
|
|
695
|
+
});
|
|
696
|
+
try {
|
|
697
|
+
const { extensionCreate } = await import("extension-create");
|
|
698
|
+
external_path_namespaceObject.isAbsolute(pathOrRemoteUrl) || external_path_namespaceObject.join(process.cwd(), pathOrRemoteUrl);
|
|
699
|
+
await extensionCreate(pathOrRemoteUrl, {
|
|
700
|
+
template,
|
|
701
|
+
install,
|
|
702
|
+
cliVersion: getCliPackageJson().version
|
|
703
|
+
});
|
|
704
|
+
telemetry.track('cli_command_finish', {
|
|
705
|
+
command: 'create',
|
|
706
|
+
duration_ms: Date.now() - startedAt,
|
|
707
|
+
success: true,
|
|
708
|
+
exit_code: 0
|
|
709
|
+
});
|
|
710
|
+
} catch (err) {
|
|
711
|
+
telemetry.track('cli_command_finish', {
|
|
712
|
+
command: 'create',
|
|
713
|
+
duration_ms: Date.now() - startedAt,
|
|
714
|
+
success: false,
|
|
715
|
+
exit_code: 1
|
|
716
|
+
});
|
|
717
|
+
throw err;
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
function normalizeSourceOption(source, startingUrl) {
|
|
722
|
+
if (!source) return;
|
|
723
|
+
const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
|
|
724
|
+
const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
|
|
725
|
+
if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
|
|
726
|
+
return String(source);
|
|
727
|
+
}
|
|
728
|
+
function parseLogContexts(raw) {
|
|
729
|
+
if (!raw || 0 === String(raw).trim().length) return;
|
|
730
|
+
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
731
|
+
const allowed = [
|
|
732
|
+
'background',
|
|
733
|
+
'content',
|
|
734
|
+
'page',
|
|
735
|
+
'sidebar',
|
|
736
|
+
'popup',
|
|
737
|
+
'options',
|
|
738
|
+
'devtools'
|
|
739
|
+
];
|
|
740
|
+
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
741
|
+
return values.length > 0 ? values : void 0;
|
|
742
|
+
}
|
|
743
|
+
function registerDevCommand(program, telemetry) {
|
|
744
|
+
program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(commandDescriptions.dev).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('--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>', '[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('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
|
|
745
|
+
if (devOptions.author || devOptions['authorMode']) {
|
|
746
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
747
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
748
|
+
}
|
|
749
|
+
const cmdStart = Date.now();
|
|
750
|
+
telemetry.track('cli_command_start', {
|
|
754
751
|
command: 'dev',
|
|
755
|
-
|
|
752
|
+
vendors: vendors(browser),
|
|
753
|
+
polyfill_used: devOptions.polyfill?.toString() !== 'false',
|
|
754
|
+
log_level: devOptions.logLevel || 'off',
|
|
755
|
+
log_format: devOptions.logFormat || 'pretty',
|
|
756
|
+
custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary)
|
|
756
757
|
});
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
758
|
+
const list = vendors(browser);
|
|
759
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
760
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
761
|
+
});
|
|
762
|
+
const normalizedSource = normalizeSourceOption(devOptions.source, devOptions.startingUrl);
|
|
763
|
+
if (normalizedSource) {
|
|
764
|
+
devOptions.source = normalizedSource;
|
|
765
|
+
devOptions.watchSource = true;
|
|
766
|
+
}
|
|
767
|
+
const { extensionDev } = await import("extension-develop");
|
|
768
|
+
for (const vendor of list){
|
|
769
|
+
const vendorStart = Date.now();
|
|
770
|
+
telemetry.track('cli_vendor_start', {
|
|
771
|
+
command: 'dev',
|
|
772
|
+
vendor
|
|
773
|
+
});
|
|
774
|
+
const logsOption = devOptions.logs;
|
|
775
|
+
const logContextOption = devOptions.logContext;
|
|
776
|
+
const devArgs = {
|
|
777
|
+
...devOptions,
|
|
778
|
+
profile: devOptions.profile,
|
|
779
|
+
browser: vendor,
|
|
780
|
+
chromiumBinary: devOptions.chromiumBinary,
|
|
781
|
+
geckoBinary: devOptions.geckoBinary,
|
|
782
|
+
polyfill: devOptions.polyfill?.toString() !== 'false',
|
|
783
|
+
open: devOptions.open,
|
|
784
|
+
startingUrl: devOptions.startingUrl,
|
|
785
|
+
source: devOptions.source,
|
|
786
|
+
watchSource: devOptions.watchSource,
|
|
787
|
+
install: devOptions.install,
|
|
788
|
+
logLevel: logsOption || devOptions.logLevel || 'off',
|
|
789
|
+
logContexts: parseLogContexts(logContextOption),
|
|
790
|
+
logFormat: devOptions.logFormat || 'pretty',
|
|
791
|
+
logTimestamps: false !== devOptions.logTimestamps,
|
|
792
|
+
logColor: false !== devOptions.logColor,
|
|
793
|
+
logUrl: devOptions.logUrl,
|
|
794
|
+
logTab: devOptions.logTab
|
|
795
|
+
};
|
|
796
|
+
await extensionDev(pathOrRemoteUrl, devArgs);
|
|
797
|
+
telemetry.track('cli_vendor_finish', {
|
|
798
|
+
command: 'dev',
|
|
799
|
+
vendor,
|
|
800
|
+
duration_ms: Date.now() - vendorStart
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
telemetry.track('cli_command_finish', {
|
|
781
804
|
command: 'dev',
|
|
782
|
-
|
|
783
|
-
|
|
805
|
+
duration_ms: Date.now() - cmdStart,
|
|
806
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
807
|
+
exit_code: process.exitCode ?? 0
|
|
784
808
|
});
|
|
785
|
-
}
|
|
786
|
-
telemetry.track('cli_command_finish', {
|
|
787
|
-
command: 'dev',
|
|
788
|
-
duration_ms: Date.now() - cmdStart,
|
|
789
|
-
success: 0 === process.exitCode || null == process.exitCode,
|
|
790
|
-
exit_code: process.exitCode ?? 0
|
|
791
809
|
});
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
telemetry.track('cli_command_start', {
|
|
802
|
-
command: 'start',
|
|
803
|
-
vendors: vendors(browser),
|
|
804
|
-
polyfill_used: startOptions.polyfill?.toString() !== 'false'
|
|
805
|
-
});
|
|
806
|
-
const list = vendors(browser);
|
|
807
|
-
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
808
|
-
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
809
|
-
});
|
|
810
|
-
const { extensionStart } = await import("extension-develop");
|
|
811
|
-
for (const vendor of list){
|
|
812
|
-
const vendorStart = Date.now();
|
|
813
|
-
telemetry.track('cli_vendor_start', {
|
|
810
|
+
}
|
|
811
|
+
function registerStartCommand(program, telemetry) {
|
|
812
|
+
program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description(commandDescriptions.start).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>', '[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('--install [boolean]', '[experimental] install project dependencies when missing', parseOptionalBoolean).option('--author, --author-mode', '[experimental] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
|
|
813
|
+
if (startOptions.author || startOptions.authorMode) {
|
|
814
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
815
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
816
|
+
}
|
|
817
|
+
const cmdStart = Date.now();
|
|
818
|
+
telemetry.track('cli_command_start', {
|
|
814
819
|
command: 'start',
|
|
815
|
-
|
|
820
|
+
vendors: vendors(browser),
|
|
821
|
+
polyfill_used: startOptions.polyfill?.toString() !== 'false'
|
|
816
822
|
});
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
await extensionStart(pathOrRemoteUrl, {
|
|
821
|
-
mode: 'production',
|
|
822
|
-
profile: startOptions.profile,
|
|
823
|
-
browser: vendor,
|
|
824
|
-
chromiumBinary: startOptions.chromiumBinary,
|
|
825
|
-
geckoBinary: startOptions.geckoBinary,
|
|
826
|
-
startingUrl: startOptions.startingUrl,
|
|
827
|
-
port: startOptions.port,
|
|
828
|
-
install: startOptions.install,
|
|
829
|
-
source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
|
|
830
|
-
watchSource: startOptions.watchSource,
|
|
831
|
-
logLevel: logsOption || startOptions.logLevel || 'off',
|
|
832
|
-
logContexts,
|
|
833
|
-
logFormat: startOptions.logFormat || 'pretty',
|
|
834
|
-
logTimestamps: false !== startOptions.logTimestamps,
|
|
835
|
-
logColor: false !== startOptions.logColor,
|
|
836
|
-
logUrl: startOptions.logUrl,
|
|
837
|
-
logTab: startOptions.logTab
|
|
823
|
+
const list = vendors(browser);
|
|
824
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
825
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
838
826
|
});
|
|
839
|
-
|
|
827
|
+
const { extensionStart } = await import("extension-develop");
|
|
828
|
+
for (const vendor of list){
|
|
829
|
+
const vendorStart = Date.now();
|
|
830
|
+
telemetry.track('cli_vendor_start', {
|
|
831
|
+
command: 'start',
|
|
832
|
+
vendor
|
|
833
|
+
});
|
|
834
|
+
const logsOption = startOptions.logs;
|
|
835
|
+
const logContextOption = startOptions.logContext;
|
|
836
|
+
const logContexts = parseLogContexts(logContextOption);
|
|
837
|
+
await extensionStart(pathOrRemoteUrl, {
|
|
838
|
+
mode: 'production',
|
|
839
|
+
profile: startOptions.profile,
|
|
840
|
+
browser: vendor,
|
|
841
|
+
chromiumBinary: startOptions.chromiumBinary,
|
|
842
|
+
geckoBinary: startOptions.geckoBinary,
|
|
843
|
+
startingUrl: startOptions.startingUrl,
|
|
844
|
+
port: startOptions.port,
|
|
845
|
+
install: startOptions.install,
|
|
846
|
+
source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
|
|
847
|
+
watchSource: startOptions.watchSource,
|
|
848
|
+
logLevel: logsOption || startOptions.logLevel || 'off',
|
|
849
|
+
logContexts,
|
|
850
|
+
logFormat: startOptions.logFormat || 'pretty',
|
|
851
|
+
logTimestamps: false !== startOptions.logTimestamps,
|
|
852
|
+
logColor: false !== startOptions.logColor,
|
|
853
|
+
logUrl: startOptions.logUrl,
|
|
854
|
+
logTab: startOptions.logTab
|
|
855
|
+
});
|
|
856
|
+
telemetry.track('cli_vendor_finish', {
|
|
857
|
+
command: 'start',
|
|
858
|
+
vendor,
|
|
859
|
+
duration_ms: Date.now() - vendorStart
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
telemetry.track('cli_command_finish', {
|
|
840
863
|
command: 'start',
|
|
841
|
-
|
|
842
|
-
|
|
864
|
+
duration_ms: Date.now() - cmdStart,
|
|
865
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
866
|
+
exit_code: process.exitCode ?? 0
|
|
843
867
|
});
|
|
844
|
-
}
|
|
845
|
-
telemetry.track('cli_command_finish', {
|
|
846
|
-
command: 'start',
|
|
847
|
-
duration_ms: Date.now() - cmdStart,
|
|
848
|
-
success: 0 === process.exitCode || null == process.exitCode,
|
|
849
|
-
exit_code: process.exitCode ?? 0
|
|
850
|
-
});
|
|
851
|
-
});
|
|
852
|
-
}
|
|
853
|
-
function registerPreviewCommand(program, telemetry) {
|
|
854
|
-
program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(commandDescriptions.preview).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>', '[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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
|
|
855
|
-
if (previewOptions.author || previewOptions['authorMode']) {
|
|
856
|
-
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
857
|
-
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
858
|
-
}
|
|
859
|
-
const cmdStart = Date.now();
|
|
860
|
-
telemetry.track('cli_command_start', {
|
|
861
|
-
command: 'preview',
|
|
862
|
-
vendors: vendors(browser)
|
|
863
|
-
});
|
|
864
|
-
const list = vendors(browser);
|
|
865
|
-
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
866
|
-
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
867
868
|
});
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
869
|
+
}
|
|
870
|
+
function registerPreviewCommand(program, telemetry) {
|
|
871
|
+
program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(commandDescriptions.preview).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>', '[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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
|
|
872
|
+
if (previewOptions.author || previewOptions['authorMode']) {
|
|
873
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
874
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
875
|
+
}
|
|
876
|
+
const cmdStart = Date.now();
|
|
877
|
+
telemetry.track('cli_command_start', {
|
|
876
878
|
command: 'preview',
|
|
877
|
-
|
|
879
|
+
vendors: vendors(browser)
|
|
878
880
|
});
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
await extensionPreview(pathOrRemoteUrl, {
|
|
883
|
-
mode: 'production',
|
|
884
|
-
profile: previewOptions.profile,
|
|
885
|
-
browser: vendor,
|
|
886
|
-
chromiumBinary: previewOptions.chromiumBinary,
|
|
887
|
-
geckoBinary: previewOptions.geckoBinary,
|
|
888
|
-
startingUrl: previewOptions.startingUrl,
|
|
889
|
-
port: previewOptions.port,
|
|
890
|
-
source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
|
|
891
|
-
watchSource: previewOptions.watchSource,
|
|
892
|
-
logLevel: logsOption || previewOptions.logLevel || 'off',
|
|
893
|
-
logContexts,
|
|
894
|
-
logFormat: previewOptions.logFormat || 'pretty',
|
|
895
|
-
logTimestamps: false !== previewOptions.logTimestamps,
|
|
896
|
-
logColor: false !== previewOptions.logColor,
|
|
897
|
-
logUrl: previewOptions.logUrl,
|
|
898
|
-
logTab: previewOptions.logTab
|
|
881
|
+
const list = vendors(browser);
|
|
882
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
883
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
899
884
|
});
|
|
900
|
-
|
|
885
|
+
if (!process.env.EXTJS_LIGHT) {
|
|
886
|
+
const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
|
|
887
|
+
if (isRemote) process.env.EXTJS_LIGHT = '1';
|
|
888
|
+
}
|
|
889
|
+
const { extensionPreview } = await import("extension-develop");
|
|
890
|
+
for (const vendor of list){
|
|
891
|
+
const vendorStart = Date.now();
|
|
892
|
+
telemetry.track('cli_vendor_start', {
|
|
893
|
+
command: 'preview',
|
|
894
|
+
vendor
|
|
895
|
+
});
|
|
896
|
+
const logsOption = previewOptions.logs;
|
|
897
|
+
const logContextOption = previewOptions.logContext;
|
|
898
|
+
const logContexts = parseLogContexts(logContextOption);
|
|
899
|
+
await extensionPreview(pathOrRemoteUrl, {
|
|
900
|
+
mode: 'production',
|
|
901
|
+
profile: previewOptions.profile,
|
|
902
|
+
browser: vendor,
|
|
903
|
+
chromiumBinary: previewOptions.chromiumBinary,
|
|
904
|
+
geckoBinary: previewOptions.geckoBinary,
|
|
905
|
+
startingUrl: previewOptions.startingUrl,
|
|
906
|
+
port: previewOptions.port,
|
|
907
|
+
source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
|
|
908
|
+
watchSource: previewOptions.watchSource,
|
|
909
|
+
logLevel: logsOption || previewOptions.logLevel || 'off',
|
|
910
|
+
logContexts,
|
|
911
|
+
logFormat: previewOptions.logFormat || 'pretty',
|
|
912
|
+
logTimestamps: false !== previewOptions.logTimestamps,
|
|
913
|
+
logColor: false !== previewOptions.logColor,
|
|
914
|
+
logUrl: previewOptions.logUrl,
|
|
915
|
+
logTab: previewOptions.logTab
|
|
916
|
+
});
|
|
917
|
+
telemetry.track('cli_vendor_finish', {
|
|
918
|
+
command: 'preview',
|
|
919
|
+
vendor,
|
|
920
|
+
duration_ms: Date.now() - vendorStart
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
telemetry.track('cli_command_finish', {
|
|
901
924
|
command: 'preview',
|
|
902
|
-
|
|
903
|
-
|
|
925
|
+
duration_ms: Date.now() - cmdStart,
|
|
926
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
927
|
+
exit_code: process.exitCode ?? 0
|
|
904
928
|
});
|
|
905
|
-
}
|
|
906
|
-
telemetry.track('cli_command_finish', {
|
|
907
|
-
command: 'preview',
|
|
908
|
-
duration_ms: Date.now() - cmdStart,
|
|
909
|
-
success: 0 === process.exitCode || null == process.exitCode,
|
|
910
|
-
exit_code: process.exitCode ?? 0
|
|
911
|
-
});
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
function registerBuildCommand(program, telemetry) {
|
|
915
|
-
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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
|
|
916
|
-
if (buildOptions.author || buildOptions['authorMode']) {
|
|
917
|
-
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
918
|
-
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
919
|
-
}
|
|
920
|
-
const cmdStart = Date.now();
|
|
921
|
-
telemetry.track('cli_command_start', {
|
|
922
|
-
command: 'build',
|
|
923
|
-
vendors: vendors(browser),
|
|
924
|
-
polyfill_used: buildOptions.polyfill || false,
|
|
925
|
-
zip: buildOptions.zip || false,
|
|
926
|
-
zip_source: buildOptions.zipSource || false
|
|
927
|
-
});
|
|
928
|
-
const list = vendors(browser);
|
|
929
|
-
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
930
|
-
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
931
929
|
});
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
930
|
+
}
|
|
931
|
+
function registerBuildCommand(program, telemetry) {
|
|
932
|
+
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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
|
|
933
|
+
if (buildOptions.author || buildOptions['authorMode']) {
|
|
934
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
935
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
936
|
+
}
|
|
937
|
+
const cmdStart = Date.now();
|
|
938
|
+
telemetry.track('cli_command_start', {
|
|
936
939
|
command: 'build',
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
polyfill: buildOptions.polyfill,
|
|
942
|
-
zip: buildOptions.zip,
|
|
943
|
-
zipSource: buildOptions.zipSource,
|
|
944
|
-
zipFilename: buildOptions.zipFilename,
|
|
945
|
-
silent: buildOptions.silent,
|
|
946
|
-
install: buildOptions.install
|
|
940
|
+
vendors: vendors(browser),
|
|
941
|
+
polyfill_used: buildOptions.polyfill || false,
|
|
942
|
+
zip: buildOptions.zip || false,
|
|
943
|
+
zip_source: buildOptions.zipSource || false
|
|
947
944
|
});
|
|
948
|
-
|
|
949
|
-
|
|
945
|
+
const list = vendors(browser);
|
|
946
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
947
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
950
948
|
});
|
|
951
|
-
|
|
949
|
+
const { extensionBuild } = await import("extension-develop");
|
|
950
|
+
for (const vendor of list){
|
|
951
|
+
const vendorStart = Date.now();
|
|
952
|
+
telemetry.track('cli_vendor_start', {
|
|
953
|
+
command: 'build',
|
|
954
|
+
vendor
|
|
955
|
+
});
|
|
956
|
+
const buildSummary = await extensionBuild(pathOrRemoteUrl, {
|
|
957
|
+
browser: vendor,
|
|
958
|
+
polyfill: buildOptions.polyfill,
|
|
959
|
+
zip: buildOptions.zip,
|
|
960
|
+
zipSource: buildOptions.zipSource,
|
|
961
|
+
zipFilename: buildOptions.zipFilename,
|
|
962
|
+
silent: buildOptions.silent,
|
|
963
|
+
install: buildOptions.install
|
|
964
|
+
});
|
|
965
|
+
telemetry.track('cli_build_summary', {
|
|
966
|
+
...buildSummary
|
|
967
|
+
});
|
|
968
|
+
telemetry.track('cli_vendor_finish', {
|
|
969
|
+
command: 'build',
|
|
970
|
+
vendor,
|
|
971
|
+
duration_ms: Date.now() - vendorStart
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
telemetry.track('cli_command_finish', {
|
|
952
975
|
command: 'build',
|
|
953
|
-
|
|
954
|
-
|
|
976
|
+
duration_ms: Date.now() - cmdStart,
|
|
977
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
978
|
+
exit_code: process.exitCode ?? 0
|
|
955
979
|
});
|
|
956
|
-
}
|
|
957
|
-
telemetry.track('cli_command_finish', {
|
|
958
|
-
command: 'build',
|
|
959
|
-
duration_ms: Date.now() - cmdStart,
|
|
960
|
-
success: 0 === process.exitCode || null == process.exitCode,
|
|
961
|
-
exit_code: process.exitCode ?? 0
|
|
962
980
|
});
|
|
981
|
+
}
|
|
982
|
+
const cliPackageJson = getCliPackageJson();
|
|
983
|
+
function developVersion() {
|
|
984
|
+
try {
|
|
985
|
+
const pkg = __webpack_require__("extension-develop/package.json");
|
|
986
|
+
return pkg?.version || cliPackageJson.version;
|
|
987
|
+
} catch {
|
|
988
|
+
return cliPackageJson.version;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
process.env.EXTENSION_DEVELOP_VERSION = developVersion();
|
|
992
|
+
check_updates_checkUpdates().then((updateMessage)=>{
|
|
993
|
+
if (!updateMessage) return;
|
|
994
|
+
if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) return void console.log(updateMessage.message);
|
|
995
|
+
process.env.EXTENSION_CLI_UPDATE_SUFFIX = updateMessage.suffix;
|
|
963
996
|
});
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
extensionJs.
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
});
|
|
983
|
-
|
|
984
|
-
extensionJs.outputHelp();
|
|
985
|
-
process.exit(0);
|
|
986
|
-
}
|
|
987
|
-
extensionJs.parseAsync().catch((err)=>{
|
|
988
|
-
console.error(unhandledError(err));
|
|
989
|
-
process.exit(1);
|
|
990
|
-
});
|
|
997
|
+
const extensionJs = external_commander_namespaceObject.program;
|
|
998
|
+
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').addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true);
|
|
999
|
+
registerCreateCommand(extensionJs, telemetry_cli_telemetry);
|
|
1000
|
+
registerDevCommand(extensionJs, telemetry_cli_telemetry);
|
|
1001
|
+
registerStartCommand(extensionJs, telemetry_cli_telemetry);
|
|
1002
|
+
registerPreviewCommand(extensionJs, telemetry_cli_telemetry);
|
|
1003
|
+
registerBuildCommand(extensionJs, telemetry_cli_telemetry);
|
|
1004
|
+
extensionJs.on('option:ai-help', function() {
|
|
1005
|
+
console.log(programAIHelp());
|
|
1006
|
+
process.exit(0);
|
|
1007
|
+
});
|
|
1008
|
+
if (process.argv.length <= 2) {
|
|
1009
|
+
extensionJs.outputHelp();
|
|
1010
|
+
process.exit(0);
|
|
1011
|
+
}
|
|
1012
|
+
extensionJs.parseAsync().catch((err)=>{
|
|
1013
|
+
console.error(unhandledError(err));
|
|
1014
|
+
process.exit(1);
|
|
1015
|
+
});
|
|
1016
|
+
})();
|
|
991
1017
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
992
1018
|
Object.defineProperty(exports, '__esModule', {
|
|
993
1019
|
value: true
|