extension 4.0.29 → 4.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -6185,7 +6185,7 @@ var __webpack_modules__ = {
6185
6185
  const DEFAULT_SAMPLE_RATE = Number(process.env.EXTENSION_TELEMETRY_SAMPLE_RATE || 0.2);
6186
6186
  const DEFAULT_MAX_EVENTS = Number(process.env.EXTENSION_TELEMETRY_MAX_EVENTS || 3);
6187
6187
  const DEFAULT_DEBOUNCE_MS = Number(process.env.EXTENSION_TELEMETRY_DEBOUNCE_MS || 60000);
6188
- const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 300);
6188
+ const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 2000);
6189
6189
  const DEFAULT_AUDIT_MAX_BYTES = 1048576;
6190
6190
  function auditMaxBytes() {
6191
6191
  const raw = Number(process.env.EXTENSION_TELEMETRY_AUDIT_MAX_BYTES);
@@ -6268,15 +6268,55 @@ var __webpack_modules__ = {
6268
6268
  }
6269
6269
  return null;
6270
6270
  }
6271
+ function isInsideGitWorkTree(startDir) {
6272
+ const home = (()=>{
6273
+ try {
6274
+ return external_node_path_default().resolve(external_node_os_default().homedir());
6275
+ } catch {
6276
+ return '';
6277
+ }
6278
+ })();
6279
+ let current = external_node_path_default().resolve(startDir);
6280
+ for(let i = 0; i < 100; i++){
6281
+ if (home && current === home) break;
6282
+ try {
6283
+ if (external_node_fs_default().existsSync(external_node_path_default().join(current, '.git'))) return true;
6284
+ } catch {}
6285
+ const parent = external_node_path_default().dirname(current);
6286
+ if (parent === current) break;
6287
+ current = parent;
6288
+ }
6289
+ return false;
6290
+ }
6291
+ function machineScopedId(rawId) {
6292
+ let salt = '';
6293
+ try {
6294
+ salt = `${external_node_os_default().hostname()}|${external_node_os_default().userInfo().username}`;
6295
+ } catch {
6296
+ salt = String(external_node_os_default().hostname?.() || '');
6297
+ }
6298
+ const digest = external_node_crypto_default().createHash('sha256').update(`${rawId}|${salt}`).digest('hex');
6299
+ return [
6300
+ digest.slice(0, 8),
6301
+ digest.slice(8, 12),
6302
+ digest.slice(12, 16),
6303
+ digest.slice(16, 20),
6304
+ digest.slice(20, 32)
6305
+ ].join('-');
6306
+ }
6271
6307
  function loadOrCreateId(file) {
6308
+ const inWorkTree = isInsideGitWorkTree(external_node_path_default().dirname(file));
6272
6309
  try {
6273
- if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
6310
+ if (external_node_fs_default().existsSync(file)) {
6311
+ const stored = external_node_fs_default().readFileSync(file, 'utf8').trim();
6312
+ return inWorkTree ? machineScopedId(stored) : stored;
6313
+ }
6274
6314
  } catch {}
6275
6315
  const id = external_node_crypto_default().randomUUID();
6276
6316
  if (ensureDir(external_node_path_default().dirname(file))) try {
6277
6317
  external_node_fs_default().writeFileSync(file, id, 'utf8');
6278
6318
  } catch {}
6279
- return id;
6319
+ return inWorkTree ? machineScopedId(id) : id;
6280
6320
  }
6281
6321
  function readConsentFile(file) {
6282
6322
  try {
@@ -6320,7 +6360,7 @@ var __webpack_modules__ = {
6320
6360
  enabled: false,
6321
6361
  source: 'ci'
6322
6362
  };
6323
- if ('enabled' === stored) return {
6363
+ if ('enabled' === stored && storage && !isInsideGitWorkTree(storage.telemetryDir)) return {
6324
6364
  enabled: true,
6325
6365
  source: 'config'
6326
6366
  };
@@ -6722,9 +6762,68 @@ var __webpack_modules__ = {
6722
6762
  return await import(bridgeSpecifier);
6723
6763
  }
6724
6764
  var messaging = __webpack_require__("./helpers/messaging.ts");
6765
+ const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
6766
+ const TEMPLATE_CORPUS_REF = 'f7f4e6efb56a7e5ae08d58dbff3972d94af7d021';
6767
+ const TEMPLATE_CORPUS_SLUGS = [
6768
+ 'action',
6769
+ 'action-locales',
6770
+ 'ai-chatgpt',
6771
+ 'ai-claude',
6772
+ 'ai-gemini',
6773
+ 'ai-perplexity',
6774
+ 'content',
6775
+ 'content-css-modules',
6776
+ 'content-custom-font',
6777
+ 'content-env',
6778
+ 'content-less',
6779
+ 'content-less-modules',
6780
+ 'content-main-world',
6781
+ 'content-multi-one-entry',
6782
+ 'content-multi-three-entries',
6783
+ 'content-preact',
6784
+ 'content-react',
6785
+ 'content-sass',
6786
+ 'content-sass-modules',
6787
+ 'content-svelte',
6788
+ "content-typescript",
6789
+ 'content-vue',
6790
+ 'init',
6791
+ "javascript",
6792
+ 'new',
6793
+ 'new-browser-flags',
6794
+ 'new-config-eslint',
6795
+ 'new-config-prettier',
6796
+ 'new-config-stylelint',
6797
+ 'new-crypto',
6798
+ 'new-env',
6799
+ 'new-less',
6800
+ 'new-preact',
6801
+ 'new-react',
6802
+ 'new-react-router',
6803
+ 'new-sass',
6804
+ 'new-svelte',
6805
+ "new-typescript",
6806
+ 'new-vue',
6807
+ 'playwright',
6808
+ 'preact',
6809
+ 'react',
6810
+ 'sidebar',
6811
+ 'sidebar-antd',
6812
+ 'sidebar-monorepo-turborepo',
6813
+ 'sidebar-shadcn',
6814
+ 'special-folders-pages',
6815
+ "special-folders-scripts",
6816
+ 'svelte',
6817
+ 'transformers-js',
6818
+ "typescript",
6819
+ 'vue'
6820
+ ];
6725
6821
  const DEFAULT_TEMPLATE = "javascript";
6726
- const TEMPLATE_CATALOG_URL = 'https://github.com/extension-js/examples/tree/main/examples';
6727
- const TEMPLATE_GROUPS = [
6822
+ const BUNDLED_TEMPLATES = [
6823
+ "javascript"
6824
+ ];
6825
+ const TEMPLATE_CATALOG_URL = `https://github.com/${TEMPLATE_CORPUS_REPO}/tree/${TEMPLATE_CORPUS_REF}/examples`;
6826
+ const CURATED_GROUPS = [
6728
6827
  {
6729
6828
  title: 'Starters',
6730
6829
  summary: 'a bare manifest, or one language or framework with sidebar UI',
@@ -6745,7 +6844,7 @@ var __webpack_modules__ = {
6745
6844
  'sidebar',
6746
6845
  'sidebar-antd',
6747
6846
  'sidebar-shadcn',
6748
- 'sidebar-monorepo-turbopack',
6847
+ 'sidebar-monorepo-turborepo',
6749
6848
  'ai-chatgpt',
6750
6849
  'ai-claude',
6751
6850
  'ai-gemini',
@@ -6814,6 +6913,33 @@ var __webpack_modules__ = {
6814
6913
  ]
6815
6914
  }
6816
6915
  ];
6916
+ const UNCURATED_GROUP_TITLE = 'More templates';
6917
+ function buildTemplateGroups() {
6918
+ const published = new Set(TEMPLATE_CORPUS_SLUGS);
6919
+ const claimed = new Set();
6920
+ const groups = [];
6921
+ for (const group of CURATED_GROUPS){
6922
+ const templates = group.templates.filter((name)=>{
6923
+ if (!published.has(name) || claimed.has(name)) return false;
6924
+ claimed.add(name);
6925
+ return true;
6926
+ });
6927
+ if (templates.length) groups.push({
6928
+ ...group,
6929
+ templates
6930
+ });
6931
+ }
6932
+ const uncurated = TEMPLATE_CORPUS_SLUGS.filter((name)=>!claimed.has(name));
6933
+ if (uncurated.length) groups.push({
6934
+ title: UNCURATED_GROUP_TITLE,
6935
+ summary: 'published in the catalog, not yet grouped',
6936
+ templates: [
6937
+ ...uncurated
6938
+ ]
6939
+ });
6940
+ return groups;
6941
+ }
6942
+ const TEMPLATE_GROUPS = buildTemplateGroups();
6817
6943
  const TEMPLATE_ALIASES = [];
6818
6944
  function listTemplates() {
6819
6945
  return TEMPLATE_GROUPS.flatMap((group)=>group.templates);
@@ -6857,14 +6983,19 @@ var __webpack_modules__ = {
6857
6983
  function renderCreateTemplateHelp() {
6858
6984
  const total = listTemplates().length;
6859
6985
  const dim = (text)=>external_pintor_default().gray(text);
6986
+ const defaultIsBundled = BUNDLED_TEMPLATES.includes(DEFAULT_TEMPLATE);
6860
6987
  return [
6861
6988
  '',
6862
6989
  external_pintor_default().underline(external_pintor_default().blue(`Templates (${total})`)),
6863
6990
  renderTemplateList(),
6864
6991
  '',
6865
6992
  ` ${external_pintor_default().green('Default')}`,
6866
- ` ${external_pintor_default().blue(DEFAULT_TEMPLATE)} ${dim('is used when --template is omitted. It ships inside the CLI,')}`,
6867
- dim(' so it scaffolds with no network call.'),
6993
+ ` ${external_pintor_default().blue(DEFAULT_TEMPLATE)} ${dim('is used when --template is omitted.')}`,
6994
+ ...defaultIsBundled ? [
6995
+ dim(' It ships inside the CLI, so it scaffolds with no network.')
6996
+ ] : [
6997
+ dim(' It downloads the catalog archive like every other name.')
6998
+ ],
6868
6999
  '',
6869
7000
  ` ${external_pintor_default().green('Everything else')}`,
6870
7001
  dim(' downloads the catalog archive at create time, so it needs the'),
@@ -7290,7 +7421,7 @@ Environment variables
7290
7421
 
7291
7422
  Available templates
7292
7423
  ${TEMPLATE_GROUPS.map((group)=>`- ${external_pintor_default().green(group.title)} ${messages_arg(`(${group.summary})`)}: ${group.templates.map((template)=>messages_code(template)).join(', ')}`).join('\n')}${TEMPLATE_ALIASES.length > 0 ? `\n- ${external_pintor_default().green('Alias')}: ${TEMPLATE_ALIASES.map((alias)=>`${messages_code(alias.name)} ${messages_arg(alias.note)}`).join(', ')}` : ''}
7293
- - ${messages_code(DEFAULT_TEMPLATE)} is the default when ${messages_code('--template')} is omitted. It ships inside the CLI and needs no network.
7424
+ - ${messages_code(DEFAULT_TEMPLATE)} is the default when ${messages_code('--template')} is omitted.${BUNDLED_TEMPLATES.includes(DEFAULT_TEMPLATE) ? ' It ships inside the CLI and needs no network.' : ''}
7294
7425
  - Every other name is downloaded from ${messages_code(TEMPLATE_CATALOG_URL)} at create time. A GitHub or ZIP URL works in place of a name.
7295
7426
  - A name that is not on this list fails with ${messages_code('TemplateNotFoundError')}. Run ${messages_code('extension create --help')} for the same list.
7296
7427
 
@@ -7427,9 +7558,13 @@ Cross-browser compatibility
7427
7558
  templates: {
7428
7559
  default: DEFAULT_TEMPLATE,
7429
7560
  bundled: [
7430
- DEFAULT_TEMPLATE
7561
+ ...BUNDLED_TEMPLATES
7431
7562
  ],
7432
7563
  catalogUrl: TEMPLATE_CATALOG_URL,
7564
+ corpus: {
7565
+ repo: TEMPLATE_CORPUS_REPO,
7566
+ ref: TEMPLATE_CORPUS_REF
7567
+ },
7433
7568
  names: listTemplates(),
7434
7569
  groups: TEMPLATE_GROUPS.map((group)=>({
7435
7570
  title: group.title,
@@ -7445,10 +7580,10 @@ Cross-browser compatibility
7445
7580
  },
7446
7581
  notes: [
7447
7582
  `extension create <name> with no --template scaffolds ${DEFAULT_TEMPLATE}`,
7448
- `${DEFAULT_TEMPLATE} is bundled with the CLI and scaffolds offline. Every other name downloads the examples archive at create time`,
7583
+ 'every name in bundled[] ships inside the CLI package and scaffolds offline. Every other name downloads the examples archive at create time',
7449
7584
  'a GitHub URL or a ZIP URL is accepted in place of a catalog name',
7450
7585
  'a name outside names[] fails with TemplateNotFoundError and creates nothing',
7451
- 'this list ships with the CLI, so it is the list this CLI version can scaffold, not necessarily the current contents of the catalog repository'
7586
+ `names[] is generated from ${TEMPLATE_CORPUS_REPO} at corpus.ref, the exact commit this CLI version downloads, so it is what this version can scaffold and not the current contents of the catalog repository`
7452
7587
  ]
7453
7588
  },
7454
7589
  capabilities: {
@@ -7636,6 +7771,7 @@ Cross-browser compatibility
7636
7771
  const browser = options.browser || 'chromium';
7637
7772
  const format = resolveFormat(options);
7638
7773
  const matches = makeFilter(options);
7774
+ if (options.signalsOnly) console.error("extension logs --signals-only: no signals emitter ships in this build, so dev sessions record no dx.signal events and this filter will print nothing.");
7639
7775
  if (options.follow) return void await followLogs(projectPath, browser, format, matches);
7640
7776
  const file = logsFilePath(projectPath, browser);
7641
7777
  if (!external_node_fs_default().existsSync(file)) {
File without changes
@@ -225,6 +225,10 @@ export type ProgramAIHelpJSON = {
225
225
  default: string;
226
226
  bundled: string[];
227
227
  catalogUrl: string;
228
+ corpus: {
229
+ repo: string;
230
+ ref: string;
231
+ };
228
232
  names: string[];
229
233
  groups: Array<{
230
234
  title: string;
@@ -26,6 +26,8 @@ type TelemetryStorage = {
26
26
  export declare const DEFAULT_POSTHOG_KEY: string;
27
27
  export declare function isSourceCheckout(startDir?: string): boolean;
28
28
  export declare function resolveTelemetryStorage(): TelemetryStorage | null;
29
+ export declare function isInsideGitWorkTree(startDir: string): boolean;
30
+ export declare function loadOrCreateId(file: string): string;
29
31
  export declare function resolveTelemetryConsent(argv?: string[]): {
30
32
  enabled: boolean;
31
33
  source: TelemetrySource;
@@ -1,5 +1,6 @@
1
1
  export declare const DEFAULT_TEMPLATE = "javascript";
2
- export declare const TEMPLATE_CATALOG_URL = "https://github.com/extension-js/examples/tree/main/examples";
2
+ export declare const BUNDLED_TEMPLATES: readonly string[];
3
+ export declare const TEMPLATE_CATALOG_URL = "https://github.com/extension-js/examples/tree/f7f4e6efb56a7e5ae08d58dbff3972d94af7d021/examples";
3
4
  export interface TemplateGroup {
4
5
  title: string;
5
6
  summary: string;
@@ -10,6 +11,8 @@ export interface TemplateAlias {
10
11
  resolvesTo: string;
11
12
  note: string;
12
13
  }
14
+ export declare const CURATED_GROUPS: readonly TemplateGroup[];
15
+ export declare const UNCURATED_GROUP_TITLE = "More templates";
13
16
  export declare const TEMPLATE_GROUPS: readonly TemplateGroup[];
14
17
  export declare const TEMPLATE_ALIASES: readonly TemplateAlias[];
15
18
  export declare function listTemplates(): string[];
@@ -0,0 +1,3 @@
1
+ export declare const TEMPLATE_CORPUS_REPO = "extension-js/examples";
2
+ export declare const TEMPLATE_CORPUS_REF = "f7f4e6efb56a7e5ae08d58dbff3972d94af7d021";
3
+ export declare const TEMPLATE_CORPUS_SLUGS: readonly string[];
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "extension": "./bin/extension.cjs"
39
39
  },
40
40
  "name": "extension",
41
- "version": "4.0.29",
41
+ "version": "4.0.32",
42
42
  "description": "The cross-browser extension framework. Build Chrome, Edge, Firefox, and Safari extensions with no build configuration.",
43
43
  "homepage": "https://extension.js.org/",
44
44
  "bugs": {
@@ -106,9 +106,9 @@
106
106
  "vivaldi-location2": "2.1.1",
107
107
  "waterfox-location": "2.1.1",
108
108
  "yandex-location": "2.1.1",
109
- "extension-create": "4.0.29",
110
- "extension-develop": "4.0.29",
111
- "extension-install": "4.0.29",
109
+ "extension-create": "4.0.32",
110
+ "extension-develop": "4.0.32",
111
+ "extension-install": "4.0.32",
112
112
  "commander": "^15.0.0",
113
113
  "pintor": "0.3.0",
114
114
  "semver": "^7.7.3",
package/types/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  declare global {
7
7
  // Align types with Extension.js runtime: we provide the browser global via
8
- // webextension-polyfill in Chromium, and it's natively available in Firefox.
8
+ // webextension-polyfill in Chromium; Firefox and Safari ship it natively.
9
9
  const browser: typeof import('webextension-polyfill')
10
10
 
11
11
  type ExtensionBrowser =