extension 4.1.14 → 4.1.16
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/browsers.cjs +107 -1
- package/dist/cli.cjs +287 -16
- package/dist/extension/browsers/browsers-lib/first-run-install.d.ts +4 -0
- package/dist/extension/browsers/browsers-lib/messages.d.ts +4 -0
- package/dist/extension/helpers/browser-install-outcome.d.ts +10 -0
- package/dist/extension/helpers/no-browser.d.ts +2 -0
- package/dist/extension/helpers/telemetry-cli.d.ts +15 -2
- package/dist/extension/helpers/telemetry-signals.d.ts +14 -0
- package/dist/extension/helpers/telemetry.d.ts +4 -0
- package/dist/extension/helpers/template-catalog.d.ts +1 -1
- package/dist/extension/helpers/template-corpus.generated.d.ts +1 -1
- package/package.json +4 -4
package/dist/browsers.cjs
CHANGED
|
@@ -891,6 +891,20 @@ var __webpack_modules__ = {
|
|
|
891
891
|
function rdpInvalidRequestPayload() {
|
|
892
892
|
return `${getLoggingPrefix('error')} Received an unreadable Firefox remote debugging message.\nThe debugging connection is out of sync with the browser, usually after a crash or an abrupt reload.\nRestart the dev session.\nIf it repeats, report it with your Firefox version.`;
|
|
893
893
|
}
|
|
894
|
+
function firstRunInstallOffer(browser) {
|
|
895
|
+
const name = managedBrowserDisplayName(browser);
|
|
896
|
+
return `${getLoggingPrefix('info')} ${name} is not installed yet.\nExtension.js runs your extension in a version-pinned browser with an isolated profile, so it never touches the browser you use every day.\n${pintor__rspack_import_8_default().gray('NO DOWNLOAD')} ${pintor__rspack_import_8_default().blue('--browser=edge')} or ${pintor__rspack_import_8_default().blue('--browser=brave')} use a browser already on this machine, and ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} pins any binary, including your own Chrome.`;
|
|
897
|
+
}
|
|
898
|
+
function firstRunInstallQuestion(browser) {
|
|
899
|
+
const name = managedBrowserDisplayName(browser);
|
|
900
|
+
return `${getLoggingPrefix('info')} Download ${name} now? ${pintor__rspack_import_8_default().gray('[Y/n]')} `;
|
|
901
|
+
}
|
|
902
|
+
function firstRunInstallDeclined(browser) {
|
|
903
|
+
return `${getLoggingPrefix('info')} Skipped the download.\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${browser}`)} when you want it, or pass one of the no-download options above.`;
|
|
904
|
+
}
|
|
905
|
+
function firstRunInstallFailed(browser, reason) {
|
|
906
|
+
return `${getLoggingPrefix('warn')} The download did not finish.\n${pintor__rspack_import_8_default().gray('REASON')} ${reason}\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${browser}`)} to see the full output.`;
|
|
907
|
+
}
|
|
894
908
|
__webpack_require__.d(__webpack_exports__, {
|
|
895
909
|
$q: ()=>safariDefaultBundleIdNote,
|
|
896
910
|
$w: ()=>bestEffortBannerPrintFailed,
|
|
@@ -909,6 +923,7 @@ var __webpack_modules__ = {
|
|
|
909
923
|
F1: ()=>cdpClientBrowserConnectionEstablished,
|
|
910
924
|
F4: ()=>enhancedProcessManagementUncaughtException,
|
|
911
925
|
FF: ()=>cdpClientFoundTargets,
|
|
926
|
+
FW: ()=>firstRunInstallQuestion,
|
|
912
927
|
Fm: ()=>connectionClosedError,
|
|
913
928
|
G3: ()=>safariRequiresMacOS,
|
|
914
929
|
GB: ()=>waitingForBrowserDebugger,
|
|
@@ -928,6 +943,7 @@ var __webpack_modules__ = {
|
|
|
928
943
|
MS: ()=>errorConnectingToBrowser,
|
|
929
944
|
N4: ()=>enhancedProcessManagementUnhandledRejection,
|
|
930
945
|
NO: ()=>mv3BackgroundScriptsNotSupportedByChromium,
|
|
946
|
+
NT: ()=>firstRunInstallDeclined,
|
|
931
947
|
Nk: ()=>chromiumDryRunNotLaunching,
|
|
932
948
|
Q0: ()=>chromiumDryRunBinary,
|
|
933
949
|
Rl: ()=>safariBuilt,
|
|
@@ -959,6 +975,7 @@ var __webpack_modules__ = {
|
|
|
959
975
|
fR: ()=>cdpClientConnectionError,
|
|
960
976
|
fd: ()=>safariRegistered,
|
|
961
977
|
fw: ()=>safariOpening,
|
|
978
|
+
gX: ()=>firstRunInstallFailed,
|
|
962
979
|
hE: ()=>cdpClientConnectionClosed,
|
|
963
980
|
io: ()=>emptyLine,
|
|
964
981
|
jP: ()=>rdpInvalidRequestPayload,
|
|
@@ -969,6 +986,7 @@ var __webpack_modules__ = {
|
|
|
969
986
|
l9: ()=>parsingPacketError,
|
|
970
987
|
lO: ()=>firefoxDryRunArgs,
|
|
971
988
|
l_: ()=>safariConverted,
|
|
989
|
+
lk: ()=>firstRunInstallOffer,
|
|
972
990
|
ne: ()=>requireChromiumBinaryForChromiumBased,
|
|
973
991
|
nn: ()=>chromeProcessExited,
|
|
974
992
|
oB: ()=>safariSettingsPreserved,
|
|
@@ -2196,6 +2214,63 @@ var __webpack_modules__ = {
|
|
|
2196
2214
|
var external_yandex_location_default = /*#__PURE__*/ __webpack_require__.n(external_yandex_location_namespaceObject);
|
|
2197
2215
|
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
2198
2216
|
var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
|
|
2217
|
+
const external_node_readline_namespaceObject = require("node:readline");
|
|
2218
|
+
var external_node_readline_default = /*#__PURE__*/ __webpack_require__.n(external_node_readline_namespaceObject);
|
|
2219
|
+
var browser_install_outcome = __webpack_require__("./helpers/browser-install-outcome.ts");
|
|
2220
|
+
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
2221
|
+
function isCI() {
|
|
2222
|
+
const v = process.env;
|
|
2223
|
+
return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
|
|
2224
|
+
}
|
|
2225
|
+
function canPromptForInstall() {
|
|
2226
|
+
if (process.env.VITEST || process.env.VITEST_WORKER_ID) return false;
|
|
2227
|
+
if (process.env.EXTENSION_NO_INSTALL_PROMPT) return false;
|
|
2228
|
+
if (isCI()) return false;
|
|
2229
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
2230
|
+
}
|
|
2231
|
+
function askToInstall(question) {
|
|
2232
|
+
return new Promise((resolve)=>{
|
|
2233
|
+
const rl = external_node_readline_default().createInterface({
|
|
2234
|
+
input: process.stdin,
|
|
2235
|
+
output: process.stdout
|
|
2236
|
+
});
|
|
2237
|
+
const finish = (answer)=>{
|
|
2238
|
+
try {
|
|
2239
|
+
rl.close();
|
|
2240
|
+
} catch {}
|
|
2241
|
+
resolve(answer);
|
|
2242
|
+
};
|
|
2243
|
+
rl.question(question, (answer)=>{
|
|
2244
|
+
const normalized = String(answer || '').trim().toLowerCase();
|
|
2245
|
+
finish('n' !== normalized && 'no' !== normalized);
|
|
2246
|
+
});
|
|
2247
|
+
rl.on('SIGINT', ()=>finish(false));
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
async function offerManagedInstall(target) {
|
|
2251
|
+
if (!canPromptForInstall()) return false;
|
|
2252
|
+
(0, messaging._w)(messages.lk(target));
|
|
2253
|
+
(0, browser_install_outcome.rQ)('offered', target);
|
|
2254
|
+
const accepted = await askToInstall(messages.FW(target));
|
|
2255
|
+
if (!accepted) {
|
|
2256
|
+
(0, browser_install_outcome.rQ)('declined', target);
|
|
2257
|
+
(0, messaging._w)(messages.NT(target));
|
|
2258
|
+
return false;
|
|
2259
|
+
}
|
|
2260
|
+
const startedAt = Date.now();
|
|
2261
|
+
try {
|
|
2262
|
+
const { extensionInstall } = await import("extension-install");
|
|
2263
|
+
await extensionInstall({
|
|
2264
|
+
browser: target
|
|
2265
|
+
});
|
|
2266
|
+
(0, browser_install_outcome.rQ)('accepted', target, (Date.now() - startedAt) / 1000);
|
|
2267
|
+
return true;
|
|
2268
|
+
} catch (error) {
|
|
2269
|
+
(0, browser_install_outcome.rQ)('failed', target, (Date.now() - startedAt) / 1000);
|
|
2270
|
+
(0, messaging._w)(messages.gX(target, error instanceof Error ? error.message : String(error)));
|
|
2271
|
+
return false;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2199
2274
|
var instance_registry = __webpack_require__("./browsers/browsers-lib/instance-registry.ts");
|
|
2200
2275
|
const MSG_REFERENCE = /__MSG_([A-Za-z0-9_@]+?)__/g;
|
|
2201
2276
|
function collectMsgReferences(value) {
|
|
@@ -2416,7 +2491,6 @@ var __webpack_modules__ = {
|
|
|
2416
2491
|
return false;
|
|
2417
2492
|
}
|
|
2418
2493
|
}
|
|
2419
|
-
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
2420
2494
|
var output_binaries_resolver = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
|
|
2421
2495
|
var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
|
|
2422
2496
|
var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
|
|
@@ -3208,6 +3282,26 @@ var __webpack_modules__ = {
|
|
|
3208
3282
|
browserBinaryLocation = normalized;
|
|
3209
3283
|
}
|
|
3210
3284
|
}
|
|
3285
|
+
if (!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) {
|
|
3286
|
+
const offerTarget = 'chromium' === browser ? 'chrome' : 'chrome' === browser || 'edge' === browser ? browser : null;
|
|
3287
|
+
if (offerTarget && await offerManagedInstall(offerTarget)) {
|
|
3288
|
+
const justInstalled = ()=>{
|
|
3289
|
+
try {
|
|
3290
|
+
const env = managedEnvFor(offerTarget);
|
|
3291
|
+
const located = 'edge' === offerTarget ? external_edge_location_default()({
|
|
3292
|
+
env
|
|
3293
|
+
}) : external_chrome_location2_default()(true, {
|
|
3294
|
+
env
|
|
3295
|
+
});
|
|
3296
|
+
return normalizePath(located || null);
|
|
3297
|
+
} catch {
|
|
3298
|
+
return null;
|
|
3299
|
+
}
|
|
3300
|
+
};
|
|
3301
|
+
const resolved = resolveManagedBinary() || justInstalled();
|
|
3302
|
+
if (isUsableBinary(resolved)) browserBinaryLocation = resolved;
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3211
3305
|
if (!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) {
|
|
3212
3306
|
if ('chromium' === browser || 'chromium-based' === browser) printInstallGuidance(getInstallGuidanceText('chromium'), 'chromium');
|
|
3213
3307
|
if (!printedGuidance && 'chromium' !== browser && 'chromium-based' !== browser) this.logger.error(messages.Ih(browser, browserBinaryLocation || ''));
|
|
@@ -6186,6 +6280,18 @@ var __webpack_modules__ = {
|
|
|
6186
6280
|
P: ()=>createSafariPackager
|
|
6187
6281
|
});
|
|
6188
6282
|
},
|
|
6283
|
+
"./helpers/browser-install-outcome.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
6284
|
+
function recordBrowserInstall(outcome, browser, seconds) {
|
|
6285
|
+
({
|
|
6286
|
+
...'number' == typeof seconds && Number.isFinite(seconds) && seconds >= 0 ? {
|
|
6287
|
+
seconds: Math.round(seconds)
|
|
6288
|
+
} : {}
|
|
6289
|
+
});
|
|
6290
|
+
}
|
|
6291
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
6292
|
+
rQ: ()=>recordBrowserInstall
|
|
6293
|
+
});
|
|
6294
|
+
},
|
|
6189
6295
|
"./helpers/messaging.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
6190
6296
|
var pintor__rspack_import_0 = __webpack_require__("pintor");
|
|
6191
6297
|
var pintor__rspack_import_0_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_0);
|
package/dist/cli.cjs
CHANGED
|
@@ -892,6 +892,20 @@ var __webpack_modules__ = {
|
|
|
892
892
|
function rdpInvalidRequestPayload() {
|
|
893
893
|
return `${getLoggingPrefix('error')} Received an unreadable Firefox remote debugging message.\nThe debugging connection is out of sync with the browser, usually after a crash or an abrupt reload.\nRestart the dev session.\nIf it repeats, report it with your Firefox version.`;
|
|
894
894
|
}
|
|
895
|
+
function firstRunInstallOffer(browser) {
|
|
896
|
+
const name = managedBrowserDisplayName(browser);
|
|
897
|
+
return `${getLoggingPrefix('info')} ${name} is not installed yet.\nExtension.js runs your extension in a version-pinned browser with an isolated profile, so it never touches the browser you use every day.\n${pintor__rspack_import_8_default().gray('NO DOWNLOAD')} ${pintor__rspack_import_8_default().blue('--browser=edge')} or ${pintor__rspack_import_8_default().blue('--browser=brave')} use a browser already on this machine, and ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} pins any binary, including your own Chrome.`;
|
|
898
|
+
}
|
|
899
|
+
function firstRunInstallQuestion(browser) {
|
|
900
|
+
const name = managedBrowserDisplayName(browser);
|
|
901
|
+
return `${getLoggingPrefix('info')} Download ${name} now? ${pintor__rspack_import_8_default().gray('[Y/n]')} `;
|
|
902
|
+
}
|
|
903
|
+
function firstRunInstallDeclined(browser) {
|
|
904
|
+
return `${getLoggingPrefix('info')} Skipped the download.\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${browser}`)} when you want it, or pass one of the no-download options above.`;
|
|
905
|
+
}
|
|
906
|
+
function firstRunInstallFailed(browser, reason) {
|
|
907
|
+
return `${getLoggingPrefix('warn')} The download did not finish.\n${pintor__rspack_import_8_default().gray('REASON')} ${reason}\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${browser}`)} to see the full output.`;
|
|
908
|
+
}
|
|
895
909
|
__webpack_require__.d(__webpack_exports__, {
|
|
896
910
|
$q: ()=>safariDefaultBundleIdNote,
|
|
897
911
|
$w: ()=>bestEffortBannerPrintFailed,
|
|
@@ -910,6 +924,7 @@ var __webpack_modules__ = {
|
|
|
910
924
|
F1: ()=>cdpClientBrowserConnectionEstablished,
|
|
911
925
|
F4: ()=>enhancedProcessManagementUncaughtException,
|
|
912
926
|
FF: ()=>cdpClientFoundTargets,
|
|
927
|
+
FW: ()=>firstRunInstallQuestion,
|
|
913
928
|
Fm: ()=>connectionClosedError,
|
|
914
929
|
G3: ()=>safariRequiresMacOS,
|
|
915
930
|
GB: ()=>waitingForBrowserDebugger,
|
|
@@ -929,6 +944,7 @@ var __webpack_modules__ = {
|
|
|
929
944
|
MS: ()=>errorConnectingToBrowser,
|
|
930
945
|
N4: ()=>enhancedProcessManagementUnhandledRejection,
|
|
931
946
|
NO: ()=>mv3BackgroundScriptsNotSupportedByChromium,
|
|
947
|
+
NT: ()=>firstRunInstallDeclined,
|
|
932
948
|
Nk: ()=>chromiumDryRunNotLaunching,
|
|
933
949
|
Q0: ()=>chromiumDryRunBinary,
|
|
934
950
|
Rl: ()=>safariBuilt,
|
|
@@ -960,6 +976,7 @@ var __webpack_modules__ = {
|
|
|
960
976
|
fR: ()=>cdpClientConnectionError,
|
|
961
977
|
fd: ()=>safariRegistered,
|
|
962
978
|
fw: ()=>safariOpening,
|
|
979
|
+
gX: ()=>firstRunInstallFailed,
|
|
963
980
|
hE: ()=>cdpClientConnectionClosed,
|
|
964
981
|
io: ()=>emptyLine,
|
|
965
982
|
jP: ()=>rdpInvalidRequestPayload,
|
|
@@ -970,6 +987,7 @@ var __webpack_modules__ = {
|
|
|
970
987
|
l9: ()=>parsingPacketError,
|
|
971
988
|
lO: ()=>firefoxDryRunArgs,
|
|
972
989
|
l_: ()=>safariConverted,
|
|
990
|
+
lk: ()=>firstRunInstallOffer,
|
|
973
991
|
ne: ()=>requireChromiumBinaryForChromiumBased,
|
|
974
992
|
nn: ()=>chromeProcessExited,
|
|
975
993
|
oB: ()=>safariSettingsPreserved,
|
|
@@ -2187,6 +2205,63 @@ var __webpack_modules__ = {
|
|
|
2187
2205
|
var external_yandex_location_default = /*#__PURE__*/ __webpack_require__.n(external_yandex_location_namespaceObject);
|
|
2188
2206
|
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
2189
2207
|
var banner = __webpack_require__("./browsers/browsers-lib/banner.ts");
|
|
2208
|
+
const external_node_readline_namespaceObject = require("node:readline");
|
|
2209
|
+
var external_node_readline_default = /*#__PURE__*/ __webpack_require__.n(external_node_readline_namespaceObject);
|
|
2210
|
+
var browser_install_outcome = __webpack_require__("./helpers/browser-install-outcome.ts");
|
|
2211
|
+
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
2212
|
+
function isCI() {
|
|
2213
|
+
const v = process.env;
|
|
2214
|
+
return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
|
|
2215
|
+
}
|
|
2216
|
+
function canPromptForInstall() {
|
|
2217
|
+
if (process.env.VITEST || process.env.VITEST_WORKER_ID) return false;
|
|
2218
|
+
if (process.env.EXTENSION_NO_INSTALL_PROMPT) return false;
|
|
2219
|
+
if (isCI()) return false;
|
|
2220
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
2221
|
+
}
|
|
2222
|
+
function askToInstall(question) {
|
|
2223
|
+
return new Promise((resolve)=>{
|
|
2224
|
+
const rl = external_node_readline_default().createInterface({
|
|
2225
|
+
input: process.stdin,
|
|
2226
|
+
output: process.stdout
|
|
2227
|
+
});
|
|
2228
|
+
const finish = (answer)=>{
|
|
2229
|
+
try {
|
|
2230
|
+
rl.close();
|
|
2231
|
+
} catch {}
|
|
2232
|
+
resolve(answer);
|
|
2233
|
+
};
|
|
2234
|
+
rl.question(question, (answer)=>{
|
|
2235
|
+
const normalized = String(answer || '').trim().toLowerCase();
|
|
2236
|
+
finish('n' !== normalized && 'no' !== normalized);
|
|
2237
|
+
});
|
|
2238
|
+
rl.on('SIGINT', ()=>finish(false));
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
async function offerManagedInstall(target) {
|
|
2242
|
+
if (!canPromptForInstall()) return false;
|
|
2243
|
+
(0, messaging._w)(messages.lk(target));
|
|
2244
|
+
(0, browser_install_outcome.rQ)('offered', target);
|
|
2245
|
+
const accepted = await askToInstall(messages.FW(target));
|
|
2246
|
+
if (!accepted) {
|
|
2247
|
+
(0, browser_install_outcome.rQ)('declined', target);
|
|
2248
|
+
(0, messaging._w)(messages.NT(target));
|
|
2249
|
+
return false;
|
|
2250
|
+
}
|
|
2251
|
+
const startedAt = Date.now();
|
|
2252
|
+
try {
|
|
2253
|
+
const { extensionInstall } = await import("extension-install");
|
|
2254
|
+
await extensionInstall({
|
|
2255
|
+
browser: target
|
|
2256
|
+
});
|
|
2257
|
+
(0, browser_install_outcome.rQ)('accepted', target, (Date.now() - startedAt) / 1000);
|
|
2258
|
+
return true;
|
|
2259
|
+
} catch (error) {
|
|
2260
|
+
(0, browser_install_outcome.rQ)('failed', target, (Date.now() - startedAt) / 1000);
|
|
2261
|
+
(0, messaging._w)(messages.gX(target, error instanceof Error ? error.message : String(error)));
|
|
2262
|
+
return false;
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2190
2265
|
var instance_registry = __webpack_require__("./browsers/browsers-lib/instance-registry.ts");
|
|
2191
2266
|
const MSG_REFERENCE = /__MSG_([A-Za-z0-9_@]+?)__/g;
|
|
2192
2267
|
function collectMsgReferences(value) {
|
|
@@ -2407,7 +2482,6 @@ var __webpack_modules__ = {
|
|
|
2407
2482
|
return false;
|
|
2408
2483
|
}
|
|
2409
2484
|
}
|
|
2410
|
-
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
2411
2485
|
var output_binaries_resolver = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
|
|
2412
2486
|
var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
|
|
2413
2487
|
var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
|
|
@@ -3199,6 +3273,26 @@ var __webpack_modules__ = {
|
|
|
3199
3273
|
browserBinaryLocation = normalized;
|
|
3200
3274
|
}
|
|
3201
3275
|
}
|
|
3276
|
+
if (!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) {
|
|
3277
|
+
const offerTarget = 'chromium' === browser ? 'chrome' : 'chrome' === browser || 'edge' === browser ? browser : null;
|
|
3278
|
+
if (offerTarget && await offerManagedInstall(offerTarget)) {
|
|
3279
|
+
const justInstalled = ()=>{
|
|
3280
|
+
try {
|
|
3281
|
+
const env = managedEnvFor(offerTarget);
|
|
3282
|
+
const located = 'edge' === offerTarget ? external_edge_location_default()({
|
|
3283
|
+
env
|
|
3284
|
+
}) : external_chrome_location2_default()(true, {
|
|
3285
|
+
env
|
|
3286
|
+
});
|
|
3287
|
+
return normalizePath(located || null);
|
|
3288
|
+
} catch {
|
|
3289
|
+
return null;
|
|
3290
|
+
}
|
|
3291
|
+
};
|
|
3292
|
+
const resolved = resolveManagedBinary() || justInstalled();
|
|
3293
|
+
if (isUsableBinary(resolved)) browserBinaryLocation = resolved;
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3202
3296
|
if (!browserBinaryLocation || !external_node_fs_.existsSync(browserBinaryLocation)) {
|
|
3203
3297
|
if ('chromium' === browser || 'chromium-based' === browser) printInstallGuidance(getInstallGuidanceText('chromium'), 'chromium');
|
|
3204
3298
|
if (!printedGuidance && 'chromium' !== browser && 'chromium-based' !== browser) this.logger.error(messages.Ih(browser, browserBinaryLocation || ''));
|
|
@@ -6177,6 +6271,25 @@ var __webpack_modules__ = {
|
|
|
6177
6271
|
P: ()=>createSafariPackager
|
|
6178
6272
|
});
|
|
6179
6273
|
},
|
|
6274
|
+
"./helpers/browser-install-outcome.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
6275
|
+
let record = null;
|
|
6276
|
+
function recordBrowserInstall(outcome, browser, seconds) {
|
|
6277
|
+
record = {
|
|
6278
|
+
outcome,
|
|
6279
|
+
browser,
|
|
6280
|
+
...'number' == typeof seconds && Number.isFinite(seconds) && seconds >= 0 ? {
|
|
6281
|
+
seconds: Math.round(seconds)
|
|
6282
|
+
} : {}
|
|
6283
|
+
};
|
|
6284
|
+
}
|
|
6285
|
+
function readBrowserInstall() {
|
|
6286
|
+
return record;
|
|
6287
|
+
}
|
|
6288
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
6289
|
+
rQ: ()=>recordBrowserInstall,
|
|
6290
|
+
w6: ()=>readBrowserInstall
|
|
6291
|
+
});
|
|
6292
|
+
},
|
|
6180
6293
|
"./helpers/messaging.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
6181
6294
|
var pintor__rspack_import_0 = __webpack_require__("pintor");
|
|
6182
6295
|
var pintor__rspack_import_0_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_0);
|
|
@@ -6497,6 +6610,7 @@ var __webpack_modules__ = {
|
|
|
6497
6610
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_);
|
|
6498
6611
|
var external_pintor_ = __webpack_require__("pintor");
|
|
6499
6612
|
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
|
|
6613
|
+
var browser_install_outcome = __webpack_require__("./helpers/browser-install-outcome.ts");
|
|
6500
6614
|
let cachedPackageJson = null;
|
|
6501
6615
|
function getCliPackageJson() {
|
|
6502
6616
|
if (cachedPackageJson) return cachedPackageJson;
|
|
@@ -6512,6 +6626,7 @@ var __webpack_modules__ = {
|
|
|
6512
6626
|
}
|
|
6513
6627
|
throw new Error('Extension.js CLI package.json not found.');
|
|
6514
6628
|
}
|
|
6629
|
+
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
6515
6630
|
var external_node_crypto_ = __webpack_require__("node:crypto");
|
|
6516
6631
|
var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_);
|
|
6517
6632
|
var external_node_os_ = __webpack_require__("node:os");
|
|
@@ -6527,6 +6642,15 @@ var __webpack_modules__ = {
|
|
|
6527
6642
|
return obj;
|
|
6528
6643
|
}
|
|
6529
6644
|
const VERSION_MAX_LENGTH = 64;
|
|
6645
|
+
const CATALOG_CODE = /^E_[A-Z0-9_]{1,48}$/;
|
|
6646
|
+
function catalogCode(value) {
|
|
6647
|
+
if ('string' != typeof value) return;
|
|
6648
|
+
return CATALOG_CODE.test(value) ? value : void 0;
|
|
6649
|
+
}
|
|
6650
|
+
function smallExitCode(value) {
|
|
6651
|
+
if ('number' != typeof value || !Number.isInteger(value)) return;
|
|
6652
|
+
return value >= 0 && value <= 255 ? value : void 0;
|
|
6653
|
+
}
|
|
6530
6654
|
function sanitizeTag(value) {
|
|
6531
6655
|
return String(value).trim().replace(/[^a-zA-Z0-9._-]/g, '').slice(0, 64);
|
|
6532
6656
|
}
|
|
@@ -6731,6 +6855,10 @@ var __webpack_modules__ = {
|
|
|
6731
6855
|
get isEnabled() {
|
|
6732
6856
|
return !this.disabled;
|
|
6733
6857
|
}
|
|
6858
|
+
disable() {
|
|
6859
|
+
this.disabled = true;
|
|
6860
|
+
this.buffer.length = 0;
|
|
6861
|
+
}
|
|
6734
6862
|
track(event, props) {
|
|
6735
6863
|
try {
|
|
6736
6864
|
if (this.disabled) return;
|
|
@@ -6747,6 +6875,11 @@ var __webpack_modules__ = {
|
|
|
6747
6875
|
};
|
|
6748
6876
|
if (props.template) enforcedProps.template = sanitizeTag(props.template);
|
|
6749
6877
|
if (props.source) enforcedProps.source = sanitizeTag(props.source);
|
|
6878
|
+
if ('started' === props.session) enforcedProps.session = 'started';
|
|
6879
|
+
const code = catalogCode(props.code);
|
|
6880
|
+
if (code) enforcedProps.code = code;
|
|
6881
|
+
const exitCode = smallExitCode(props.exit_code);
|
|
6882
|
+
if (void 0 !== exitCode) enforcedProps.exit_code = exitCode;
|
|
6750
6883
|
const payload = {
|
|
6751
6884
|
event,
|
|
6752
6885
|
properties: {
|
|
@@ -6758,7 +6891,7 @@ var __webpack_modules__ = {
|
|
|
6758
6891
|
distinct_id: this.anonId
|
|
6759
6892
|
};
|
|
6760
6893
|
this.writeAudit(payload);
|
|
6761
|
-
if ('command_executed' === event && 'create' !== props.command && Math.random() > this.sampleRate) return;
|
|
6894
|
+
if ('command_executed' === event && 'create' !== props.command && 'started' !== props.session && Math.random() > this.sampleRate) return;
|
|
6762
6895
|
if (!this.apiKey || !this.host) return;
|
|
6763
6896
|
this.buffer.push(payload);
|
|
6764
6897
|
this.sent += 1;
|
|
@@ -6862,7 +6995,7 @@ var __webpack_modules__ = {
|
|
|
6862
6995
|
return Math.min(Math.max(n, min), max);
|
|
6863
6996
|
}
|
|
6864
6997
|
const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
|
|
6865
|
-
const TEMPLATE_CORPUS_REF = '
|
|
6998
|
+
const TEMPLATE_CORPUS_REF = 'd951b735ee5fbe904bba0c47d688527300d10e32';
|
|
6866
6999
|
const TEMPLATE_CORPUS_SLUGS = [
|
|
6867
7000
|
'action',
|
|
6868
7001
|
'action-locales',
|
|
@@ -7147,14 +7280,23 @@ var __webpack_modules__ = {
|
|
|
7147
7280
|
].join('\n');
|
|
7148
7281
|
}
|
|
7149
7282
|
const KNOWN_COMMANDS = new Set([
|
|
7283
|
+
'build',
|
|
7284
|
+
'capabilities',
|
|
7150
7285
|
'create',
|
|
7151
7286
|
'dev',
|
|
7152
|
-
'
|
|
7153
|
-
'
|
|
7154
|
-
'
|
|
7287
|
+
'doctor',
|
|
7288
|
+
'eval',
|
|
7289
|
+
'inspect',
|
|
7155
7290
|
'install',
|
|
7156
|
-
'
|
|
7291
|
+
'logs',
|
|
7292
|
+
'open',
|
|
7293
|
+
'preview',
|
|
7294
|
+
'publish',
|
|
7295
|
+
'reload',
|
|
7296
|
+
'start',
|
|
7297
|
+
'storage',
|
|
7157
7298
|
'telemetry',
|
|
7299
|
+
'uninstall',
|
|
7158
7300
|
'unknown'
|
|
7159
7301
|
]);
|
|
7160
7302
|
function detectInvokedCommand(argv) {
|
|
@@ -7187,8 +7329,17 @@ var __webpack_modules__ = {
|
|
|
7187
7329
|
if (templateAliasFor(name)) return name;
|
|
7188
7330
|
}
|
|
7189
7331
|
function telemetryCommandContext(command, argv = process.argv) {
|
|
7190
|
-
|
|
7332
|
+
const install = (0, browser_install_outcome.w6)();
|
|
7333
|
+
const installContext = install ? {
|
|
7334
|
+
browser_install: install.outcome,
|
|
7335
|
+
browser_install_browser: install.browser,
|
|
7336
|
+
...void 0 === install.seconds ? {} : {
|
|
7337
|
+
browser_install_seconds: install.seconds
|
|
7338
|
+
}
|
|
7339
|
+
} : {};
|
|
7340
|
+
if ('create' !== command) return installContext;
|
|
7191
7341
|
return {
|
|
7342
|
+
...installContext,
|
|
7192
7343
|
template: advertisedTemplateName(readArgValue(argv, [
|
|
7193
7344
|
'--template',
|
|
7194
7345
|
'-t'
|
|
@@ -7209,8 +7360,12 @@ var __webpack_modules__ = {
|
|
|
7209
7360
|
function getTelemetryConsent() {
|
|
7210
7361
|
return consent;
|
|
7211
7362
|
}
|
|
7363
|
+
function invokedCommand() {
|
|
7364
|
+
return invoked;
|
|
7365
|
+
}
|
|
7212
7366
|
function setTelemetryConsent(value) {
|
|
7213
7367
|
const ok = writeConsent(value);
|
|
7368
|
+
if ('disabled' === value) telemetry.disable();
|
|
7214
7369
|
const storage = resolveTelemetryStorage();
|
|
7215
7370
|
return {
|
|
7216
7371
|
ok,
|
|
@@ -7218,12 +7373,29 @@ var __webpack_modules__ = {
|
|
|
7218
7373
|
};
|
|
7219
7374
|
}
|
|
7220
7375
|
let tracked = false;
|
|
7376
|
+
let sessionStarted = false;
|
|
7221
7377
|
function markTracked() {
|
|
7222
7378
|
if (tracked) return false;
|
|
7223
7379
|
tracked = true;
|
|
7224
7380
|
return true;
|
|
7225
7381
|
}
|
|
7382
|
+
function markCommandSessionStart(command = invoked) {
|
|
7383
|
+
if (tracked || sessionStarted) return;
|
|
7384
|
+
sessionStarted = true;
|
|
7385
|
+
telemetry.track('command_executed', {
|
|
7386
|
+
command,
|
|
7387
|
+
success: true,
|
|
7388
|
+
version: telemetry_cli_version,
|
|
7389
|
+
session: 'started',
|
|
7390
|
+
...telemetryCommandContext(command)
|
|
7391
|
+
});
|
|
7392
|
+
telemetry.flush();
|
|
7393
|
+
}
|
|
7394
|
+
function hasTrackedSessionStart() {
|
|
7395
|
+
return sessionStarted;
|
|
7396
|
+
}
|
|
7226
7397
|
function markCommandSuccess(command = invoked) {
|
|
7398
|
+
if (sessionStarted) return;
|
|
7227
7399
|
if (!markTracked()) return;
|
|
7228
7400
|
telemetry.track('command_executed', {
|
|
7229
7401
|
command,
|
|
@@ -7232,12 +7404,29 @@ var __webpack_modules__ = {
|
|
|
7232
7404
|
...telemetryCommandContext(command)
|
|
7233
7405
|
});
|
|
7234
7406
|
}
|
|
7235
|
-
function
|
|
7407
|
+
function telemetryFailureCode(code) {
|
|
7408
|
+
if ('string' != typeof code) return;
|
|
7409
|
+
return Object.prototype.hasOwnProperty.call(messaging.Lp, code) ? code : void 0;
|
|
7410
|
+
}
|
|
7411
|
+
function telemetryExitCode(exitCode) {
|
|
7412
|
+
if ('number' != typeof exitCode) return;
|
|
7413
|
+
if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > 255) return;
|
|
7414
|
+
return exitCode;
|
|
7415
|
+
}
|
|
7416
|
+
function markCommandFailure(command = invoked, details = {}) {
|
|
7236
7417
|
if (!markTracked()) return;
|
|
7418
|
+
const code = telemetryFailureCode(details.code);
|
|
7419
|
+
const exitCode = telemetryExitCode(details.exitCode);
|
|
7237
7420
|
telemetry.track('command_failed', {
|
|
7238
7421
|
command,
|
|
7239
7422
|
success: false,
|
|
7240
7423
|
version: telemetry_cli_version,
|
|
7424
|
+
...code ? {
|
|
7425
|
+
code
|
|
7426
|
+
} : {},
|
|
7427
|
+
...void 0 === exitCode ? {} : {
|
|
7428
|
+
exit_code: exitCode
|
|
7429
|
+
},
|
|
7241
7430
|
...telemetryCommandContext(command)
|
|
7242
7431
|
});
|
|
7243
7432
|
}
|
|
@@ -7264,7 +7453,17 @@ var __webpack_modules__ = {
|
|
|
7264
7453
|
});
|
|
7265
7454
|
}
|
|
7266
7455
|
const TELEMETRY_FLUSH_TIMEOUT_MS = 500;
|
|
7456
|
+
function markOutcomeForExit(code) {
|
|
7457
|
+
try {
|
|
7458
|
+
if ('unknown' === invokedCommand()) return;
|
|
7459
|
+
if (0 === code) return void markCommandSuccess();
|
|
7460
|
+
markCommandFailure(void 0, {
|
|
7461
|
+
exitCode: code
|
|
7462
|
+
});
|
|
7463
|
+
} catch {}
|
|
7464
|
+
}
|
|
7267
7465
|
async function exitAfterDrain(code) {
|
|
7466
|
+
markOutcomeForExit(code);
|
|
7268
7467
|
try {
|
|
7269
7468
|
await Promise.race([
|
|
7270
7469
|
telemetry.flush(),
|
|
@@ -7403,7 +7602,6 @@ var __webpack_modules__ = {
|
|
|
7403
7602
|
const bridgeSpecifier = 'extension-develop/bridge';
|
|
7404
7603
|
return await import(bridgeSpecifier);
|
|
7405
7604
|
}
|
|
7406
|
-
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
7407
7605
|
function getLoggingPrefix(type) {
|
|
7408
7606
|
return (0, messaging.Pl)(type);
|
|
7409
7607
|
}
|
|
@@ -9108,7 +9306,10 @@ Cross-browser compatibility
|
|
|
9108
9306
|
cliVersion: getCliPackageJson().version
|
|
9109
9307
|
});
|
|
9110
9308
|
} catch (error) {
|
|
9111
|
-
markCommandFailure(
|
|
9309
|
+
markCommandFailure(void 0, {
|
|
9310
|
+
code: createErrorCode(error),
|
|
9311
|
+
exitCode: 1
|
|
9312
|
+
});
|
|
9112
9313
|
if (!asJson) throw error;
|
|
9113
9314
|
console.log(JSON.stringify(messaging.Pr.fail('create', 'failed', {
|
|
9114
9315
|
code: createErrorCode(error),
|
|
@@ -9321,6 +9522,8 @@ Cross-browser compatibility
|
|
|
9321
9522
|
function cliGeckoBinary(opts) {
|
|
9322
9523
|
return opts.geckoBinary ?? opts.firefoxBinary;
|
|
9323
9524
|
}
|
|
9525
|
+
const BROWSER_LAUNCH_HELP_FOOTER = "\nTo stop the browser launch, use --no-browser.\nTo launch the browser without opening a tab for your extension, use --no-open.\n";
|
|
9526
|
+
const NO_OPEN_FLAG_DESCRIPTION = 'launch the browser but do not open a tab for your extension. To stop the browser launch itself, use --no-browser';
|
|
9324
9527
|
async function resolveNoBrowser(projectPath, command) {
|
|
9325
9528
|
if ('1' === process.env.EXTENSION_CLI_NO_BROWSER) return true;
|
|
9326
9529
|
try {
|
|
@@ -9544,7 +9747,7 @@ Cross-browser compatibility
|
|
|
9544
9747
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
|
|
9545
9748
|
}
|
|
9546
9749
|
function registerDevCommand(program) {
|
|
9547
|
-
program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser
|
|
9750
|
+
program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the dev server still starts\n --no-reload emit a dev-mode dist without the content-script reload runtime, tabs need a manual reload to see changes\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).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').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).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', NO_OPEN_FLAG_DESCRIPTION).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)=>{
|
|
9548
9751
|
const { browser: cliBrowser, ...devOptions } = options;
|
|
9549
9752
|
const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'dev') ?? 'chromium';
|
|
9550
9753
|
if (devOptions.debug || devOptions.author || devOptions.authorMode) {
|
|
@@ -9665,6 +9868,7 @@ Cross-browser compatibility
|
|
|
9665
9868
|
pid: process.pid,
|
|
9666
9869
|
noBrowser
|
|
9667
9870
|
}));
|
|
9871
|
+
markCommandSessionStart('dev');
|
|
9668
9872
|
const { extensionDev } = await loadExtensionDevelopModule();
|
|
9669
9873
|
for (const vendor of list){
|
|
9670
9874
|
const logsOption = devOptions.logs;
|
|
@@ -10209,7 +10413,7 @@ Cross-browser compatibility
|
|
|
10209
10413
|
'Manifest file not found'
|
|
10210
10414
|
];
|
|
10211
10415
|
function registerPreviewCommand(program) {
|
|
10212
|
-
program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after',
|
|
10416
|
+
program.command('preview').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.preview).addHelpText('after', "\nAdditional option:\n --no-browser stop the browser launch\n" + BROWSER_LAUNCH_HELP_FOOTER).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`--browser <${NO_SAFARI_BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--no-open', NO_OPEN_FLAG_DESCRIPTION).option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|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('--output-path <dir>', 'path to an existing unpacked extension directory. Defaults to dist/<browser> when available').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, options, command)=>{
|
|
10213
10417
|
const { browser: cliBrowser, ...previewOptions } = options;
|
|
10214
10418
|
const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'preview') ?? 'chromium';
|
|
10215
10419
|
if (previewOptions.debug || previewOptions.author || previewOptions.authorMode) {
|
|
@@ -10250,6 +10454,7 @@ Cross-browser compatibility
|
|
|
10250
10454
|
const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
|
|
10251
10455
|
if (isRemote) process.env.EXTJS_LIGHT = '1';
|
|
10252
10456
|
}
|
|
10457
|
+
markCommandSessionStart('preview');
|
|
10253
10458
|
const { extensionPreview } = await loadExtensionDevelopPreviewModule();
|
|
10254
10459
|
const previewed = [];
|
|
10255
10460
|
for (const vendor of list){
|
|
@@ -10263,6 +10468,7 @@ Cross-browser compatibility
|
|
|
10263
10468
|
browser: vendor,
|
|
10264
10469
|
chromiumBinary: previewOptions.chromiumBinary,
|
|
10265
10470
|
geckoBinary: cliGeckoBinary(previewOptions),
|
|
10471
|
+
noOpen: explicitCliValue(command, 'open', false === previewOptions.open),
|
|
10266
10472
|
startingUrl: previewOptions.startingUrl,
|
|
10267
10473
|
port: previewOptions.port,
|
|
10268
10474
|
noBrowser: await resolveNoBrowser(pathOrRemoteUrl || process.cwd(), 'preview'),
|
|
@@ -10474,7 +10680,7 @@ Cross-browser compatibility
|
|
|
10474
10680
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
|
|
10475
10681
|
}
|
|
10476
10682
|
function registerStartCommand(program) {
|
|
10477
|
-
program.command('start').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after',
|
|
10683
|
+
program.command('start').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.start).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the build still runs\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`--browser <${NO_SAFARI_BROWSER_TARGETS_HELP}>`, 'specify a browser/engine to run. Defaults to `chromium`').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', NO_OPEN_FLAG_DESCRIPTION).option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).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()).action(async (pathOrRemoteUrl, options, command)=>{
|
|
10478
10684
|
const { browser: cliBrowser, ...startOptions } = options;
|
|
10479
10685
|
const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'start') ?? 'chromium';
|
|
10480
10686
|
if (startOptions.debug || startOptions.author || startOptions.authorMode) {
|
|
@@ -10542,6 +10748,7 @@ Cross-browser compatibility
|
|
|
10542
10748
|
pid: process.pid,
|
|
10543
10749
|
noBrowser: await resolveNoBrowser(pathOrRemoteUrl || process.cwd(), 'start')
|
|
10544
10750
|
}));
|
|
10751
|
+
markCommandSessionStart('start');
|
|
10545
10752
|
const { extensionBuild } = await loadExtensionDevelopModule();
|
|
10546
10753
|
for (const vendor of list){
|
|
10547
10754
|
const logsOption = startOptions.logs;
|
|
@@ -10581,6 +10788,7 @@ Cross-browser compatibility
|
|
|
10581
10788
|
port: startOptions.port,
|
|
10582
10789
|
host: startOptions.host,
|
|
10583
10790
|
noBrowser: false,
|
|
10791
|
+
noOpen: explicitCliValue(command, 'open', false === startOptions.open),
|
|
10584
10792
|
extensions: parseExtensionsList(startOptions.extensions),
|
|
10585
10793
|
metadataCommand: 'start',
|
|
10586
10794
|
logLevel,
|
|
@@ -10667,6 +10875,63 @@ Cross-browser compatibility
|
|
|
10667
10875
|
}
|
|
10668
10876
|
return null;
|
|
10669
10877
|
}
|
|
10878
|
+
const TERMINATION_SIGNALS = [
|
|
10879
|
+
'SIGINT',
|
|
10880
|
+
'SIGTERM'
|
|
10881
|
+
];
|
|
10882
|
+
const FLUSH_DEADLINE_MS = 500;
|
|
10883
|
+
const SIGNAL_NUMBERS = {
|
|
10884
|
+
SIGINT: 2,
|
|
10885
|
+
SIGTERM: 15
|
|
10886
|
+
};
|
|
10887
|
+
function signalExitCode(signal) {
|
|
10888
|
+
return 128 + SIGNAL_NUMBERS[signal];
|
|
10889
|
+
}
|
|
10890
|
+
let handled = false;
|
|
10891
|
+
const ownListeners = new Set();
|
|
10892
|
+
let telemetry_signals_installed = false;
|
|
10893
|
+
async function flushTelemetryWithin(ms) {
|
|
10894
|
+
try {
|
|
10895
|
+
await Promise.race([
|
|
10896
|
+
telemetry.flush(),
|
|
10897
|
+
new Promise((resolve)=>setTimeout(resolve, ms).unref?.())
|
|
10898
|
+
]);
|
|
10899
|
+
} catch {}
|
|
10900
|
+
}
|
|
10901
|
+
async function handleTerminationSignal(signal, deps) {
|
|
10902
|
+
if (handled) return;
|
|
10903
|
+
handled = true;
|
|
10904
|
+
const counted = deps.sessionStarted();
|
|
10905
|
+
const othersOwn = deps.othersOwnTermination();
|
|
10906
|
+
if (!counted && !othersOwn) deps.markInterrupted(signalExitCode(signal));
|
|
10907
|
+
await deps.flush();
|
|
10908
|
+
if (!othersOwn) await deps.exit(counted ? 0 : signalExitCode(signal));
|
|
10909
|
+
}
|
|
10910
|
+
function defaultDeps() {
|
|
10911
|
+
return {
|
|
10912
|
+
sessionStarted: hasTrackedSessionStart,
|
|
10913
|
+
markInterrupted: (exitCode)=>markCommandFailure(void 0, {
|
|
10914
|
+
code: messaging.Lp.E_INTERRUPTED,
|
|
10915
|
+
exitCode
|
|
10916
|
+
}),
|
|
10917
|
+
flush: ()=>flushTelemetryWithin(FLUSH_DEADLINE_MS),
|
|
10918
|
+
othersOwnTermination: ()=>TERMINATION_SIGNALS.some((signal)=>process.listeners(signal).some((listener)=>!ownListeners.has(listener))),
|
|
10919
|
+
exit: (code)=>exitAfterDrain(code)
|
|
10920
|
+
};
|
|
10921
|
+
}
|
|
10922
|
+
function installTelemetrySignalHandlers() {
|
|
10923
|
+
if (telemetry_signals_installed) return;
|
|
10924
|
+
if (!getTelemetryConsent().enabled) return;
|
|
10925
|
+
telemetry_signals_installed = true;
|
|
10926
|
+
for (const signal of TERMINATION_SIGNALS){
|
|
10927
|
+
const listener = ()=>{
|
|
10928
|
+
handleTerminationSignal(signal, defaultDeps());
|
|
10929
|
+
};
|
|
10930
|
+
ownListeners.add(listener);
|
|
10931
|
+
process.once(signal, listener);
|
|
10932
|
+
}
|
|
10933
|
+
}
|
|
10934
|
+
installTelemetrySignalHandlers();
|
|
10670
10935
|
const index_cliPackageJson = getCliPackageJson();
|
|
10671
10936
|
function developVersion() {
|
|
10672
10937
|
return resolveExtensionDevelopVersion(__dirname, index_cliPackageJson.version);
|
|
@@ -10775,13 +11040,19 @@ Cross-browser compatibility
|
|
|
10775
11040
|
if (isCommanderError(err)) {
|
|
10776
11041
|
const exitCode = commanderExitCode(err);
|
|
10777
11042
|
if (0 === exitCode) process.exit(0);
|
|
10778
|
-
markCommandFailure(
|
|
11043
|
+
markCommandFailure(void 0, {
|
|
11044
|
+
code: messaging.Lp.E_ARGS,
|
|
11045
|
+
exitCode
|
|
11046
|
+
});
|
|
10779
11047
|
console.error(commanderHumanError(err, commandName));
|
|
10780
11048
|
if (asJson) writeStdoutFrame(commanderErrorEnvelope(err, commandName));
|
|
10781
11049
|
await exitAfterDrain(exitCode);
|
|
10782
11050
|
return;
|
|
10783
11051
|
}
|
|
10784
|
-
markCommandFailure(
|
|
11052
|
+
markCommandFailure(void 0, {
|
|
11053
|
+
code: telemetryFailureCode(err?.code) || messaging.Lp.E_INTERNAL,
|
|
11054
|
+
exitCode: 1
|
|
11055
|
+
});
|
|
10785
11056
|
console.error(unhandledError(err));
|
|
10786
11057
|
if (asJson && !isErrorFramed(err)) writeStdoutFrame(internalErrorEnvelope(err, commandName));
|
|
10787
11058
|
await exitAfterDrain(1);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type InstallableTarget = 'chrome' | 'chromium' | 'edge' | 'firefox';
|
|
2
|
+
export declare function canPromptForInstall(): boolean;
|
|
3
|
+
export declare function askToInstall(question: string): Promise<boolean>;
|
|
4
|
+
export declare function offerManagedInstall(target: InstallableTarget): Promise<boolean>;
|
|
@@ -140,4 +140,8 @@ export declare function requireGeckoBinaryForGeckoBased(): string;
|
|
|
140
140
|
export declare function invalidChromiumBinaryPath(p: string): string;
|
|
141
141
|
export declare function invalidGeckoBinaryPath(p: string): string;
|
|
142
142
|
export declare function rdpInvalidRequestPayload(): string;
|
|
143
|
+
export declare function firstRunInstallOffer(browser: string): string;
|
|
144
|
+
export declare function firstRunInstallQuestion(browser: string): string;
|
|
145
|
+
export declare function firstRunInstallDeclined(browser: string): string;
|
|
146
|
+
export declare function firstRunInstallFailed(browser: string, reason: string): string;
|
|
143
147
|
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type BrowserInstallOutcome = 'offered' | 'accepted' | 'declined' | 'failed';
|
|
2
|
+
interface BrowserInstallRecord {
|
|
3
|
+
outcome: BrowserInstallOutcome;
|
|
4
|
+
browser: string;
|
|
5
|
+
seconds?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function recordBrowserInstall(outcome: BrowserInstallOutcome, browser: string, seconds?: number): void;
|
|
8
|
+
export declare function readBrowserInstall(): BrowserInstallRecord | null;
|
|
9
|
+
export declare function resetBrowserInstall(): void;
|
|
10
|
+
export {};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
+
export declare const BROWSER_LAUNCH_HELP_FOOTER: string;
|
|
2
|
+
export declare const NO_OPEN_FLAG_DESCRIPTION = "launch the browser but do not open a tab for your extension. To stop the browser launch itself, use --no-browser";
|
|
1
3
|
export declare function resolveNoBrowser(projectPath: string, command: 'dev' | 'start' | 'preview'): Promise<boolean>;
|
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { Telemetry, type TelemetrySource } from './telemetry';
|
|
2
|
-
type KnownCommand = 'create' | 'dev' | '
|
|
2
|
+
type KnownCommand = 'build' | 'capabilities' | 'create' | 'dev' | 'doctor' | 'eval' | 'inspect' | 'install' | 'logs' | 'open' | 'preview' | 'publish' | 'reload' | 'start' | 'storage' | 'telemetry' | 'uninstall' | 'unknown';
|
|
3
|
+
export declare const KNOWN_COMMANDS: ReadonlySet<KnownCommand>;
|
|
3
4
|
export declare function detectInvokedCommand(argv: string[]): KnownCommand;
|
|
4
5
|
export declare function advertisedTemplateName(value: string | undefined): string | undefined;
|
|
5
6
|
export declare function telemetryCommandContext(command: string, argv?: string[]): {
|
|
6
7
|
template?: string;
|
|
7
8
|
source?: string;
|
|
9
|
+
browser_install?: string;
|
|
10
|
+
browser_install_browser?: string;
|
|
11
|
+
browser_install_seconds?: number;
|
|
8
12
|
};
|
|
9
13
|
export declare const telemetry: Telemetry;
|
|
10
14
|
export declare function getTelemetryConsent(): {
|
|
11
15
|
enabled: boolean;
|
|
12
16
|
source: TelemetrySource;
|
|
13
17
|
};
|
|
18
|
+
export declare function invokedCommand(): string;
|
|
14
19
|
export declare function setTelemetryConsent(value: 'enabled' | 'disabled'): {
|
|
15
20
|
ok: boolean;
|
|
16
21
|
path: string | null;
|
|
17
22
|
};
|
|
23
|
+
export declare function markCommandSessionStart(command?: KnownCommand): void;
|
|
24
|
+
export declare function hasTrackedSessionStart(): boolean;
|
|
18
25
|
export declare function markCommandSuccess(command?: KnownCommand): void;
|
|
19
|
-
export
|
|
26
|
+
export interface CommandFailureDetails {
|
|
27
|
+
code?: unknown;
|
|
28
|
+
exitCode?: unknown;
|
|
29
|
+
}
|
|
30
|
+
export declare function telemetryFailureCode(code: unknown): string | undefined;
|
|
31
|
+
export declare function telemetryExitCode(exitCode: unknown): number | undefined;
|
|
32
|
+
export declare function markCommandFailure(command?: KnownCommand, details?: CommandFailureDetails): void;
|
|
20
33
|
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type TerminationSignal = 'SIGINT' | 'SIGTERM';
|
|
2
|
+
export declare const TERMINATION_SIGNALS: readonly TerminationSignal[];
|
|
3
|
+
export declare function signalExitCode(signal: TerminationSignal): number;
|
|
4
|
+
export interface TerminationSignalDeps {
|
|
5
|
+
sessionStarted: () => boolean;
|
|
6
|
+
markInterrupted: (exitCode: number) => void;
|
|
7
|
+
flush: () => Promise<void>;
|
|
8
|
+
othersOwnTermination: () => boolean;
|
|
9
|
+
exit: (code: number) => void | Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare function __resetTelemetrySignalsForTest(): void;
|
|
12
|
+
export declare function flushTelemetryWithin(ms: number): Promise<void>;
|
|
13
|
+
export declare function handleTerminationSignal(signal: TerminationSignal, deps: TerminationSignalDeps): Promise<void>;
|
|
14
|
+
export declare function installTelemetrySignalHandlers(): void;
|
|
@@ -5,6 +5,9 @@ export type TelemetryProps = {
|
|
|
5
5
|
version: string;
|
|
6
6
|
template?: string;
|
|
7
7
|
source?: string;
|
|
8
|
+
session?: 'started';
|
|
9
|
+
code?: string;
|
|
10
|
+
exit_code?: number;
|
|
8
11
|
};
|
|
9
12
|
export type TelemetrySource = 'env' | 'flag' | 'config' | 'ci' | 'default';
|
|
10
13
|
type TelemetryInit = {
|
|
@@ -53,6 +56,7 @@ export declare class Telemetry {
|
|
|
53
56
|
private buffer;
|
|
54
57
|
constructor(init: TelemetryInit);
|
|
55
58
|
get isEnabled(): boolean;
|
|
59
|
+
disable(): void;
|
|
56
60
|
track(event: TelemetryEvent, props: TelemetryProps): void;
|
|
57
61
|
flush(): Promise<void>;
|
|
58
62
|
shutdown(): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const DEFAULT_TEMPLATE = "typescript";
|
|
2
2
|
export declare const BUNDLED_TEMPLATES: readonly string[];
|
|
3
|
-
export declare const TEMPLATE_CATALOG_URL = "https://github.com/extension-js/examples/tree/
|
|
3
|
+
export declare const TEMPLATE_CATALOG_URL = "https://github.com/extension-js/examples/tree/d951b735ee5fbe904bba0c47d688527300d10e32/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 = "
|
|
2
|
+
export declare const TEMPLATE_CORPUS_REF = "d951b735ee5fbe904bba0c47d688527300d10e32";
|
|
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.
|
|
41
|
+
"version": "4.1.16",
|
|
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.
|
|
110
|
-
"extension-develop": "4.1.
|
|
111
|
-
"extension-install": "4.1.
|
|
109
|
+
"extension-create": "4.1.16",
|
|
110
|
+
"extension-develop": "4.1.16",
|
|
111
|
+
"extension-install": "4.1.16",
|
|
112
112
|
"commander": "^15.0.0",
|
|
113
113
|
"pintor": "0.3.0",
|
|
114
114
|
"semver": "^7.7.3",
|