extension 4.1.19 → 4.1.21
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 +23 -20
- package/bin/extension.cjs +2 -0
- package/dist/84.cjs +2 -1
- package/dist/browsers.cjs +179 -95
- package/dist/cli.cjs +454 -238
- package/dist/extension/browsers/__spec__/safari-fake-tools.d.ts +27 -0
- package/dist/extension/browsers/browsers-lib/constants.d.ts +0 -2
- package/dist/extension/browsers/browsers-lib/messages.d.ts +2 -1
- package/dist/extension/browsers/browsers-lib/resolve-profile.d.ts +0 -35
- package/dist/extension/browsers/browsers-lib/write-json-atomic.d.ts +1 -0
- package/dist/extension/browsers/browsers-types.d.ts +0 -89
- package/dist/extension/browsers/index.d.ts +1 -29
- package/dist/extension/browsers/run-chromium/chromium-launch/extension-output-path.d.ts +0 -6
- package/dist/extension/browsers/run-chromium/chromium-launch/index.d.ts +0 -9
- package/dist/extension/browsers/run-chromium/chromium-types.d.ts +0 -11
- package/dist/extension/browsers/run-safari/safari-launch/index.d.ts +2 -7
- package/dist/extension/browsers/run-safari/safari-launch/tools.d.ts +17 -0
- package/dist/extension/browsers/run-safari/safari-packager.d.ts +2 -16
- package/dist/extension/browsers/run-safari/safari-types.d.ts +2 -1
- package/dist/extension/commands/act.d.ts +0 -6
- package/dist/extension/commands/doctor.d.ts +0 -7
- package/dist/extension/commands/publish.d.ts +0 -6
- package/dist/extension/config-types.d.ts +5 -2
- package/dist/extension/helpers/cli-explicit.d.ts +0 -15
- package/dist/extension/helpers/messages.d.ts +7 -0
- package/dist/extension/helpers/node-version-guard.d.ts +7 -2
- package/dist/extension/helpers/template-catalog.d.ts +1 -1
- package/dist/extension/helpers/template-corpus.generated.d.ts +1 -1
- package/dist/extension/helpers/vendors.d.ts +1 -0
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
[action-url]: https://github.com/extension-js/extension.js/actions
|
|
7
7
|
[discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=0971fe
|
|
8
8
|
[discord-url]: https://discord.gg/v9h2RgeTSN
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[scorecard-image]: https://img.shields.io/ossf-scorecard/github.com/extension-js/extension.js?label=OpenSSF%20Scorecard&style=flat&color=0971fe
|
|
12
|
-
[scorecard-url]: https://scorecard.dev/viewer/?uri=github.com/extension-js/extension.js
|
|
9
|
+
[bestpractices-image]: https://img.shields.io/cii/level/14662?label=Best%20Practices&style=flat&color=0971fe
|
|
10
|
+
[bestpractices-url]: https://www.bestpractices.dev/projects/14662
|
|
13
11
|
|
|
14
|
-
# Extension.js [![Version][npm-version-image]][npm-version-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] [![Best Practices][bestpractices-image]][bestpractices-url]
|
|
15
13
|
|
|
16
14
|
> The cross-browser extension framework. Build for Chrome, Edge, Firefox, and Safari with no build config required.
|
|
17
15
|
|
|
@@ -25,7 +23,9 @@ npm run dev
|
|
|
25
23
|
|
|
26
24
|
Works with `npm`, `pnpm`, `yarn`, `bun`, and `deno`.
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
The CLI itself runs on Node.js 22.12+, Deno 2.5+, and Bun 1.2+.
|
|
27
|
+
|
|
28
|
+
[Documentation](https://extension.js.org/docs) · [Templates](https://templates.extension.dev/?utm_source=readme&utm_campaign=nav-templates) · [YouTube](https://www.youtube.com/@BrowserExtension) · [Showcase](https://extension.js.org/showcase) · [Blog](https://extension.js.org/blog)
|
|
29
29
|
|
|
30
30
|
## Why Extension.js
|
|
31
31
|
|
|
@@ -173,13 +173,25 @@ npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-sampl
|
|
|
173
173
|
|
|
174
174
|
## Package managers
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
Add Extension.js to a project, or run it once without installing, with the package manager you already use.
|
|
177
177
|
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
| npm
|
|
178
|
+
| Package manager | Add to a project | Run without installing |
|
|
179
|
+
| :-- | :-- | :-- |
|
|
180
|
+
| npm | `npm install extension@latest --save-dev` | `npx extension@latest create my-extension` |
|
|
181
|
+
| pnpm | `pnpm add extension@latest --save-dev` | `pnpm dlx extension@latest create my-extension` |
|
|
182
|
+
| Yarn | `yarn add extension@latest --dev` | `yarn dlx extension@latest create my-extension` |
|
|
183
|
+
| Bun | `bun add --dev extension@latest` | `bunx extension@latest create my-extension` |
|
|
184
|
+
| Deno | `deno add npm:extension@latest` | `deno run -A npm:extension@latest create my-extension` |
|
|
181
185
|
|
|
182
|
-
|
|
186
|
+
Which runtime the CLI then executes on is a separate question, answered below.
|
|
187
|
+
|
|
188
|
+
## Runtimes
|
|
189
|
+
|
|
190
|
+
| | Runtime | Status | Notes |
|
|
191
|
+
| :-: | :-- | :-- | :-- |
|
|
192
|
+
| <img alt="Node.js" src="https://media.extension.land/logos/package-managers/node.svg" width="28"> | Node.js | ✅ 22.12 and newer | The default. `npx`, `pnpm dlx`, `yarn dlx` and `bunx` all land here through the published bin |
|
|
193
|
+
| <picture><source media="(prefers-color-scheme: dark)" srcset="https://media.extension.land/logos/package-managers/deno-dark.svg"><img alt="Deno" src="https://media.extension.land/logos/package-managers/deno.svg" width="28"></picture> | Deno | ✅ 2.5 and newer | `deno run -A npm:extension@latest`. Deno 2.8.0 is refused because it cannot load `node:querystring`, fixed in 2.8.1 |
|
|
194
|
+
| <img alt="Bun" src="https://media.extension.land/logos/package-managers/bun.svg" width="28"> | Bun | ✅ 1.2 and newer | `bunx --bun extension` and `bun run --bun`. Plain `bunx` runs the CLI on Node.js instead, through the published bin |
|
|
183
195
|
|
|
184
196
|
## Community
|
|
185
197
|
|
|
@@ -193,15 +205,6 @@ npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-sampl
|
|
|
193
205
|
Sponsors help the project ship faster releases, better developer experience, and long-term reliability for extension teams.
|
|
194
206
|
|
|
195
207
|
<div align="center">
|
|
196
|
-
<p>
|
|
197
|
-
<a href="https://www.testmuai.com/?utm_medium=sponsor&utm_source=extensionjs" target="_blank" rel="noopener noreferrer">
|
|
198
|
-
<picture>
|
|
199
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://extension.js.org/images/sponsors/testmuai_dark.svg" />
|
|
200
|
-
<source media="(prefers-color-scheme: light)" srcset="https://extension.js.org/images/sponsors/testmuai.svg" />
|
|
201
|
-
<img src="https://extension.js.org/images/sponsors/testmuai.svg" width="220" alt="TestMu AI" />
|
|
202
|
-
</picture>
|
|
203
|
-
</a>
|
|
204
|
-
</p>
|
|
205
208
|
<p>
|
|
206
209
|
<a href="https://extension.dev/?utm_medium=sponsor&utm_source=extensionjs" target="_blank" rel="noopener noreferrer">
|
|
207
210
|
<picture>
|
package/bin/extension.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
|
|
2
3
|
// ██████╗██╗ ██╗
|
|
3
4
|
// ██╔════╝██║ ██║
|
|
4
5
|
// ██║ ██║ ██║
|
|
@@ -38,6 +39,7 @@ if (fs.existsSync(distCjsEntry)) {
|
|
|
38
39
|
console.error(
|
|
39
40
|
'[Extension.js] CLI not built. Run "pnpm --filter extension compile".'
|
|
40
41
|
)
|
|
42
|
+
|
|
41
43
|
process.exit(1)
|
|
42
44
|
}
|
|
43
45
|
} else {
|
package/dist/84.cjs
CHANGED
|
@@ -197,6 +197,7 @@ exports.modules = {
|
|
|
197
197
|
var newtab_override = __webpack_require__("./browsers/browsers-lib/newtab-override.ts");
|
|
198
198
|
var ready_stamp = __webpack_require__("./browsers/browsers-lib/ready-stamp.ts");
|
|
199
199
|
var shared_utils = __webpack_require__("./browsers/browsers-lib/shared-utils.ts");
|
|
200
|
+
var write_json_atomic = __webpack_require__("./browsers/browsers-lib/write-json-atomic.ts");
|
|
200
201
|
var external_ws_ = __webpack_require__("ws");
|
|
201
202
|
var external_ws_default = /*#__PURE__*/ __webpack_require__.n(external_ws_);
|
|
202
203
|
var constants = __webpack_require__("./browsers/browsers-lib/constants.ts");
|
|
@@ -1116,7 +1117,7 @@ exports.modules = {
|
|
|
1116
1117
|
const ready = JSON.parse(external_node_fs_.readFileSync(readyPath, 'utf-8'));
|
|
1117
1118
|
if (ready.cdpPort !== chromeRemoteDebugPort) {
|
|
1118
1119
|
ready.cdpPort = chromeRemoteDebugPort;
|
|
1119
|
-
|
|
1120
|
+
(0, write_json_atomic.Z)(readyPath, ready);
|
|
1120
1121
|
}
|
|
1121
1122
|
}
|
|
1122
1123
|
}
|
package/dist/browsers.cjs
CHANGED
|
@@ -740,16 +740,19 @@ var __webpack_modules__ = {
|
|
|
740
740
|
const tail = outputTail.trim().length ? `\n${pintor__rspack_import_8_default().gray('── last output ──')}\n${outputTail}` : `\n${pintor__rspack_import_8_default().gray('(no output captured)')}`;
|
|
741
741
|
return `${getLoggingPrefix('error')} Safari packaging tool ${pintor__rspack_import_8_default().underline(tool)} failed (${pintor__rspack_import_8_default().red(code)}).${tail}`;
|
|
742
742
|
}
|
|
743
|
+
const SAFARI_KEPT_ON_PURPOSE = {
|
|
744
|
+
world: 'Safari has honored the MAIN world since Safari 18, so the key stays'
|
|
745
|
+
};
|
|
743
746
|
function safariConverterWarnings(warnings) {
|
|
744
|
-
|
|
747
|
+
const kept = warnings.map((line)=>line.trim()).filter((line)=>line in SAFARI_KEPT_ON_PURPOSE);
|
|
748
|
+
const keptLines = kept.map((line)=>` ${pintor__rspack_import_8_default().yellow(line)} ${pintor__rspack_import_8_default().gray(SAFARI_KEPT_ON_PURPOSE[line])}`).join('\n');
|
|
749
|
+
return `${getLoggingPrefix('warn')} safari-web-extension-converter reported ${pintor__rspack_import_8_default().yellow(String(warnings.length))} ${1 === warnings.length ? 'warning' : 'warnings'}, some manifest keys/APIs may not be supported by Safari:\n` + warnings.map((line)=>` ${pintor__rspack_import_8_default().gray('•')} ${line}`).join('\n') + (kept.length ? `\nExtension.js kept ${1 === kept.length ? 'one of these keys' : 'some of these keys'} on purpose:\n${keptLines}` : '');
|
|
745
750
|
}
|
|
746
751
|
function safariDefaultBundleIdNote(bundleId) {
|
|
747
|
-
return `${getLoggingPrefix('
|
|
752
|
+
return `${getLoggingPrefix('info')} Bundle id ${pintor__rspack_import_8_default().gray(bundleId)} (generated, set ${pintor__rspack_import_8_default().blue('--bundle-id')} to own it).`;
|
|
748
753
|
}
|
|
749
|
-
function safariOpenHint(appPath, appName
|
|
750
|
-
|
|
751
|
-
if (signed) return launch + `Then turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
|
|
752
|
-
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.`;
|
|
754
|
+
function safariOpenHint(appPath, appName) {
|
|
755
|
+
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 turn on ${pintor__rspack_import_8_default().yellow(appName)} in Safari ▸ Settings ▸ Extensions.`;
|
|
753
756
|
}
|
|
754
757
|
function safariDryRunNotBuilding() {
|
|
755
758
|
return `${getLoggingPrefix('info')} Dry run: skip the Safari app build.`;
|
|
@@ -761,17 +764,21 @@ var __webpack_modules__ = {
|
|
|
761
764
|
return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
|
|
762
765
|
}
|
|
763
766
|
function safariNextSteps(appName, signed) {
|
|
764
|
-
|
|
765
|
-
|
|
767
|
+
const steps = `${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`;
|
|
768
|
+
if (signed) return steps + ` ${pintor__rspack_import_8_default().gray('→')} Signed with your team id, so the identity is stable for distribution.`;
|
|
769
|
+
return steps + ` ${pintor__rspack_import_8_default().gray('→')} Ad-hoc signed, so it stays enabled across restarts.`;
|
|
766
770
|
}
|
|
767
771
|
function safariRegistered(appName) {
|
|
768
772
|
return `${getLoggingPrefix('success')} Safari recognizes ${pintor__rspack_import_8_default().yellow(appName)}, finish enabling it with the steps above.`;
|
|
769
773
|
}
|
|
774
|
+
function safariPidUnresolved(appName) {
|
|
775
|
+
return `${getLoggingPrefix('warn')} Opened ${pintor__rspack_import_8_default().yellow(appName)} but could not find its process id.\nThe session's ready.json names the app and the extension without a ${pintor__rspack_import_8_default().gray('browserPid')}.`;
|
|
776
|
+
}
|
|
770
777
|
function safariNotYetRegistered(appName) {
|
|
771
778
|
return `${getLoggingPrefix('info')} Safari hasn't picked up ${pintor__rspack_import_8_default().yellow(appName)} yet.\nOpen the app once, then check Safari ▸ Settings ▸ Extensions.`;
|
|
772
779
|
}
|
|
773
780
|
function safariRebuilt(appName) {
|
|
774
|
-
return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().yellow(appName)}
|
|
781
|
+
return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().yellow(appName)}.`;
|
|
775
782
|
}
|
|
776
783
|
function safariProjectStale() {
|
|
777
784
|
return `${getLoggingPrefix('info')} Regenerating the Xcode project, manifest.json or identity options changed since it was generated.`;
|
|
@@ -1028,6 +1035,7 @@ var __webpack_modules__ = {
|
|
|
1028
1035
|
jR: ()=>safariBuilding,
|
|
1029
1036
|
jc: ()=>safariProjectStale,
|
|
1030
1037
|
jk: ()=>requireGeckoBinaryForGeckoBased,
|
|
1038
|
+
jn: ()=>safariPidUnresolved,
|
|
1031
1039
|
kK: ()=>preferringSystemBrowserOverSnapshot,
|
|
1032
1040
|
l9: ()=>parsingPacketError,
|
|
1033
1041
|
lO: ()=>firefoxDryRunArgs,
|
|
@@ -1400,6 +1408,7 @@ var __webpack_modules__ = {
|
|
|
1400
1408
|
"./browsers/browsers-lib/ready-stamp.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1401
1409
|
var node_fs__rspack_import_0 = __webpack_require__("node:fs");
|
|
1402
1410
|
var node_path__rspack_import_1 = __webpack_require__("node:path");
|
|
1411
|
+
var _write_json_atomic__rspack_import_2 = __webpack_require__("./browsers/browsers-lib/write-json-atomic.ts");
|
|
1403
1412
|
function readyPathFor(extensionOutputPath) {
|
|
1404
1413
|
return node_path__rspack_import_1.join(node_path__rspack_import_1.dirname(extensionOutputPath), 'extension-js', node_path__rspack_import_1.basename(extensionOutputPath), 'ready.json');
|
|
1405
1414
|
}
|
|
@@ -1411,7 +1420,7 @@ var __webpack_modules__ = {
|
|
|
1411
1420
|
const ready = JSON.parse(node_fs__rspack_import_0.readFileSync(readyPath, 'utf-8'));
|
|
1412
1421
|
if (ready.rdpPort === rdpPort) return;
|
|
1413
1422
|
ready.rdpPort = rdpPort;
|
|
1414
|
-
|
|
1423
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1415
1424
|
} catch {}
|
|
1416
1425
|
}
|
|
1417
1426
|
function stampReadyBrowserLaunch(extensionOutputPath, details) {
|
|
@@ -1429,7 +1438,7 @@ var __webpack_modules__ = {
|
|
|
1429
1438
|
if (binary) ready.binary = binary;
|
|
1430
1439
|
const provenance = String(details?.binaryProvenance || '').trim();
|
|
1431
1440
|
if (provenance) ready.binaryProvenance = provenance;
|
|
1432
|
-
|
|
1441
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1433
1442
|
} catch {}
|
|
1434
1443
|
}
|
|
1435
1444
|
function stampReadyExtensionId(extensionOutputPath, extensionId) {
|
|
@@ -1441,7 +1450,7 @@ var __webpack_modules__ = {
|
|
|
1441
1450
|
const ready = JSON.parse(node_fs__rspack_import_0.readFileSync(readyPath, 'utf-8'));
|
|
1442
1451
|
if (ready.extensionId === id) return;
|
|
1443
1452
|
ready.extensionId = id;
|
|
1444
|
-
|
|
1453
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1445
1454
|
} catch {}
|
|
1446
1455
|
}
|
|
1447
1456
|
function stampReadyExtensionLoadRefused(extensionOutputPath, reason) {
|
|
@@ -1456,7 +1465,7 @@ var __webpack_modules__ = {
|
|
|
1456
1465
|
ready.message = `${browserLabel.charAt(0).toUpperCase() + browserLabel.slice(1)} refused to load the extension at ${extensionOutputPath}${reason ? `: ${reason}` : ''}`;
|
|
1457
1466
|
ready.extensionLoadRefusedAt = new Date().toISOString();
|
|
1458
1467
|
if (reason) ready.extensionLoadRefusedReason = reason;
|
|
1459
|
-
|
|
1468
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1460
1469
|
} catch {}
|
|
1461
1470
|
}
|
|
1462
1471
|
function stampReadyProfileLocked(extensionOutputPath, details) {
|
|
@@ -1470,7 +1479,7 @@ var __webpack_modules__ = {
|
|
|
1470
1479
|
ready.message = String(details?.message || '').trim() || 'the browser profile is already in use by another session';
|
|
1471
1480
|
ready.profileLockedAt = new Date().toISOString();
|
|
1472
1481
|
if (details?.owner) ready.profileLockOwner = details.owner;
|
|
1473
|
-
|
|
1482
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1474
1483
|
} catch {}
|
|
1475
1484
|
}
|
|
1476
1485
|
function stampReadyBrowserExited(extensionOutputPath, code) {
|
|
@@ -1486,7 +1495,7 @@ var __webpack_modules__ = {
|
|
|
1486
1495
|
ready.code = 'browser_exited';
|
|
1487
1496
|
ready.message = `the ${ready.browser || 'browser'} process exited (code ${code ?? 'unknown'}); nothing is running`;
|
|
1488
1497
|
}
|
|
1489
|
-
|
|
1498
|
+
(0, _write_json_atomic__rspack_import_2.Z)(readyPath, ready);
|
|
1490
1499
|
} catch {}
|
|
1491
1500
|
}
|
|
1492
1501
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -1949,6 +1958,27 @@ var __webpack_modules__ = {
|
|
|
1949
1958
|
yO: ()=>probeChromiumBinaryVersion
|
|
1950
1959
|
});
|
|
1951
1960
|
},
|
|
1961
|
+
"./browsers/browsers-lib/write-json-atomic.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1962
|
+
var node_fs__rspack_import_0 = __webpack_require__("node:fs");
|
|
1963
|
+
function writeJsonAtomic(filePath, value) {
|
|
1964
|
+
const tmpPath = `${filePath}.tmp-${process.pid}`;
|
|
1965
|
+
try {
|
|
1966
|
+
node_fs__rspack_import_0.writeFileSync(tmpPath, JSON.stringify(value, null, 2), 'utf-8');
|
|
1967
|
+
node_fs__rspack_import_0.renameSync(tmpPath, filePath);
|
|
1968
|
+
return true;
|
|
1969
|
+
} catch {
|
|
1970
|
+
try {
|
|
1971
|
+
node_fs__rspack_import_0.rmSync(tmpPath, {
|
|
1972
|
+
force: true
|
|
1973
|
+
});
|
|
1974
|
+
} catch {}
|
|
1975
|
+
return false;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
1979
|
+
Z: ()=>writeJsonAtomic
|
|
1980
|
+
});
|
|
1981
|
+
},
|
|
1952
1982
|
"./browsers/browsers-lib/wsl-support.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1953
1983
|
__webpack_require__.d(__webpack_exports__, {
|
|
1954
1984
|
qc: ()=>external_wsl_support_namespaceObject.hasGuiDisplay,
|
|
@@ -5812,7 +5842,6 @@ var __webpack_modules__ = {
|
|
|
5812
5842
|
QW: ()=>safariBuildPreflight,
|
|
5813
5843
|
iF: ()=>safariPreflightError
|
|
5814
5844
|
});
|
|
5815
|
-
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
5816
5845
|
var external_node_fs_ = __webpack_require__("node:fs");
|
|
5817
5846
|
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
5818
5847
|
var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
|
|
@@ -5826,6 +5855,7 @@ var __webpack_modules__ = {
|
|
|
5826
5855
|
(0, messaging._w)(messages.Aj(xcodebuildCmd));
|
|
5827
5856
|
}
|
|
5828
5857
|
var safari_config = __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
|
|
5858
|
+
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
5829
5859
|
function isMacOS() {
|
|
5830
5860
|
return 'darwin' === process.platform;
|
|
5831
5861
|
}
|
|
@@ -5883,20 +5913,6 @@ var __webpack_modules__ = {
|
|
|
5883
5913
|
ok: Boolean(converter && xcodebuild)
|
|
5884
5914
|
};
|
|
5885
5915
|
}
|
|
5886
|
-
function fallbackLogger() {
|
|
5887
|
-
return {
|
|
5888
|
-
info: (...a)=>(0, messaging._w)(...a),
|
|
5889
|
-
warn: (...a)=>(0, messaging.mR)(...a),
|
|
5890
|
-
error: (...a)=>(0, messaging.Gg)(...a),
|
|
5891
|
-
debug: (...a)=>console?.debug?.(...a)
|
|
5892
|
-
};
|
|
5893
|
-
}
|
|
5894
|
-
function isTestEnv() {
|
|
5895
|
-
return Boolean(process.env.VITEST || process.env.VITEST_WORKER_ID);
|
|
5896
|
-
}
|
|
5897
|
-
function delay(ms) {
|
|
5898
|
-
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
5899
|
-
}
|
|
5900
5916
|
const TOOL_TAIL_LINES = 50;
|
|
5901
5917
|
const TOOL_TAIL_BYTES = 8192;
|
|
5902
5918
|
function toolOutputTail(output) {
|
|
@@ -5935,18 +5951,85 @@ var __webpack_modules__ = {
|
|
|
5935
5951
|
}));
|
|
5936
5952
|
});
|
|
5937
5953
|
}
|
|
5954
|
+
async function resolvePidForBundle(bundleId) {
|
|
5955
|
+
for(let attempt = 0; attempt < 10; attempt += 1){
|
|
5956
|
+
const pid = await new Promise((resolve)=>{
|
|
5957
|
+
const child = (0, external_node_child_process_.spawn)("osascript", [
|
|
5958
|
+
'-e',
|
|
5959
|
+
`tell application "System Events" to get unix id of first process whose bundle identifier is "${bundleId}"`
|
|
5960
|
+
]);
|
|
5961
|
+
let out = '';
|
|
5962
|
+
child.stdout.on('data', (d)=>out += String(d));
|
|
5963
|
+
child.on('error', ()=>resolve(null));
|
|
5964
|
+
child.on('close', ()=>{
|
|
5965
|
+
const n = Number(String(out).trim());
|
|
5966
|
+
resolve(Number.isFinite(n) && n > 0 ? n : null);
|
|
5967
|
+
});
|
|
5968
|
+
});
|
|
5969
|
+
if (pid) return pid;
|
|
5970
|
+
await new Promise((r)=>setTimeout(r, 500));
|
|
5971
|
+
}
|
|
5972
|
+
return null;
|
|
5973
|
+
}
|
|
5974
|
+
function createSafariTools() {
|
|
5975
|
+
return {
|
|
5976
|
+
detectToolchain: ()=>detectSafariToolchain(),
|
|
5977
|
+
runConverter: (args)=>runTool('xcrun', args),
|
|
5978
|
+
runXcodebuild: (args)=>runTool('xcodebuild', args),
|
|
5979
|
+
openApp: (target)=>runTool('open', [
|
|
5980
|
+
target
|
|
5981
|
+
]),
|
|
5982
|
+
openSafari: (binary)=>runTool('open', [
|
|
5983
|
+
'-a',
|
|
5984
|
+
binary
|
|
5985
|
+
]),
|
|
5986
|
+
resolvePid: (bundleId)=>resolvePidForBundle(bundleId),
|
|
5987
|
+
pluginkitList: async ()=>{
|
|
5988
|
+
const { ok, output } = await runTool('pluginkit', [
|
|
5989
|
+
'-m'
|
|
5990
|
+
], {
|
|
5991
|
+
quiet: true
|
|
5992
|
+
});
|
|
5993
|
+
return ok ? output : '';
|
|
5994
|
+
}
|
|
5995
|
+
};
|
|
5996
|
+
}
|
|
5997
|
+
function fallbackLogger() {
|
|
5998
|
+
return {
|
|
5999
|
+
info: (...a)=>(0, messaging._w)(...a),
|
|
6000
|
+
warn: (...a)=>(0, messaging.mR)(...a),
|
|
6001
|
+
error: (...a)=>(0, messaging.Gg)(...a),
|
|
6002
|
+
debug: (...a)=>console?.debug?.(...a)
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
function delay(ms) {
|
|
6006
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
6007
|
+
}
|
|
5938
6008
|
function converterWarnings(output) {
|
|
5939
|
-
|
|
6009
|
+
const lines = output.split(/\r?\n/);
|
|
6010
|
+
const collected = [];
|
|
6011
|
+
let inWarning = false;
|
|
6012
|
+
for (const line of lines){
|
|
6013
|
+
const trimmed = line.trim();
|
|
6014
|
+
if (/warning/i.test(line)) {
|
|
6015
|
+
inWarning = true;
|
|
6016
|
+
if (trimmed.length > 0) collected.push(trimmed);
|
|
6017
|
+
continue;
|
|
6018
|
+
}
|
|
6019
|
+
const isContinuation = inWarning && /^\s/.test(line) && trimmed.length > 0;
|
|
6020
|
+
if (isContinuation) {
|
|
6021
|
+
collected.push(trimmed);
|
|
6022
|
+
continue;
|
|
6023
|
+
}
|
|
6024
|
+
inWarning = false;
|
|
6025
|
+
}
|
|
6026
|
+
return collected;
|
|
5940
6027
|
}
|
|
5941
|
-
async function confirmRegisteredWithSafari(bundleIdentifier) {
|
|
6028
|
+
async function confirmRegisteredWithSafari(tools, bundleIdentifier) {
|
|
5942
6029
|
const needle = `${bundleIdentifier}.Extension`;
|
|
5943
6030
|
for(let attempt = 0; attempt < 6; attempt += 1){
|
|
5944
|
-
const
|
|
5945
|
-
|
|
5946
|
-
], {
|
|
5947
|
-
quiet: true
|
|
5948
|
-
});
|
|
5949
|
-
if (ok && output.includes(needle)) return true;
|
|
6031
|
+
const listing = await tools.pluginkitList();
|
|
6032
|
+
if (listing.includes(needle)) return true;
|
|
5950
6033
|
await delay(800);
|
|
5951
6034
|
}
|
|
5952
6035
|
return false;
|
|
@@ -5961,6 +6044,10 @@ var __webpack_modules__ = {
|
|
|
5961
6044
|
macOsOnly: config.macOsOnly
|
|
5962
6045
|
};
|
|
5963
6046
|
}
|
|
6047
|
+
function completePackage(config, logger, mode) {
|
|
6048
|
+
if ('full' === mode && config.bundleIdDerived) logger.info?.(messages.$q(config.bundleIdentifier));
|
|
6049
|
+
return describePackage(config);
|
|
6050
|
+
}
|
|
5964
6051
|
function safariPreflightError() {
|
|
5965
6052
|
const tc = detectSafariToolchain();
|
|
5966
6053
|
if (!tc.platformOk) return messages.G3(process.platform);
|
|
@@ -5984,26 +6071,6 @@ var __webpack_modules__ = {
|
|
|
5984
6071
|
severity: 'ok'
|
|
5985
6072
|
};
|
|
5986
6073
|
}
|
|
5987
|
-
async function resolvePidForBundle(bundleId) {
|
|
5988
|
-
for(let attempt = 0; attempt < 10; attempt += 1){
|
|
5989
|
-
const pid = await new Promise((resolve)=>{
|
|
5990
|
-
const child = (0, external_node_child_process_.spawn)("osascript", [
|
|
5991
|
-
'-e',
|
|
5992
|
-
`tell application "System Events" to get unix id of first process whose bundle identifier is "${bundleId}"`
|
|
5993
|
-
]);
|
|
5994
|
-
let out = '';
|
|
5995
|
-
child.stdout.on('data', (d)=>out += String(d));
|
|
5996
|
-
child.on('error', ()=>resolve(null));
|
|
5997
|
-
child.on('close', ()=>{
|
|
5998
|
-
const n = Number(String(out).trim());
|
|
5999
|
-
resolve(Number.isFinite(n) && n > 0 ? n : null);
|
|
6000
|
-
});
|
|
6001
|
-
});
|
|
6002
|
-
if (pid) return pid;
|
|
6003
|
-
await new Promise((r)=>setTimeout(r, 500));
|
|
6004
|
-
}
|
|
6005
|
-
return null;
|
|
6006
|
-
}
|
|
6007
6074
|
async function announceSafariDevSession(host, config, appPath) {
|
|
6008
6075
|
try {
|
|
6009
6076
|
await (0, banner.ai)({
|
|
@@ -6019,16 +6086,16 @@ var __webpack_modules__ = {
|
|
|
6019
6086
|
} catch {}
|
|
6020
6087
|
}
|
|
6021
6088
|
async function runSafariPipeline(compilation, host, logger, mode) {
|
|
6089
|
+
const tools = host.tools || createSafariTools();
|
|
6022
6090
|
const config = (0, safari_config.F7)(compilation, host);
|
|
6023
6091
|
const converterArgs = (0, safari_config.w7)(config);
|
|
6024
6092
|
const xcodebuildArgs = (0, safari_config.vx)(config);
|
|
6025
6093
|
const isSigned = Boolean(config.developmentTeam);
|
|
6026
|
-
if (
|
|
6027
|
-
if (host.dryRun || isTestEnv()) {
|
|
6094
|
+
if (host.dryRun) {
|
|
6028
6095
|
logSafariDryRun(`xcrun ${converterArgs.join(' ')}`, `xcodebuild ${xcodebuildArgs.join(' ')}`);
|
|
6029
|
-
return
|
|
6096
|
+
return completePackage(config, logger, mode);
|
|
6030
6097
|
}
|
|
6031
|
-
const toolchain =
|
|
6098
|
+
const toolchain = tools.detectToolchain();
|
|
6032
6099
|
if (!toolchain.platformOk) {
|
|
6033
6100
|
logger.warn?.(messages.G3(process.platform));
|
|
6034
6101
|
return describePackage(config);
|
|
@@ -6052,7 +6119,7 @@ var __webpack_modules__ = {
|
|
|
6052
6119
|
}
|
|
6053
6120
|
const { saved, restore } = (0, safari_config._D)(config);
|
|
6054
6121
|
logger.info?.(messages.uK(config.extensionDir));
|
|
6055
|
-
const converted = await
|
|
6122
|
+
const converted = await tools.runConverter(converterArgs);
|
|
6056
6123
|
if (!converted.ok) {
|
|
6057
6124
|
const tail = toolOutputTail(converted.output);
|
|
6058
6125
|
logger.error?.(messages.A('safari-web-extension-converter', converted.code, tail));
|
|
@@ -6067,9 +6134,9 @@ var __webpack_modules__ = {
|
|
|
6067
6134
|
if (preservedKeys.length > 0) logger.info?.(messages.oB(preservedKeys));
|
|
6068
6135
|
(0, safari_config.x7)(config);
|
|
6069
6136
|
logger.info?.(messages.l_(config.projectLocation));
|
|
6070
|
-
} else logger.info?.(messages.oM());
|
|
6137
|
+
} else if ('full' === mode) logger.info?.(messages.oM());
|
|
6071
6138
|
if ('full' === mode) logger.info?.(messages.jR((0, safari_config.aD)(config)));
|
|
6072
|
-
const built = await
|
|
6139
|
+
const built = await tools.runXcodebuild(xcodebuildArgs);
|
|
6073
6140
|
if (!built.ok) {
|
|
6074
6141
|
const tail = toolOutputTail(built.output);
|
|
6075
6142
|
logger.error?.(messages.A('xcodebuild', built.code, tail));
|
|
@@ -6082,32 +6149,28 @@ var __webpack_modules__ = {
|
|
|
6082
6149
|
}
|
|
6083
6150
|
logger.info?.(messages.Rl(appPath));
|
|
6084
6151
|
if (!config.open) {
|
|
6085
|
-
logger.info?.(messages.aO(appPath, config.appName
|
|
6152
|
+
logger.info?.(messages.aO(appPath, config.appName));
|
|
6086
6153
|
if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
|
|
6087
|
-
return
|
|
6154
|
+
return completePackage(config, logger, mode);
|
|
6088
6155
|
}
|
|
6089
6156
|
const target = external_node_fs_.existsSync(appPath) ? appPath : (0, safari_config.Gi)(config);
|
|
6090
6157
|
logger.info?.(messages.fw(target));
|
|
6091
|
-
await
|
|
6092
|
-
|
|
6093
|
-
]);
|
|
6094
|
-
if (config.safariBinary) await runTool('open', [
|
|
6095
|
-
'-a',
|
|
6096
|
-
config.safariBinary
|
|
6097
|
-
]);
|
|
6158
|
+
await tools.openApp(target);
|
|
6159
|
+
if (config.safariBinary) await tools.openSafari(config.safariBinary);
|
|
6098
6160
|
const raisedBundleId = config.safariBinary ? 'com.apple.Safari' : config.bundleIdentifier;
|
|
6099
|
-
const browserPid = await
|
|
6100
|
-
|
|
6101
|
-
browserPid,
|
|
6161
|
+
const browserPid = await tools.resolvePid(raisedBundleId);
|
|
6162
|
+
(0, ready_stamp.M)(config.extensionDir, {
|
|
6163
|
+
browserPid: browserPid || void 0,
|
|
6102
6164
|
binary: config.safariBinary || appPath,
|
|
6103
6165
|
binaryProvenance: config.safariBinary ? 'pinned' : 'system',
|
|
6104
6166
|
extensionId: `${config.bundleIdentifier}.Extension`
|
|
6105
6167
|
});
|
|
6168
|
+
if (!browserPid) logger.warn?.(messages.jn(config.appName));
|
|
6106
6169
|
logger.info?.(messages.fO(config.appName, isSigned));
|
|
6107
|
-
if (await confirmRegisteredWithSafari(config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
|
|
6170
|
+
if (await confirmRegisteredWithSafari(tools, config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
|
|
6108
6171
|
else logger.info?.(messages.qY(config.appName));
|
|
6109
6172
|
if (host.announceDevReady) await announceSafariDevSession(host, config, appPath);
|
|
6110
|
-
return
|
|
6173
|
+
return completePackage(config, logger, mode);
|
|
6111
6174
|
}
|
|
6112
6175
|
async function packageSafariExtension(host, outputPath, logger, mode = 'full') {
|
|
6113
6176
|
const compilation = {
|
|
@@ -6227,36 +6290,56 @@ var __webpack_modules__ = {
|
|
|
6227
6290
|
function manifestFingerprintPath(config) {
|
|
6228
6291
|
return node_path__rspack_import_1.join(config.projectLocation, '.manifest-fingerprint');
|
|
6229
6292
|
}
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
if ('object' != typeof obj) return JSON.stringify(obj);
|
|
6233
|
-
if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(',')}]`;
|
|
6234
|
-
const keys = Object.keys(obj).sort();
|
|
6235
|
-
return `{${keys.map((k)=>`${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',')}}`;
|
|
6236
|
-
}
|
|
6237
|
-
function readManifestRaw(extensionDir) {
|
|
6293
|
+
const HOT_UPDATE_DIR = 'hot';
|
|
6294
|
+
function topLevelEntries(extensionDir) {
|
|
6238
6295
|
try {
|
|
6239
|
-
return node_fs__rspack_import_0.
|
|
6296
|
+
return node_fs__rspack_import_0.readdirSync(extensionDir).filter((entry)=>entry !== HOT_UPDATE_DIR).sort();
|
|
6240
6297
|
} catch {
|
|
6241
|
-
return
|
|
6298
|
+
return [];
|
|
6242
6299
|
}
|
|
6243
6300
|
}
|
|
6244
|
-
function
|
|
6301
|
+
function iconsFingerprint(extensionDir) {
|
|
6245
6302
|
try {
|
|
6246
|
-
|
|
6303
|
+
const raw = node_fs__rspack_import_0.readFileSync(node_path__rspack_import_1.join(extensionDir, 'manifest.json'), 'utf8');
|
|
6304
|
+
const icons = JSON.parse(raw).icons;
|
|
6305
|
+
if (!icons || 'object' != typeof icons) return '';
|
|
6306
|
+
return Object.keys(icons).sort().map((size)=>`${size}:${String(icons[size])}`).join(',');
|
|
6247
6307
|
} catch {
|
|
6248
|
-
return
|
|
6308
|
+
return '';
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6311
|
+
function asRecord(value) {
|
|
6312
|
+
return value && 'object' == typeof value && !Array.isArray(value) ? value : {};
|
|
6313
|
+
}
|
|
6314
|
+
function judgedManifestSurface(extensionDir) {
|
|
6315
|
+
const manifest = readManifest(extensionDir);
|
|
6316
|
+
const parts = [
|
|
6317
|
+
Object.keys(manifest).sort().join(',')
|
|
6318
|
+
];
|
|
6319
|
+
for (const listName of [
|
|
6320
|
+
'permissions',
|
|
6321
|
+
'optional_permissions'
|
|
6322
|
+
]){
|
|
6323
|
+
const list = manifest[listName];
|
|
6324
|
+
const names = Array.isArray(list) ? list.filter((entry)=>'string' == typeof entry).sort() : [];
|
|
6325
|
+
parts.push(`${listName}:${names.join(',')}`);
|
|
6249
6326
|
}
|
|
6327
|
+
const contentScripts = manifest.content_scripts;
|
|
6328
|
+
if (Array.isArray(contentScripts)) parts.push(contentScripts.map((entry)=>Object.keys(asRecord(entry)).sort().join('+')).join(';'));
|
|
6329
|
+
parts.push(Object.keys(asRecord(manifest.options_ui)).sort().join(','));
|
|
6330
|
+
return parts.join('|');
|
|
6250
6331
|
}
|
|
6251
6332
|
function composeProjectFingerprint(config) {
|
|
6252
6333
|
return JSON.stringify({
|
|
6253
|
-
v:
|
|
6334
|
+
v: 4,
|
|
6254
6335
|
identity: {
|
|
6255
6336
|
appName: config.appName,
|
|
6256
6337
|
bundleId: config.bundleIdentifier,
|
|
6257
6338
|
macOsOnly: config.macOsOnly
|
|
6258
6339
|
},
|
|
6259
|
-
|
|
6340
|
+
entries: topLevelEntries(config.extensionDir),
|
|
6341
|
+
icons: iconsFingerprint(config.extensionDir),
|
|
6342
|
+
judged: judgedManifestSurface(config.extensionDir)
|
|
6260
6343
|
});
|
|
6261
6344
|
}
|
|
6262
6345
|
function saveManifestFingerprint(config) {
|
|
@@ -6339,7 +6422,7 @@ var __webpack_modules__ = {
|
|
|
6339
6422
|
return Object.fromEntries(Object.entries(input).filter(([, value])=>void 0 !== value));
|
|
6340
6423
|
}
|
|
6341
6424
|
function createSafariPackager(options = {}) {
|
|
6342
|
-
const { browser = 'safari', noOpen = true, dryRun = false, logger, ...identity } = options;
|
|
6425
|
+
const { browser = 'safari', noOpen = true, dryRun = false, logger, tools, ...identity } = options;
|
|
6343
6426
|
return async (distPath, mode = 'full', overrides)=>await (0, _safari_launch__rspack_import_0.Ah)({
|
|
6344
6427
|
extension: [
|
|
6345
6428
|
distPath
|
|
@@ -6347,6 +6430,7 @@ var __webpack_modules__ = {
|
|
|
6347
6430
|
browser,
|
|
6348
6431
|
noOpen,
|
|
6349
6432
|
dryRun,
|
|
6433
|
+
tools,
|
|
6350
6434
|
...withoutUndefined(identity),
|
|
6351
6435
|
...withoutUndefined(overrides)
|
|
6352
6436
|
}, distPath, logger, mode);
|