extension 3.1.0-next.8 → 3.2.0-next.10

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.js CHANGED
@@ -1,6 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __webpack_require__ = {};
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,67 +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
- const external_commander_namespaceObject = require("commander");
26
- var package_namespaceObject = JSON.parse('{"license":"MIT","repository":{"type":"git","url":"git+https://github.com/extension-js/extension.js.git","directory":"programs/cli"},"engines":{"node":">=18"},"exports":{".":{"types":"./dist/cli.d.ts","import":"./dist/cli.js","require":"./dist/cli.js"}},"main":"./dist/cli.js","types":"./dist/cli.d.ts","typesVersions":{"*":{"types":["./types/index.d.ts"],"types/*":["./types/*"]}},"files":["dist","types"],"bin":{"extension":"./dist/cli.js"},"name":"extension","version":"3.1.0-next.8","description":"Create cross-browser extensions with no build configuration.","homepage":"https://extension.js.org/","bugs":{"url":"https://github.com/extension-js/extension.js/issues"},"author":{"name":"Cezar Augusto","email":"boss@cezaraugusto.net","url":"https://cezaraugusto.com"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"scripts":{"prepublishOnly":"pnpm run compile","compile":"rslib build","watch":"rslib build --watch","test":"vitest run"},"keywords":["zero-config","build","develop","browser","extension","chrome extension","edge extension","firefox extension","safari extension","web","react","typescript","webextension","browser-extension","chrome-extension","firefox-addon","edge-extension","safari-web-extension","manifest-v3","mv3","cross-browser","content-script","background-script","devtools","create-extension","scaffold","starter-template","boilerplate","cli"],"dependencies":{"extension-create":"^3.1.0-next.8","extension-develop":"^3.1.0-next.8","commander":"^14.0.2","pintor":"0.3.0","semver":"^7.7.3","update-check":"^1.5.4"},"devDependencies":{"@rslib/core":"^0.19.2","@types/chrome":"^0.1.33","@types/node":"^25.0.9","@types/react":"^19.2.8","@types/react-dom":"^19.2.3","@types/webextension-polyfill":"0.12.4","@types/mock-fs":"^4.13.4","@types/semver":"^7.7.1","mock-fs":"^5.5.0","webextension-polyfill":"^0.12.0","tsconfig":"*","typescript":"5.9.3","vitest":"^4.0.17"}}');
27
- const external_update_check_namespaceObject = require("update-check");
28
- var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
29
- const external_pintor_namespaceObject = require("pintor");
30
- var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
31
- function getLoggingPrefix(type) {
32
- const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
33
- if (isAuthor) {
34
- const base = 'error' === type ? 'ERROR Author says' : '►►► Author says';
35
- return external_pintor_default().brightMagenta(base);
36
- }
37
- if ('error' === type) return external_pintor_default().red('ERROR');
38
- if ('warn' === type) return external_pintor_default().brightYellow('►►►');
39
- if ('info' === type) return external_pintor_default().gray('►►►');
40
- return external_pintor_default().green('►►►');
41
- }
42
- const code = (text)=>external_pintor_default().blue(text);
43
- const arg = (text)=>external_pintor_default().gray(text);
44
- const fmt = {
45
- heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
46
- label: (k)=>external_pintor_default().gray(k.toUpperCase()),
47
- val: (v)=>external_pintor_default().underline(v),
48
- code: (v)=>external_pintor_default().blue(v),
49
- bullet: (s)=>`- ${s}`,
50
- block (title, rows) {
51
- const head = fmt.heading(title);
52
- const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
53
- return `${head}\n${body}`;
54
- },
55
- truncate (input, max = 800) {
56
- const s = (()=>{
57
- try {
58
- return 'string' == typeof input ? input : JSON.stringify(input);
59
- } catch {
60
- return String(input);
61
- }
62
- })();
63
- 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('►►►');
64
55
  }
65
- };
66
- const commandDescriptions = {
67
- create: 'Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
68
- dev: 'Starts the development server with hot reloading',
69
- start: 'Builds and starts the extension in production mode',
70
- preview: 'Previews the extension in production mode without building',
71
- build: 'Builds the extension for packaging/distribution',
72
- cleanup: 'Cleans up orphaned instances and frees unused ports'
73
- };
74
- function unhandledError(err) {
75
- const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : fmt.truncate(err);
76
- return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
77
- }
78
- function updateFailed(err) {
79
- return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String(err?.message || err))}`;
80
- }
81
- function checkUpdates(packageJson, update) {
82
- return `${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.`;
83
- }
84
- function programUserHelp() {
85
- return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
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')}
86
105
 
87
106
  Usage: extension [command] [options]
88
107
 
@@ -156,16 +175,16 @@ ${external_pintor_default().underline('Path Resolution (important)')}
156
175
 
157
176
 
158
177
  AI Assistants
159
- - For AI-oriented guidance and deep-dive tips, run ${code('extension --ai-help')}
178
+ - For AI-oriented guidance and deeper tips, run ${code('extension --ai-help')}
160
179
 
161
180
  Report issues
162
181
  - ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
163
- }
164
- function unsupportedBrowserFlag(value, supported) {
165
- return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}. Supported: ${supported.join(', ')}.`;
166
- }
167
- function programAIHelp() {
168
- return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
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')}
169
188
 
170
189
  Browser-Specific Configuration
171
190
  - Use browser prefixes in manifest.json for browser-specific fields:
@@ -271,7 +290,7 @@ Source Inspection & Real-Time Monitoring
271
290
  - Watch mode is enabled by default when ${code('--source')} is present
272
291
  - Automatically enables Chrome remote debugging (port 9222) when source inspection is active
273
292
  - Extracts Shadow DOM content from ${code('#extension-root')} or ${code('[data-extension-root=\"true\"]')} elements
274
- - Perfect for debugging content script behavior and style injection
293
+ - Useful for debugging content script behavior and style injection
275
294
  - Example: ${code('extension dev --source=' + arg('https://example.com'))}
276
295
 
277
296
  Non-Destructive Testing in CI
@@ -298,610 +317,703 @@ Cross-Browser Compatibility
298
317
  - Use ${code('--polyfill')} flag to enable webextension-polyfill
299
318
  - Automatically handles browser API differences
300
319
  - Supports Chrome, Edge, Firefox with single codebase`;
301
- }
302
- const external_semver_namespaceObject = require("semver");
303
- function isStableVersion(version) {
304
- const v = external_semver_namespaceObject.parse(version);
305
- return Boolean(v && 0 === v.prerelease.length);
306
- }
307
- async function check_updates_checkUpdates(packageJson) {
308
- let update = null;
309
- try {
310
- update = await external_update_check_default()(packageJson);
311
- } catch (err) {
312
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(updateFailed(err));
313
- }
314
- if (update && isStableVersion(update.latest)) console.log(checkUpdates(packageJson, update));
315
- }
316
- const external_fs_namespaceObject = require("fs");
317
- var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
318
- const external_path_namespaceObject = require("path");
319
- var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
320
- const external_node_os_namespaceObject = require("node:os");
321
- var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
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
- const external_node_crypto_namespaceObject = require("node:crypto");
327
- var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
328
- function _define_property(obj, key, value) {
329
- if (key in obj) Object.defineProperty(obj, key, {
330
- value: value,
331
- enumerable: true,
332
- configurable: true,
333
- writable: true
334
- });
335
- else obj[key] = value;
336
- return obj;
337
- }
338
- function isCI() {
339
- const v = process.env;
340
- return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
341
- }
342
- function configDir() {
343
- const xdg = process.env.XDG_CONFIG_HOME;
344
- if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
345
- if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
346
- return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
347
- }
348
- function ensureDir(p) {
349
- if (external_node_fs_default().existsSync(p)) return;
350
- external_node_fs_default().mkdirSync(p, {
351
- recursive: true
352
- });
353
- }
354
- function loadOrCreateId(file) {
355
- if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
356
- const id = external_node_crypto_default().randomUUID();
357
- ensureDir(external_node_path_default().dirname(file));
358
- external_node_fs_default().writeFileSync(file, id, 'utf8');
359
- return id;
360
- }
361
- function auditFilePath() {
362
- const dir = external_node_path_default().join(configDir(), 'telemetry');
363
- ensureDir(dir);
364
- return external_node_path_default().join(dir, 'events.jsonl');
365
- }
366
- const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
367
- const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
368
- const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
369
- class Telemetry {
370
- track(event, props = {}) {
371
- if (this.disabled) return;
372
- const payload = {
373
- event,
374
- properties: {
375
- ...this.common,
376
- ...props,
377
- $ip: null
378
- },
379
- distinct_id: this.anonId
380
- };
381
- external_node_fs_default().appendFileSync(auditFilePath(), JSON.stringify(payload) + '\n');
382
- if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
383
- if (!this.apiKey || !this.host) return;
384
- this.buffer.push(payload);
385
- if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
386
- if (!this.timer) this.timer = setTimeout(()=>{
387
- this.timer = null;
388
- this.flush();
389
- }, DEFAULT_FLUSH_INTERVAL);
390
- }
391
- async flush() {
392
- if (this.disabled || !this.apiKey || !this.host) return;
393
- if (0 === this.buffer.length) return;
394
- const batch = this.buffer.splice(0, this.buffer.length);
395
- try {
396
- const ac = new AbortController();
397
- const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
398
- const url = new URL('/capture/', this.host);
399
- await fetch(url.toString(), {
400
- method: 'POST',
401
- headers: {
402
- 'content-type': 'application/json'
403
- },
404
- body: JSON.stringify({
405
- api_key: this.apiKey,
406
- batch: batch.map((e)=>({
407
- event: e.event,
408
- properties: e.properties,
409
- distinct_id: e.distinct_id
410
- }))
411
- }),
412
- signal: ac.signal,
413
- keepalive: true
414
- }).catch(()=>{});
415
- clearTimeout(t);
416
- } catch {}
417
320
  }
418
- shutdown() {}
419
- constructor(init){
420
- _define_property(this, "anonId", void 0);
421
- _define_property(this, "common", void 0);
422
- _define_property(this, "debug", void 0);
423
- _define_property(this, "disabled", void 0);
424
- _define_property(this, "apiKey", void 0);
425
- _define_property(this, "host", void 0);
426
- _define_property(this, "buffer", []);
427
- _define_property(this, "timer", null);
428
- this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
429
- this.disabled = Boolean(init.disabled);
430
- this.anonId = 'disabled';
431
- if (!this.disabled) {
432
- const idFile = external_node_path_default().join(configDir(), 'telemetry', 'anonymous-id');
433
- this.anonId = loadOrCreateId(idFile);
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;
434
338
  }
435
- this.common = {
436
- app: init.app,
437
- version: init.version,
438
- os: process.platform,
439
- arch: process.arch,
440
- node: process.versions.node,
441
- is_ci: isCI(),
442
- schema_version: 1
443
- };
444
- this.apiKey = init.apiKey || process.env.EXTENSION_PUBLIC_POSTHOG_KEY;
445
- this.host = init.host || process.env.EXTENSION_PUBLIC_POSTHOG_HOST;
446
- if (!this.disabled) {
447
- const consentPath = external_node_path_default().join(configDir(), 'telemetry', 'consent');
448
- if (!external_node_fs_default().existsSync(consentPath)) {
449
- external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
450
- this.track('cli_telemetry_consent', {
451
- value: 'implicit_opt_in'
452
- });
453
- console.log(`${external_pintor_default().gray('►►► system')} [extension] anonymous telemetry helps us improve. Pass --no-telemetry to opt out. Read more in TELEMETRY.md.`);
454
- }
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);
455
355
  }
356
+ return null;
456
357
  }
457
- }
458
- function summarizeManifest(manifest) {
459
- const mv = manifest?.manifest_version === 2 ? 2 : 3;
460
- const permissions = Array.isArray(manifest?.permissions) ? manifest.permissions : [];
461
- const optionalPermissions = Array.isArray(manifest?.optional_permissions) ? manifest.optional_permissions : [];
462
- const hostPermissions = Array.isArray(manifest?.host_permissions) ? manifest.host_permissions : [];
463
- const usesAllUrls = [
464
- ...permissions,
465
- ...hostPermissions
466
- ].includes('<all_urls>');
467
- const usesDeclarativeNetRequest = permissions.includes('declarativeNetRequest') || permissions.includes('declarativeNetRequestWithHostAccess');
468
- const background = manifest?.background;
469
- let backgroundType = 'none';
470
- if (3 === mv && background?.service_worker) backgroundType = 'service_worker';
471
- else if (2 === mv && (Array.isArray(background?.scripts) && background.scripts.length > 0 || background?.page)) backgroundType = 'event_page';
472
- const contentScriptsCount = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts.length : 0;
473
- const hasDevtoolsPage = Boolean(manifest?.devtools_page);
474
- const hasActionPopup = Boolean(manifest?.action?.default_popup);
475
- return {
476
- mv,
477
- permissions_count: permissions.length,
478
- optional_permissions_count: optionalPermissions.length,
479
- host_permissions_count: hostPermissions.length,
480
- uses_all_urls: usesAllUrls,
481
- uses_declarative_net_request: usesDeclarativeNetRequest,
482
- background_type: backgroundType,
483
- content_scripts_count: contentScriptsCount,
484
- has_devtools_page: hasDevtoolsPage,
485
- has_action_popup: hasActionPopup
486
- };
487
- }
488
- function isTelemetryDisabledFromArgs(argv) {
489
- return argv.includes('--no-telemetry');
490
- }
491
- const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
492
- function findManifestJson(projectRoot) {
493
- const stack = [
494
- projectRoot
495
- ];
496
- while(stack.length > 0){
497
- const dir = stack.pop();
498
- if (!dir) continue;
499
- let entries;
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
372
+ });
373
+ else obj[key] = value;
374
+ return obj;
375
+ }
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);
379
+ }
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');
385
+ }
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) {
500
397
  try {
501
- entries = external_fs_default().readdirSync(dir, {
502
- withFileTypes: true
398
+ if (external_node_fs_default().existsSync(p)) return true;
399
+ external_node_fs_default().mkdirSync(p, {
400
+ recursive: true
503
401
  });
402
+ return true;
504
403
  } catch {
505
- continue;
404
+ return false;
506
405
  }
507
- for (const entry of entries){
508
- if (entry.isFile() && 'manifest.json' === entry.name) return external_path_default().join(dir, entry.name);
509
- if (entry.isDirectory() && !entry.name.startsWith('.') && 'node_modules' !== entry.name && 'dist' !== entry.name) stack.push(external_path_default().join(dir, entry.name));
406
+ }
407
+ function ensureWritableDir(p) {
408
+ if (!ensureDir(p)) return false;
409
+ try {
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;
510
417
  }
511
418
  }
512
- return null;
513
- }
514
- const telemetry_cli_telemetry = new Telemetry({
515
- app: 'extension',
516
- version: package_namespaceObject.version,
517
- disabled: telemetryDisabled
518
- });
519
- if (!telemetryDisabled) {
520
- const startedAt = Date.now();
521
- const known = new Set([
522
- 'create',
523
- 'dev',
524
- 'start',
525
- 'preview',
526
- 'build',
527
- 'cleanup'
528
- ]);
529
- const invoked = process.argv.slice(2).find((a)=>known.has(a)) || 'unknown';
530
- telemetry_cli_telemetry.track('cli_boot', {
531
- command_guess: invoked
532
- });
533
- const manifestPath = findManifestJson(process.cwd());
534
- if (manifestPath) {
535
- const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
536
- const json = JSON.parse(raw);
537
- const summary = summarizeManifest(json);
538
- telemetry_cli_telemetry.track('manifest_summary', summary);
539
- }
540
- process.on('beforeExit', async function() {
541
- telemetry_cli_telemetry.track('cli_shutdown', {
542
- command_guess: invoked,
543
- duration_ms: Date.now() - startedAt,
544
- exit_code: process.exitCode ?? 0
545
- });
546
- await telemetry_cli_telemetry.flush();
547
- });
548
- process.on('uncaughtException', function(err) {
549
- telemetry_cli_telemetry.track('cli_error', {
550
- command_guess: invoked,
551
- error_name: String(err?.name || 'Error').slice(0, 64)
552
- });
553
- });
554
- process.on('unhandledRejection', function(reason) {
555
- telemetry_cli_telemetry.track('cli_error', {
556
- command_guess: invoked,
557
- error_name: String(reason?.name || 'PromiseRejection').slice(0, 64)
558
- });
559
- });
560
- }
561
- require("node:url");
562
- function parseOptionalBoolean(value) {
563
- if (void 0 === value) return true;
564
- const normalized = String(value).trim().toLowerCase();
565
- return ![
566
- 'false',
567
- '0',
568
- 'no',
569
- 'off'
570
- ].includes(normalized);
571
- }
572
- const vendors = (browser)=>{
573
- const value = browser ?? 'chromium';
574
- return 'all' === value ? [
575
- 'chrome',
576
- 'edge',
577
- 'firefox'
578
- ] : String(value).split(',');
579
- };
580
- function validateVendorsOrExit(vendorsList, onInvalid) {
581
- const supported = [
582
- 'chrome',
583
- 'edge',
584
- 'firefox',
585
- 'chromium',
586
- 'chromium-based',
587
- 'gecko-based',
588
- 'firefox-based'
589
- ];
590
- for (const v of vendorsList)if (!supported.includes(v)) {
591
- onInvalid(v, supported);
592
- process.exit(1);
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');
426
+ } catch {}
427
+ return id;
593
428
  }
594
- }
595
- function registerCreateCommand(program, telemetry) {
596
- 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 (disabled by default)', parseOptionalBoolean, false).action(async function(pathOrRemoteUrl, { template, install }) {
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
+ };
447
+ }
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
+ };
465
+ try {
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);
505
+ } catch {}
506
+ }
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
+ }
549
+ }
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
+ }
604
+ }
605
+ return null;
606
+ }
607
+ const telemetry_cli_telemetry = new Telemetry({
608
+ app: 'extension',
609
+ version: getCliPackageJson().version,
610
+ disabled: telemetryDisabled
611
+ });
612
+ if (!telemetryDisabled) {
597
613
  const startedAt = Date.now();
598
- telemetry.track('cli_command_start', {
599
- command: 'create',
600
- template: template || 'default',
601
- install: Boolean(install)
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
602
625
  });
603
- try {
604
- const { extensionCreate } = await import("extension-create");
605
- await extensionCreate(pathOrRemoteUrl, {
606
- template,
607
- install,
608
- cliVersion: package_namespaceObject.version
609
- });
610
- telemetry.track('cli_command_finish', {
611
- 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,
612
636
  duration_ms: Date.now() - startedAt,
613
- success: true,
614
- exit_code: 0
637
+ exit_code: process.exitCode ?? 0
615
638
  });
616
- } catch (err) {
617
- telemetry.track('cli_command_finish', {
618
- command: 'create',
619
- duration_ms: Date.now() - startedAt,
620
- success: false,
621
- exit_code: 1
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)
622
645
  });
623
- throw err;
624
- }
625
- });
626
- }
627
- function normalizeSourceOption(source, startingUrl) {
628
- if (!source) return;
629
- const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
630
- const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
631
- if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
632
- return String(source);
633
- }
634
- function parseLogContexts(raw) {
635
- if (!raw || 0 === String(raw).trim().length) return;
636
- if ('all' === String(raw).trim().toLowerCase()) return;
637
- const allowed = [
638
- 'background',
639
- 'content',
640
- 'page',
641
- 'sidebar',
642
- 'popup',
643
- 'options',
644
- 'devtools'
645
- ];
646
- const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
647
- return values.length > 0 ? values : void 0;
648
- }
649
- function registerDevCommand(program, telemetry) {
650
- 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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
651
- if (devOptions.author || devOptions['authorMode']) {
652
- process.env.EXTENSION_AUTHOR_MODE = 'true';
653
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
654
- }
655
- const cmdStart = Date.now();
656
- telemetry.track('cli_command_start', {
657
- command: 'dev',
658
- vendors: vendors(browser),
659
- polyfill_used: devOptions.polyfill?.toString() !== 'false',
660
- log_level: devOptions.logLevel || 'off',
661
- log_format: devOptions.logFormat || 'pretty',
662
- custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary)
663
646
  });
664
- const list = vendors(browser);
665
- validateVendorsOrExit(list, (invalid, supported)=>{
666
- console.error(unsupportedBrowserFlag(invalid, supported));
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
+ });
667
652
  });
668
- const normalizedSource = normalizeSourceOption(devOptions.source, devOptions.startingUrl);
669
- if (normalizedSource) {
670
- devOptions.source = normalizedSource;
671
- devOptions.watchSource = true;
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);
672
686
  }
673
- const { extensionDev } = await import("extension-develop");
674
- for (const vendor of list){
675
- const vendorStart = Date.now();
676
- telemetry.track('cli_vendor_start', {
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', {
677
751
  command: 'dev',
678
- vendor
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)
679
757
  });
680
- const logsOption = devOptions.logs;
681
- const logContextOption = devOptions.logContext;
682
- const devArgs = {
683
- ...devOptions,
684
- profile: devOptions.profile,
685
- browser: vendor,
686
- chromiumBinary: devOptions.chromiumBinary,
687
- geckoBinary: devOptions.geckoBinary,
688
- polyfill: devOptions.polyfill?.toString() !== 'false',
689
- open: devOptions.open,
690
- startingUrl: devOptions.startingUrl,
691
- source: devOptions.source,
692
- watchSource: devOptions.watchSource,
693
- logLevel: logsOption || devOptions.logLevel || 'off',
694
- logContexts: parseLogContexts(logContextOption),
695
- logFormat: devOptions.logFormat || 'pretty',
696
- logTimestamps: false !== devOptions.logTimestamps,
697
- logColor: false !== devOptions.logColor,
698
- logUrl: devOptions.logUrl,
699
- logTab: devOptions.logTab
700
- };
701
- await extensionDev(pathOrRemoteUrl, devArgs);
702
- telemetry.track('cli_vendor_finish', {
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', {
703
804
  command: 'dev',
704
- vendor,
705
- duration_ms: Date.now() - vendorStart
805
+ duration_ms: Date.now() - cmdStart,
806
+ success: 0 === process.exitCode || null == process.exitCode,
807
+ exit_code: process.exitCode ?? 0
706
808
  });
707
- }
708
- telemetry.track('cli_command_finish', {
709
- command: 'dev',
710
- duration_ms: Date.now() - cmdStart,
711
- success: 0 === process.exitCode || null == process.exitCode,
712
- exit_code: process.exitCode ?? 0
713
809
  });
714
- });
715
- }
716
- function registerStartCommand(program, telemetry) {
717
- 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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
718
- if (startOptions.author || startOptions.authorMode) {
719
- process.env.EXTENSION_AUTHOR_MODE = 'true';
720
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
721
- }
722
- const cmdStart = Date.now();
723
- telemetry.track('cli_command_start', {
724
- command: 'start',
725
- vendors: vendors(browser),
726
- polyfill_used: startOptions.polyfill?.toString() !== 'false'
727
- });
728
- const list = vendors(browser);
729
- validateVendorsOrExit(list, (invalid, supported)=>{
730
- console.error(unsupportedBrowserFlag(invalid, supported));
731
- });
732
- const { extensionStart } = await import("extension-develop");
733
- for (const vendor of list){
734
- const vendorStart = Date.now();
735
- 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', {
736
819
  command: 'start',
737
- vendor
820
+ vendors: vendors(browser),
821
+ polyfill_used: startOptions.polyfill?.toString() !== 'false'
738
822
  });
739
- const logsOption = startOptions.logs;
740
- const logContextOption = startOptions.logContext;
741
- const logContexts = parseLogContexts(logContextOption);
742
- await extensionStart(pathOrRemoteUrl, {
743
- mode: 'production',
744
- profile: startOptions.profile,
745
- browser: vendor,
746
- chromiumBinary: startOptions.chromiumBinary,
747
- geckoBinary: startOptions.geckoBinary,
748
- startingUrl: startOptions.startingUrl,
749
- port: startOptions.port,
750
- source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
751
- watchSource: startOptions.watchSource,
752
- logLevel: logsOption || startOptions.logLevel || 'off',
753
- logContexts,
754
- logFormat: startOptions.logFormat || 'pretty',
755
- logTimestamps: false !== startOptions.logTimestamps,
756
- logColor: false !== startOptions.logColor,
757
- logUrl: startOptions.logUrl,
758
- logTab: startOptions.logTab
823
+ const list = vendors(browser);
824
+ validateVendorsOrExit(list, (invalid, supported)=>{
825
+ console.error(unsupportedBrowserFlag(invalid, supported));
759
826
  });
760
- telemetry.track('cli_vendor_finish', {
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', {
761
863
  command: 'start',
762
- vendor,
763
- duration_ms: Date.now() - vendorStart
864
+ duration_ms: Date.now() - cmdStart,
865
+ success: 0 === process.exitCode || null == process.exitCode,
866
+ exit_code: process.exitCode ?? 0
764
867
  });
765
- }
766
- telemetry.track('cli_command_finish', {
767
- command: 'start',
768
- duration_ms: Date.now() - cmdStart,
769
- success: 0 === process.exitCode || null == process.exitCode,
770
- exit_code: process.exitCode ?? 0
771
868
  });
772
- });
773
- }
774
- function registerPreviewCommand(program, telemetry) {
775
- 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 }) {
776
- if (previewOptions.author || previewOptions['authorMode']) {
777
- process.env.EXTENSION_AUTHOR_MODE = 'true';
778
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
779
- }
780
- const cmdStart = Date.now();
781
- telemetry.track('cli_command_start', {
782
- command: 'preview',
783
- vendors: vendors(browser)
784
- });
785
- const list = vendors(browser);
786
- validateVendorsOrExit(list, (invalid, supported)=>{
787
- console.error(unsupportedBrowserFlag(invalid, supported));
788
- });
789
- if (!process.env.EXTJS_LIGHT) {
790
- const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
791
- if (isRemote) process.env.EXTJS_LIGHT = '1';
792
- }
793
- const { extensionPreview } = await import("extension-develop");
794
- for (const vendor of list){
795
- const vendorStart = Date.now();
796
- telemetry.track('cli_vendor_start', {
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', {
797
878
  command: 'preview',
798
- vendor
879
+ vendors: vendors(browser)
799
880
  });
800
- const logsOption = previewOptions.logs;
801
- const logContextOption = previewOptions.logContext;
802
- const logContexts = parseLogContexts(logContextOption);
803
- await extensionPreview(pathOrRemoteUrl, {
804
- mode: 'production',
805
- profile: previewOptions.profile,
806
- browser: vendor,
807
- chromiumBinary: previewOptions.chromiumBinary,
808
- geckoBinary: previewOptions.geckoBinary,
809
- startingUrl: previewOptions.startingUrl,
810
- port: previewOptions.port,
811
- source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
812
- watchSource: previewOptions.watchSource,
813
- logLevel: logsOption || previewOptions.logLevel || 'off',
814
- logContexts,
815
- logFormat: previewOptions.logFormat || 'pretty',
816
- logTimestamps: false !== previewOptions.logTimestamps,
817
- logColor: false !== previewOptions.logColor,
818
- logUrl: previewOptions.logUrl,
819
- logTab: previewOptions.logTab
881
+ const list = vendors(browser);
882
+ validateVendorsOrExit(list, (invalid, supported)=>{
883
+ console.error(unsupportedBrowserFlag(invalid, supported));
820
884
  });
821
- telemetry.track('cli_vendor_finish', {
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', {
822
924
  command: 'preview',
823
- vendor,
824
- duration_ms: Date.now() - vendorStart
925
+ duration_ms: Date.now() - cmdStart,
926
+ success: 0 === process.exitCode || null == process.exitCode,
927
+ exit_code: process.exitCode ?? 0
825
928
  });
826
- }
827
- telemetry.track('cli_command_finish', {
828
- command: 'preview',
829
- duration_ms: Date.now() - cmdStart,
830
- success: 0 === process.exitCode || null == process.exitCode,
831
- exit_code: process.exitCode ?? 0
832
- });
833
- });
834
- }
835
- function registerBuildCommand(program, telemetry) {
836
- 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('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
837
- if (buildOptions.author || buildOptions['authorMode']) {
838
- process.env.EXTENSION_AUTHOR_MODE = 'true';
839
- if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
840
- }
841
- const cmdStart = Date.now();
842
- telemetry.track('cli_command_start', {
843
- command: 'build',
844
- vendors: vendors(browser),
845
- polyfill_used: buildOptions.polyfill || false,
846
- zip: buildOptions.zip || false,
847
- zip_source: buildOptions.zipSource || false
848
929
  });
849
- const list = vendors(browser);
850
- validateVendorsOrExit(list, (invalid, supported)=>{
851
- console.error(unsupportedBrowserFlag(invalid, supported));
852
- });
853
- const { extensionBuild } = await import("extension-develop");
854
- for (const vendor of list){
855
- const vendorStart = Date.now();
856
- telemetry.track('cli_vendor_start', {
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', {
857
939
  command: 'build',
858
- vendor
859
- });
860
- const buildSummary = await extensionBuild(pathOrRemoteUrl, {
861
- browser: vendor,
862
- polyfill: buildOptions.polyfill,
863
- zip: buildOptions.zip,
864
- zipSource: buildOptions.zipSource,
865
- zipFilename: buildOptions.zipFilename,
866
- silent: buildOptions.silent
940
+ vendors: vendors(browser),
941
+ polyfill_used: buildOptions.polyfill || false,
942
+ zip: buildOptions.zip || false,
943
+ zip_source: buildOptions.zipSource || false
867
944
  });
868
- telemetry.track('cli_build_summary', {
869
- ...buildSummary
945
+ const list = vendors(browser);
946
+ validateVendorsOrExit(list, (invalid, supported)=>{
947
+ console.error(unsupportedBrowserFlag(invalid, supported));
870
948
  });
871
- telemetry.track('cli_vendor_finish', {
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', {
872
975
  command: 'build',
873
- vendor,
874
- duration_ms: Date.now() - vendorStart
976
+ duration_ms: Date.now() - cmdStart,
977
+ success: 0 === process.exitCode || null == process.exitCode,
978
+ exit_code: process.exitCode ?? 0
875
979
  });
876
- }
877
- telemetry.track('cli_command_finish', {
878
- command: 'build',
879
- duration_ms: Date.now() - cmdStart,
880
- success: 0 === process.exitCode || null == process.exitCode,
881
- exit_code: process.exitCode ?? 0
882
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;
883
996
  });
884
- }
885
- check_updates_checkUpdates(package_namespaceObject);
886
- const extensionJs = external_commander_namespaceObject.program;
887
- extensionJs.name(package_namespaceObject.name).description(package_namespaceObject.description).version(package_namespaceObject.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);
888
- registerCreateCommand(extensionJs, telemetry_cli_telemetry);
889
- registerDevCommand(extensionJs, telemetry_cli_telemetry);
890
- registerStartCommand(extensionJs, telemetry_cli_telemetry);
891
- registerPreviewCommand(extensionJs, telemetry_cli_telemetry);
892
- registerBuildCommand(extensionJs, telemetry_cli_telemetry);
893
- extensionJs.on('option:ai-help', function() {
894
- console.log(programAIHelp());
895
- process.exit(0);
896
- });
897
- if (process.argv.length <= 2) {
898
- extensionJs.outputHelp();
899
- process.exit(0);
900
- }
901
- extensionJs.parseAsync().catch((err)=>{
902
- console.error(unhandledError(err));
903
- process.exit(1);
904
- });
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
+ })();
905
1017
  for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
906
1018
  Object.defineProperty(exports, '__esModule', {
907
1019
  value: true