extension 3.2.0-next.2 → 3.2.0-next.5

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.
@@ -12,6 +12,7 @@ export declare class Telemetry {
12
12
  private disabled;
13
13
  private apiKey?;
14
14
  private host?;
15
+ private storage;
15
16
  private buffer;
16
17
  private timer;
17
18
  constructor(init: TelemetryInit);
package/dist/cli.js CHANGED
@@ -361,30 +361,76 @@ function configDir() {
361
361
  if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
362
362
  return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
363
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
+ }
364
374
  function ensureDir(p) {
365
- if (external_node_fs_default().existsSync(p)) return;
366
- external_node_fs_default().mkdirSync(p, {
367
- recursive: true
368
- });
375
+ try {
376
+ if (external_node_fs_default().existsSync(p)) return true;
377
+ external_node_fs_default().mkdirSync(p, {
378
+ recursive: true
379
+ });
380
+ return true;
381
+ } catch {
382
+ return false;
383
+ }
384
+ }
385
+ function ensureWritableDir(p) {
386
+ if (!ensureDir(p)) return false;
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;
395
+ }
369
396
  }
370
397
  function loadOrCreateId(file) {
371
- if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
398
+ try {
399
+ if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
400
+ } catch {}
372
401
  const id = external_node_crypto_default().randomUUID();
373
- ensureDir(external_node_path_default().dirname(file));
374
- external_node_fs_default().writeFileSync(file, id, 'utf8');
402
+ if (ensureDir(external_node_path_default().dirname(file))) try {
403
+ external_node_fs_default().writeFileSync(file, id, 'utf8');
404
+ } catch {}
375
405
  return id;
376
406
  }
377
- function auditFilePath() {
378
- const dir = external_node_path_default().join(configDir(), 'telemetry');
379
- ensureDir(dir);
380
- return external_node_path_default().join(dir, 'events.jsonl');
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
+ };
425
+ }
426
+ return null;
381
427
  }
382
428
  const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
383
429
  const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
384
430
  const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
385
431
  class Telemetry {
386
432
  track(event, props = {}) {
387
- if (this.disabled) return;
433
+ if (this.disabled || !this.storage) return;
388
434
  const payload = {
389
435
  event,
390
436
  properties: {
@@ -394,7 +440,12 @@ class Telemetry {
394
440
  },
395
441
  distinct_id: this.anonId
396
442
  };
397
- external_node_fs_default().appendFileSync(auditFilePath(), JSON.stringify(payload) + '\n');
443
+ try {
444
+ external_node_fs_default().appendFileSync(this.storage.auditFile, JSON.stringify(payload) + '\n');
445
+ } catch {
446
+ this.disabled = true;
447
+ return;
448
+ }
398
449
  if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
399
450
  if (!this.apiKey || !this.host) return;
400
451
  this.buffer.push(payload);
@@ -439,14 +490,16 @@ class Telemetry {
439
490
  _define_property(this, "disabled", void 0);
440
491
  _define_property(this, "apiKey", void 0);
441
492
  _define_property(this, "host", void 0);
493
+ _define_property(this, "storage", null);
442
494
  _define_property(this, "buffer", []);
443
495
  _define_property(this, "timer", null);
444
496
  this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
445
497
  this.disabled = Boolean(init.disabled);
446
498
  this.anonId = 'disabled';
447
499
  if (!this.disabled) {
448
- const idFile = external_node_path_default().join(configDir(), 'telemetry', 'anonymous-id');
449
- this.anonId = loadOrCreateId(idFile);
500
+ this.storage = resolveTelemetryStorage();
501
+ if (this.storage) this.anonId = loadOrCreateId(this.storage.idFile);
502
+ else this.disabled = true;
450
503
  }
451
504
  this.common = {
452
505
  app: init.app,
@@ -459,15 +512,17 @@ class Telemetry {
459
512
  };
460
513
  this.apiKey = init.apiKey || process.env.EXTENSION_PUBLIC_POSTHOG_KEY;
461
514
  this.host = init.host || process.env.EXTENSION_PUBLIC_POSTHOG_HOST;
462
- if (!this.disabled) {
463
- const consentPath = external_node_path_default().join(configDir(), 'telemetry', 'consent');
464
- if (!external_node_fs_default().existsSync(consentPath)) {
465
- external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
466
- this.track('cli_telemetry_consent', {
467
- value: 'implicit_opt_in'
468
- });
469
- console.log(`${external_pintor_default().gray('►►►')} Telemetry is enabled for Extension.js. To opt out, run with --no-telemetry. Learn more in TELEMETRY.md.`);
470
- }
515
+ if (!this.disabled && this.storage) {
516
+ const consentPath = this.storage.consentFile;
517
+ try {
518
+ if (!external_node_fs_default().existsSync(consentPath)) {
519
+ external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
520
+ this.track('cli_telemetry_consent', {
521
+ value: 'implicit_opt_in'
522
+ });
523
+ console.log(`${external_pintor_default().gray('►►►')} Telemetry is enabled for Extension.js. To opt out, run with --no-telemetry. Learn more in TELEMETRY.md.`);
524
+ }
525
+ } catch {}
471
526
  }
472
527
  }
473
528
  }
@@ -669,7 +724,7 @@ function parseLogContexts(raw) {
669
724
  return values.length > 0 ? values : void 0;
670
725
  }
671
726
  function registerDevCommand(program, telemetry) {
672
- 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 }) {
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 }) {
673
728
  if (devOptions.author || devOptions['authorMode']) {
674
729
  process.env.EXTENSION_AUTHOR_MODE = 'true';
675
730
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
@@ -712,6 +767,7 @@ function registerDevCommand(program, telemetry) {
712
767
  startingUrl: devOptions.startingUrl,
713
768
  source: devOptions.source,
714
769
  watchSource: devOptions.watchSource,
770
+ install: devOptions.install,
715
771
  logLevel: logsOption || devOptions.logLevel || 'off',
716
772
  logContexts: parseLogContexts(logContextOption),
717
773
  logFormat: devOptions.logFormat || 'pretty',
@@ -736,7 +792,7 @@ function registerDevCommand(program, telemetry) {
736
792
  });
737
793
  }
738
794
  function registerStartCommand(program, telemetry) {
739
- 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 }) {
795
+ 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 }) {
740
796
  if (startOptions.author || startOptions.authorMode) {
741
797
  process.env.EXTENSION_AUTHOR_MODE = 'true';
742
798
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
@@ -769,6 +825,7 @@ function registerStartCommand(program, telemetry) {
769
825
  geckoBinary: startOptions.geckoBinary,
770
826
  startingUrl: startOptions.startingUrl,
771
827
  port: startOptions.port,
828
+ install: startOptions.install,
772
829
  source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
773
830
  watchSource: startOptions.watchSource,
774
831
  logLevel: logsOption || startOptions.logLevel || 'off',
@@ -855,7 +912,7 @@ function registerPreviewCommand(program, telemetry) {
855
912
  });
856
913
  }
857
914
  function registerBuildCommand(program, telemetry) {
858
- 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 }) {
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 }) {
859
916
  if (buildOptions.author || buildOptions['authorMode']) {
860
917
  process.env.EXTENSION_AUTHOR_MODE = 'true';
861
918
  if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
@@ -885,7 +942,8 @@ function registerBuildCommand(program, telemetry) {
885
942
  zip: buildOptions.zip,
886
943
  zipSource: buildOptions.zipSource,
887
944
  zipFilename: buildOptions.zipFilename,
888
- silent: buildOptions.silent
945
+ silent: buildOptions.silent,
946
+ install: buildOptions.install
889
947
  });
890
948
  telemetry.track('cli_build_summary', {
891
949
  ...buildSummary
package/package.json CHANGED
@@ -35,7 +35,7 @@
35
35
  "extension": "./dist/cli.js"
36
36
  },
37
37
  "name": "extension",
38
- "version": "3.2.0-next.2",
38
+ "version": "3.2.0-next.5",
39
39
  "description": "Create cross-browser extensions with no build configuration.",
40
40
  "homepage": "https://extension.js.org/",
41
41
  "bugs": {
@@ -51,6 +51,7 @@
51
51
  "registry": "https://registry.npmjs.org"
52
52
  },
53
53
  "scripts": {
54
+ "pretest": "pnpm run compile",
54
55
  "prepublishOnly": "pnpm run compile",
55
56
  "compile": "rslib build",
56
57
  "watch": "rslib build --watch",
@@ -88,8 +89,8 @@
88
89
  "cli"
89
90
  ],
90
91
  "dependencies": {
91
- "extension-create": "^3.2.0-next.2",
92
- "extension-develop": "^3.2.0-next.2",
92
+ "extension-create": "^3.2.0-next.5",
93
+ "extension-develop": "^3.2.0-next.5",
93
94
  "commander": "^14.0.2",
94
95
  "pintor": "0.3.0",
95
96
  "semver": "^7.7.3",
@@ -30,6 +30,7 @@ declare module 'extension-develop' {
30
30
  zipSource?: boolean
31
31
  zipFilename?: string
32
32
  silent?: boolean
33
+ install?: boolean
33
34
  }
34
35
 
35
36
  export interface DevOptions {
@@ -49,6 +50,7 @@ declare module 'extension-develop' {
49
50
  logColor?: boolean
50
51
  logUrl?: string
51
52
  logTab?: string | number
53
+ install?: boolean
52
54
  }
53
55
 
54
56
  export interface PreviewOptions extends DevOptions {}