extension 4.1.1 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  [npm-version-image]: https://img.shields.io/npm/v/extension.svg?color=0971fe
2
2
  [npm-version-url]: https://www.npmjs.com/package/extension
3
- [npm-downloads-image]: https://img.shields.io/npm/dm/extension.svg?color=0971fe
4
- [npm-downloads-url]: https://www.npmjs.com/package/extension
5
3
  [stars-image]: https://img.shields.io/github/stars/extension-js/extension.js?style=flat&color=0971fe
6
4
  [stars-url]: https://github.com/extension-js/extension.js/stargazers
7
5
  [action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main&color=0971fe
@@ -11,7 +9,7 @@
11
9
  [snyk-image]: https://snyk.io/test/github/extension-js/extension.js/badge.svg?color=0971fe
12
10
  [snyk-url]: https://snyk.io/test/github/extension-js/extension.js
13
11
 
14
- # Extension.js [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![Stars][stars-image]][stars-url] [![CI][action-image]][action-url] [![Discord][discord-image]][discord-url]
12
+ # Extension.js [![Version][npm-version-image]][npm-version-url] [![Stars][stars-image]][stars-url] [![CI][action-image]][action-url] [![Discord][discord-image]][discord-url]
15
13
 
16
14
  > The cross-browser extension framework. Build for Chrome, Edge, Firefox, and Safari with no build config required.
17
15
 
@@ -41,7 +39,7 @@ Browser extensions ship with the worst dev experience in modern web. Manifest V3
41
39
 
42
40
  ## Watch it work
43
41
 
44
- [![Extension.js in 60 seconds: one command, a running extension](https://media.extension.land/video/extension-js/sixty-second-demo.gif)](https://extension.js.org/docs)
42
+ [![One command, and the extension is running in a real browser](https://media.extension.land/video/extension-js/sixty-second-demo.gif)](https://extension.js.org/docs)
45
43
 
46
44
  Or skip the install and try a [live template](https://templates.extension.dev) in your browser.
47
45
 
@@ -96,7 +94,7 @@ npx extension@latest dev --gecko-binary "/Applications/Firefox.app/Contents/MacO
96
94
 
97
95
  | <img alt="Chrome" src="https://media.extension.land/logos/browsers/chrome.svg" width="70"> | <img alt="Edge" src="https://media.extension.land/logos/browsers/edge.svg" width="70"> | <img alt="Firefox" src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> | <img alt="Safari" src="https://media.extension.land/logos/browsers/safari.svg" width="70"> | <img alt="Chromium" src="https://media.extension.land/logos/browsers/chromium.svg" width="70"> | <img alt="Gecko" src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> |
98
96
  | :-: | :-: | :-: | :-: | :-: | :-: |
99
- | Google Chrome<br>✅ Supported | Microsoft Edge<br>✅ Supported | Mozilla Firefox<br>✅ Supported | Apple Safari<br>✅ Supported | Chromium-based<br>✅ Supported | Gecko-based<br>✅ Supported |
97
+ | <sup>Google Chrome<br>✅ Supported</sup> | <sup>Microsoft Edge<br>✅ Supported</sup> | <sup>Mozilla Firefox<br>✅ Supported</sup> | <sup>Apple Safari<br>✅ Supported</sup> | <sup>Chromium-based<br>✅ Supported</sup> | <sup>Gecko-based<br>✅ Supported</sup> |
100
98
 
101
99
  </div>
102
100
 
@@ -155,10 +153,12 @@ npm install extension@latest --save-dev
155
153
  }
156
154
  ```
157
155
 
158
- Run `npm run dev` to develop, `npm run build` for production, and `npm run preview` to inspect the production output.
156
+ Run `npm run dev` to develop, and watch the browser open with your extension already loaded:
159
157
 
160
158
  [![extension dev: the browser opens with the extension loaded](https://media.extension.land/video/extension-js/dev-build-preview.gif)](https://extension.js.org/docs/commands/dev)
161
159
 
160
+ Use `npm run build` for production, and `npm run preview` to inspect the production output.
161
+
162
162
  ## Start from a Chrome sample
163
163
 
164
164
  Pull any sample from [Chrome Extension Samples](https://github.com/GoogleChrome/chrome-extensions-samples) and run it directly:
package/dist/browsers.cjs CHANGED
@@ -706,8 +706,10 @@ var __webpack_modules__ = {
706
706
  function safariDefaultBundleIdNote(bundleId) {
707
707
  return `${getLoggingPrefix('warn')} The bundle id ${pintor__rspack_import_8_default().gray(bundleId)} is generated from the app name.\nEvery project built from the same source shares this id, and the first team to register it takes it.\nSet your own with ${pintor__rspack_import_8_default().blue('--bundle-id')} before your first submission.\nAfter a submission, a new id is a new extension with none of your users.`;
708
708
  }
709
- function safariOpenHint(appPath, appName) {
710
- return `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\nThen enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
709
+ function safariOpenHint(appPath, appName, signed) {
710
+ const launch = `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\n`;
711
+ if (signed) return launch + `Then turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
712
+ return launch + `Then enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ` + `${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
711
713
  }
712
714
  function safariDryRunNotBuilding() {
713
715
  return `${getLoggingPrefix('info')} Dry run: skip the Safari app build.`;
@@ -718,7 +720,8 @@ var __webpack_modules__ = {
718
720
  function safariDryRunXcodebuild(cmd) {
719
721
  return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
720
722
  }
721
- function safariNextSteps(appName) {
723
+ function safariNextSteps(appName, signed) {
724
+ if (signed) return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} Signed with your team id, so this survives a restart.`;
722
725
  return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Advanced ▸ check ${pintor__rspack_import_8_default().yellow('“Show features for web developers”')}\n ${pintor__rspack_import_8_default().gray('2.')} Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} ${pintor__rspack_import_8_default().gray('(resets each launch)')}\n ${pintor__rspack_import_8_default().gray('3.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} The app window that just opened can also take you there.`;
723
726
  }
724
727
  function safariRegistered(appName) {
@@ -5402,6 +5405,7 @@ var __webpack_modules__ = {
5402
5405
  var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
5403
5406
  var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
5404
5407
  var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
5408
+ var ready_stamp = __webpack_require__("./browsers/browsers-lib/ready-stamp.ts");
5405
5409
  function logSafariDryRun(converterCmd, xcodebuildCmd) {
5406
5410
  if ((0, messaging._o)()) (0, messaging._w)(messages.KP());
5407
5411
  (0, messaging._w)(messages.yc());
@@ -5567,6 +5571,26 @@ var __webpack_modules__ = {
5567
5571
  severity: 'ok'
5568
5572
  };
5569
5573
  }
5574
+ async function resolvePidForBundle(bundleId) {
5575
+ for(let attempt = 0; attempt < 10; attempt += 1){
5576
+ const pid = await new Promise((resolve)=>{
5577
+ const child = (0, external_node_child_process_.spawn)("osascript", [
5578
+ '-e',
5579
+ `tell application "System Events" to get unix id of first process whose bundle identifier is "${bundleId}"`
5580
+ ]);
5581
+ let out = '';
5582
+ child.stdout.on('data', (d)=>out += String(d));
5583
+ child.on('error', ()=>resolve(null));
5584
+ child.on('close', ()=>{
5585
+ const n = Number(String(out).trim());
5586
+ resolve(Number.isFinite(n) && n > 0 ? n : null);
5587
+ });
5588
+ });
5589
+ if (pid) return pid;
5590
+ await new Promise((r)=>setTimeout(r, 500));
5591
+ }
5592
+ return null;
5593
+ }
5570
5594
  async function announceSafariDevSession(host, config, appPath) {
5571
5595
  try {
5572
5596
  await (0, banner.ai)({
@@ -5585,6 +5609,7 @@ var __webpack_modules__ = {
5585
5609
  const config = (0, safari_config.F7)(compilation, host);
5586
5610
  const converterArgs = (0, safari_config.w7)(config);
5587
5611
  const xcodebuildArgs = (0, safari_config.vx)(config);
5612
+ const isSigned = Boolean(config.developmentTeam);
5588
5613
  if ('full' === mode && config.bundleIdDerived) logger.warn?.(messages.$q(config.bundleIdentifier));
5589
5614
  if (host.dryRun || isTestEnv()) {
5590
5615
  logSafariDryRun(`xcrun ${converterArgs.join(' ')}`, `xcodebuild ${xcodebuildArgs.join(' ')}`);
@@ -5644,7 +5669,7 @@ var __webpack_modules__ = {
5644
5669
  }
5645
5670
  logger.info?.(messages.Rl(appPath));
5646
5671
  if (!config.open) {
5647
- logger.info?.(messages.aO(appPath, config.appName));
5672
+ logger.info?.(messages.aO(appPath, config.appName, isSigned));
5648
5673
  if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
5649
5674
  return describePackage(config);
5650
5675
  }
@@ -5657,7 +5682,15 @@ var __webpack_modules__ = {
5657
5682
  '-a',
5658
5683
  config.safariBinary
5659
5684
  ]);
5660
- logger.info?.(messages.fO(config.appName));
5685
+ const raisedBundleId = config.safariBinary ? 'com.apple.Safari' : config.bundleIdentifier;
5686
+ const browserPid = await resolvePidForBundle(raisedBundleId);
5687
+ if (browserPid) (0, ready_stamp.M)(config.extensionDir, {
5688
+ browserPid,
5689
+ binary: config.safariBinary || appPath,
5690
+ binaryProvenance: config.safariBinary ? 'pinned' : 'system',
5691
+ extensionId: `${config.bundleIdentifier}.Extension`
5692
+ });
5693
+ logger.info?.(messages.fO(config.appName, isSigned));
5661
5694
  if (await confirmRegisteredWithSafari(config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
5662
5695
  else logger.info?.(messages.qY(config.appName));
5663
5696
  if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
@@ -5717,7 +5750,8 @@ var __webpack_modules__ = {
5717
5750
  macOsOnly: false !== host.macOsOnly,
5718
5751
  language: 'swift',
5719
5752
  open: !host.noOpen,
5720
- safariBinary: host.safariBinary
5753
+ safariBinary: host.safariBinary,
5754
+ developmentTeam: String(host.developmentTeam || '').trim() || void 0
5721
5755
  };
5722
5756
  }
5723
5757
  function composeConverterArgs(config) {
@@ -5751,7 +5785,7 @@ var __webpack_modules__ = {
5751
5785
  return node_path__rspack_import_1.join(derivedDataPath(config), 'Build', 'Products', 'Release', `${config.appName}.app`);
5752
5786
  }
5753
5787
  function composeXcodebuildArgs(config) {
5754
- return [
5788
+ const base = [
5755
5789
  '-project',
5756
5790
  xcodeProjectPath(config),
5757
5791
  '-scheme',
@@ -5759,7 +5793,18 @@ var __webpack_modules__ = {
5759
5793
  '-configuration',
5760
5794
  'Release',
5761
5795
  '-derivedDataPath',
5762
- derivedDataPath(config),
5796
+ derivedDataPath(config)
5797
+ ];
5798
+ const team = String(config.developmentTeam || '').trim();
5799
+ if (team) return [
5800
+ ...base,
5801
+ `DEVELOPMENT_TEAM=${team}`,
5802
+ 'CODE_SIGN_STYLE=Automatic',
5803
+ '-allowProvisioningUpdates',
5804
+ 'build'
5805
+ ];
5806
+ return [
5807
+ ...base,
5763
5808
  'CODE_SIGN_IDENTITY=-',
5764
5809
  'CODE_SIGNING_REQUIRED=NO',
5765
5810
  'CODE_SIGNING_ALLOWED=YES',
package/dist/cli.cjs CHANGED
@@ -707,8 +707,10 @@ var __webpack_modules__ = {
707
707
  function safariDefaultBundleIdNote(bundleId) {
708
708
  return `${getLoggingPrefix('warn')} The bundle id ${pintor__rspack_import_8_default().gray(bundleId)} is generated from the app name.\nEvery project built from the same source shares this id, and the first team to register it takes it.\nSet your own with ${pintor__rspack_import_8_default().blue('--bundle-id')} before your first submission.\nAfter a submission, a new id is a new extension with none of your users.`;
709
709
  }
710
- function safariOpenHint(appPath, appName) {
711
- return `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\nThen enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
710
+ function safariOpenHint(appPath, appName, signed) {
711
+ const launch = `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\n`;
712
+ if (signed) return launch + `Then turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
713
+ return launch + `Then enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ` + `${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
712
714
  }
713
715
  function safariDryRunNotBuilding() {
714
716
  return `${getLoggingPrefix('info')} Dry run: skip the Safari app build.`;
@@ -719,7 +721,8 @@ var __webpack_modules__ = {
719
721
  function safariDryRunXcodebuild(cmd) {
720
722
  return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
721
723
  }
722
- function safariNextSteps(appName) {
724
+ function safariNextSteps(appName, signed) {
725
+ if (signed) return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} Signed with your team id, so this survives a restart.`;
723
726
  return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Advanced ▸ check ${pintor__rspack_import_8_default().yellow('“Show features for web developers”')}\n ${pintor__rspack_import_8_default().gray('2.')} Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} ${pintor__rspack_import_8_default().gray('(resets each launch)')}\n ${pintor__rspack_import_8_default().gray('3.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} The app window that just opened can also take you there.`;
724
727
  }
725
728
  function safariRegistered(appName) {
@@ -5393,6 +5396,7 @@ var __webpack_modules__ = {
5393
5396
  var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
5394
5397
  var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
5395
5398
  var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
5399
+ var ready_stamp = __webpack_require__("./browsers/browsers-lib/ready-stamp.ts");
5396
5400
  function logSafariDryRun(converterCmd, xcodebuildCmd) {
5397
5401
  if ((0, messaging._o)()) (0, messaging._w)(messages.KP());
5398
5402
  (0, messaging._w)(messages.yc());
@@ -5558,6 +5562,26 @@ var __webpack_modules__ = {
5558
5562
  severity: 'ok'
5559
5563
  };
5560
5564
  }
5565
+ async function resolvePidForBundle(bundleId) {
5566
+ for(let attempt = 0; attempt < 10; attempt += 1){
5567
+ const pid = await new Promise((resolve)=>{
5568
+ const child = (0, external_node_child_process_.spawn)("osascript", [
5569
+ '-e',
5570
+ `tell application "System Events" to get unix id of first process whose bundle identifier is "${bundleId}"`
5571
+ ]);
5572
+ let out = '';
5573
+ child.stdout.on('data', (d)=>out += String(d));
5574
+ child.on('error', ()=>resolve(null));
5575
+ child.on('close', ()=>{
5576
+ const n = Number(String(out).trim());
5577
+ resolve(Number.isFinite(n) && n > 0 ? n : null);
5578
+ });
5579
+ });
5580
+ if (pid) return pid;
5581
+ await new Promise((r)=>setTimeout(r, 500));
5582
+ }
5583
+ return null;
5584
+ }
5561
5585
  async function announceSafariDevSession(host, config, appPath) {
5562
5586
  try {
5563
5587
  await (0, banner.ai)({
@@ -5576,6 +5600,7 @@ var __webpack_modules__ = {
5576
5600
  const config = (0, safari_config.F7)(compilation, host);
5577
5601
  const converterArgs = (0, safari_config.w7)(config);
5578
5602
  const xcodebuildArgs = (0, safari_config.vx)(config);
5603
+ const isSigned = Boolean(config.developmentTeam);
5579
5604
  if ('full' === mode && config.bundleIdDerived) logger.warn?.(messages.$q(config.bundleIdentifier));
5580
5605
  if (host.dryRun || isTestEnv()) {
5581
5606
  logSafariDryRun(`xcrun ${converterArgs.join(' ')}`, `xcodebuild ${xcodebuildArgs.join(' ')}`);
@@ -5635,7 +5660,7 @@ var __webpack_modules__ = {
5635
5660
  }
5636
5661
  logger.info?.(messages.Rl(appPath));
5637
5662
  if (!config.open) {
5638
- logger.info?.(messages.aO(appPath, config.appName));
5663
+ logger.info?.(messages.aO(appPath, config.appName, isSigned));
5639
5664
  if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
5640
5665
  return describePackage(config);
5641
5666
  }
@@ -5648,7 +5673,15 @@ var __webpack_modules__ = {
5648
5673
  '-a',
5649
5674
  config.safariBinary
5650
5675
  ]);
5651
- logger.info?.(messages.fO(config.appName));
5676
+ const raisedBundleId = config.safariBinary ? 'com.apple.Safari' : config.bundleIdentifier;
5677
+ const browserPid = await resolvePidForBundle(raisedBundleId);
5678
+ if (browserPid) (0, ready_stamp.M)(config.extensionDir, {
5679
+ browserPid,
5680
+ binary: config.safariBinary || appPath,
5681
+ binaryProvenance: config.safariBinary ? 'pinned' : 'system',
5682
+ extensionId: `${config.bundleIdentifier}.Extension`
5683
+ });
5684
+ logger.info?.(messages.fO(config.appName, isSigned));
5652
5685
  if (await confirmRegisteredWithSafari(config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
5653
5686
  else logger.info?.(messages.qY(config.appName));
5654
5687
  if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
@@ -5708,7 +5741,8 @@ var __webpack_modules__ = {
5708
5741
  macOsOnly: false !== host.macOsOnly,
5709
5742
  language: 'swift',
5710
5743
  open: !host.noOpen,
5711
- safariBinary: host.safariBinary
5744
+ safariBinary: host.safariBinary,
5745
+ developmentTeam: String(host.developmentTeam || '').trim() || void 0
5712
5746
  };
5713
5747
  }
5714
5748
  function composeConverterArgs(config) {
@@ -5742,7 +5776,7 @@ var __webpack_modules__ = {
5742
5776
  return node_path__rspack_import_1.join(derivedDataPath(config), 'Build', 'Products', 'Release', `${config.appName}.app`);
5743
5777
  }
5744
5778
  function composeXcodebuildArgs(config) {
5745
- return [
5779
+ const base = [
5746
5780
  '-project',
5747
5781
  xcodeProjectPath(config),
5748
5782
  '-scheme',
@@ -5750,7 +5784,18 @@ var __webpack_modules__ = {
5750
5784
  '-configuration',
5751
5785
  'Release',
5752
5786
  '-derivedDataPath',
5753
- derivedDataPath(config),
5787
+ derivedDataPath(config)
5788
+ ];
5789
+ const team = String(config.developmentTeam || '').trim();
5790
+ if (team) return [
5791
+ ...base,
5792
+ `DEVELOPMENT_TEAM=${team}`,
5793
+ 'CODE_SIGN_STYLE=Automatic',
5794
+ '-allowProvisioningUpdates',
5795
+ 'build'
5796
+ ];
5797
+ return [
5798
+ ...base,
5754
5799
  'CODE_SIGN_IDENTITY=-',
5755
5800
  'CODE_SIGNING_REQUIRED=NO',
5756
5801
  'CODE_SIGNING_ALLOWED=YES',
@@ -6824,7 +6869,7 @@ var __webpack_modules__ = {
6824
6869
  }
6825
6870
  var messaging = __webpack_require__("./helpers/messaging.ts");
6826
6871
  const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
6827
- const TEMPLATE_CORPUS_REF = 'f7f4e6efb56a7e5ae08d58dbff3972d94af7d021';
6872
+ const TEMPLATE_CORPUS_REF = '36cd41466038e3d1045e3eca368f44f40b0a024b';
6828
6873
  const TEMPLATE_CORPUS_SLUGS = [
6829
6874
  'action',
6830
6875
  'action-locales',
@@ -6870,6 +6915,7 @@ var __webpack_modules__ = {
6870
6915
  'react',
6871
6916
  'sidebar',
6872
6917
  'sidebar-antd',
6918
+ 'sidebar-monorepo-nx',
6873
6919
  'sidebar-monorepo-turborepo',
6874
6920
  'sidebar-shadcn',
6875
6921
  'special-folders-pages',
@@ -6906,6 +6952,7 @@ var __webpack_modules__ = {
6906
6952
  'sidebar-antd',
6907
6953
  'sidebar-shadcn',
6908
6954
  'sidebar-monorepo-turborepo',
6955
+ 'sidebar-monorepo-nx',
6909
6956
  'ai-chatgpt',
6910
6957
  'ai-claude',
6911
6958
  'ai-gemini',
@@ -8353,7 +8400,7 @@ Cross-browser compatibility
8353
8400
  return null;
8354
8401
  }
8355
8402
  function registerBuildCommand(program) {
8356
- program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', parseOptionalBoolean).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser = 'chromium', ...buildOptions })=>{
8403
+ program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', parseOptionalBoolean).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari treats as unsigned: the extension then needs Develop \u25b8 Allow Unsigned Extensions re-ticked on every launch. A signed build is listed and stays enabled across restarts').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser = 'chromium', ...buildOptions })=>{
8357
8404
  if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
8358
8405
  process.env.EXTENSION_DEBUG = '1';
8359
8406
  process.env.EXTENSION_AUTHOR_MODE = 'true';
@@ -8386,6 +8433,10 @@ Cross-browser compatibility
8386
8433
  '--bundle-id',
8387
8434
  buildOptions.bundleId
8388
8435
  ],
8436
+ [
8437
+ '--development-team',
8438
+ buildOptions.developmentTeam
8439
+ ],
8389
8440
  [
8390
8441
  '--force-regenerate',
8391
8442
  buildOptions.forceRegenerate
@@ -8431,6 +8482,7 @@ Cross-browser compatibility
8431
8482
  mode,
8432
8483
  appName: buildOptions.appName,
8433
8484
  bundleId: buildOptions.bundleId,
8485
+ developmentTeam: buildOptions.developmentTeam,
8434
8486
  macOsOnly: buildOptions.macosOnly,
8435
8487
  forceRegenerate: buildOptions.forceRegenerate,
8436
8488
  safariPackager: safariPackagingEnabled ? (0, safari_packager.P)({
@@ -8940,7 +8992,7 @@ Cross-browser compatibility
8940
8992
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
8941
8993
  }
8942
8994
  function registerDevCommand(program) {
8943
- program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --no-reload emit a dev-mode dist without the content-script reload runtime; tabs need manual reload to see changes\n --wait wait for ready contract and exit; pair with --output json for machine output\n").option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`-b, --browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only; no live reload)').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('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
8995
+ program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --no-reload emit a dev-mode dist without the content-script reload runtime; tabs need manual reload to see changes\n --wait wait for ready contract and exit; pair with --output json for machine output\n").option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`-b, --browser <${BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only; no live reload)').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('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari treats as unsigned: the extension then needs Develop \u25b8 Allow Unsigned Extensions re-ticked on every launch. A signed build is listed and stays enabled across restarts').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').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('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
8944
8996
  const { browser = 'chromium', ...devOptions } = options;
8945
8997
  if (devOptions.debug || devOptions.author || devOptions.authorMode) {
8946
8998
  process.env.EXTENSION_DEBUG = '1';
@@ -8984,6 +9036,10 @@ Cross-browser compatibility
8984
9036
  '--bundle-id',
8985
9037
  opts.bundleId
8986
9038
  ],
9039
+ [
9040
+ '--development-team',
9041
+ opts.developmentTeam
9042
+ ],
8987
9043
  [
8988
9044
  '--force-regenerate',
8989
9045
  opts.forceRegenerate
@@ -72,11 +72,11 @@ export declare function safariOpening(target: string): string;
72
72
  export declare function safariToolFailed(tool: string, exitCode: number | null, outputTail: string): string;
73
73
  export declare function safariConverterWarnings(warnings: string[]): string;
74
74
  export declare function safariDefaultBundleIdNote(bundleId: string): string;
75
- export declare function safariOpenHint(appPath: string, appName: string): string;
75
+ export declare function safariOpenHint(appPath: string, appName: string, signed?: boolean): string;
76
76
  export declare function safariDryRunNotBuilding(): string;
77
77
  export declare function safariDryRunConverter(cmd: string): string;
78
78
  export declare function safariDryRunXcodebuild(cmd: string): string;
79
- export declare function safariNextSteps(appName: string): string;
79
+ export declare function safariNextSteps(appName: string, signed?: boolean): string;
80
80
  export declare function safariRegistered(appName: string): string;
81
81
  export declare function safariNotYetRegistered(appName: string): string;
82
82
  export declare function safariRebuilt(appName: string): string;
@@ -2,6 +2,7 @@ import type { PluginInterface } from '../browsers-types';
2
2
  export type SafariPluginLike = Pick<PluginInterface, 'extension' | 'noOpen' | 'instanceId' | 'dryRun'> & {
3
3
  browser: PluginInterface['browser'];
4
4
  safariBinary?: string;
5
+ developmentTeam?: string;
5
6
  appName?: string;
6
7
  bundleId?: string;
7
8
  macOsOnly?: boolean;
@@ -19,4 +20,5 @@ export interface SafariBuildConfig {
19
20
  language: 'swift' | 'objc';
20
21
  open: boolean;
21
22
  safariBinary?: string;
23
+ developmentTeam?: string;
22
24
  }
@@ -1,6 +1,6 @@
1
1
  export declare const DEFAULT_TEMPLATE = "javascript";
2
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
+ export declare const TEMPLATE_CATALOG_URL = "https://github.com/extension-js/examples/tree/36cd41466038e3d1045e3eca368f44f40b0a024b/examples";
4
4
  export interface TemplateGroup {
5
5
  title: string;
6
6
  summary: string;
@@ -1,3 +1,3 @@
1
1
  export declare const TEMPLATE_CORPUS_REPO = "extension-js/examples";
2
- export declare const TEMPLATE_CORPUS_REF = "f7f4e6efb56a7e5ae08d58dbff3972d94af7d021";
2
+ export declare const TEMPLATE_CORPUS_REF = "36cd41466038e3d1045e3eca368f44f40b0a024b";
3
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.1.1",
41
+ "version": "4.1.3",
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.1.1",
110
- "extension-develop": "4.1.1",
111
- "extension-install": "4.1.1",
109
+ "extension-create": "4.1.3",
110
+ "extension-develop": "4.1.3",
111
+ "extension-install": "4.1.3",
112
112
  "commander": "^15.0.0",
113
113
  "pintor": "0.3.0",
114
114
  "semver": "^7.7.3",