extension 4.0.18 → 4.0.19
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/49.cjs +17 -8
- package/dist/browsers.cjs +661 -14
- package/dist/cli.cjs +1821 -1731
- package/dist/extension/browsers/browsers-lib/banner.d.ts +2 -0
- package/dist/extension/browsers/browsers-lib/messages.d.ts +1 -0
- package/dist/extension/browsers/index.d.ts +4 -0
- package/dist/extension/browsers/run-safari/safari-launch/index.d.ts +14 -1
- package/dist/extension/browsers/run-safari/safari-packager.d.ts +30 -0
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
|
@@ -149,7 +149,9 @@ var __webpack_modules__ = {
|
|
|
149
149
|
};
|
|
150
150
|
const updateSuffix = readUpdateSuffixOnce();
|
|
151
151
|
console.log(_messages__rspack_import_5.io());
|
|
152
|
-
console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, opts.browserVersionLine, updateSuffix || void 0
|
|
152
|
+
console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, opts.browserVersionLine, updateSuffix || void 0, {
|
|
153
|
+
profilePath: opts.profilePath
|
|
154
|
+
}));
|
|
153
155
|
console.log(_messages__rspack_import_5.io());
|
|
154
156
|
markCardPrinted(k, opts.browser, opts.outPath);
|
|
155
157
|
return true;
|
|
@@ -188,7 +190,8 @@ var __webpack_modules__ = {
|
|
|
188
190
|
console.log(_messages__rspack_import_5.io());
|
|
189
191
|
console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, browserLabel, updateSuffix || void 0, {
|
|
190
192
|
includeExtensionId: opts.includeExtensionId,
|
|
191
|
-
runLabel
|
|
193
|
+
runLabel,
|
|
194
|
+
profilePath: opts.profilePath
|
|
192
195
|
}));
|
|
193
196
|
console.log(_messages__rspack_import_5.io());
|
|
194
197
|
} else {
|
|
@@ -205,7 +208,8 @@ var __webpack_modules__ = {
|
|
|
205
208
|
console.log(_messages__rspack_import_5.io());
|
|
206
209
|
console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, browserLabel, updateSuffix || void 0, {
|
|
207
210
|
includeExtensionId: opts.includeExtensionId,
|
|
208
|
-
runLabel
|
|
211
|
+
runLabel,
|
|
212
|
+
profilePath: opts.profilePath
|
|
209
213
|
}));
|
|
210
214
|
console.log(_messages__rspack_import_5.io());
|
|
211
215
|
}
|
|
@@ -220,6 +224,10 @@ var __webpack_modules__ = {
|
|
|
220
224
|
{
|
|
221
225
|
label: 'Output',
|
|
222
226
|
value: opts.outPath
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
label: 'Profile',
|
|
230
|
+
value: opts.profilePath || ''
|
|
223
231
|
}
|
|
224
232
|
]
|
|
225
233
|
}));
|
|
@@ -796,6 +804,10 @@ var __webpack_modules__ = {
|
|
|
796
804
|
label: 'Extension ID',
|
|
797
805
|
value: includeExtensionId ? cleanId : ''
|
|
798
806
|
},
|
|
807
|
+
{
|
|
808
|
+
label: 'Profile',
|
|
809
|
+
value: String(opts?.profilePath || '').trim()
|
|
810
|
+
},
|
|
799
811
|
{
|
|
800
812
|
label: 'Run ID',
|
|
801
813
|
value: opts?.runLabel || ''
|
|
@@ -1696,12 +1708,15 @@ var __webpack_modules__ = {
|
|
|
1696
1708
|
"./browsers/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1697
1709
|
var _browsers_lib_browser_family__rspack_import_0 = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
|
|
1698
1710
|
var _browsers_lib_output_binaries_resolver__rspack_import_1 = __webpack_require__("./browsers/browsers-lib/output-binaries-resolver.ts");
|
|
1699
|
-
var
|
|
1700
|
-
var
|
|
1711
|
+
var _browsers_lib_runtime_options__rspack_import_10 = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
|
|
1712
|
+
var _run_chromium_chromium_context__rspack_import_8 = __webpack_require__("./browsers/run-chromium/chromium-context/index.ts");
|
|
1701
1713
|
var _run_chromium_chromium_launch__rspack_import_2 = __webpack_require__("./browsers/run-chromium/chromium-launch/index.ts");
|
|
1702
|
-
var
|
|
1714
|
+
var _run_firefox_firefox_context__rspack_import_9 = __webpack_require__("./browsers/run-firefox/firefox-context/index.ts");
|
|
1703
1715
|
var _run_firefox_firefox_launch__rspack_import_3 = __webpack_require__("./browsers/run-firefox/firefox-launch/index.ts");
|
|
1704
1716
|
__webpack_require__("./browsers/run-only.ts");
|
|
1717
|
+
__webpack_require__("./browsers/run-safari/safari-launch/index.ts");
|
|
1718
|
+
__webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
|
|
1719
|
+
__webpack_require__("./browsers/run-safari/safari-packager.ts");
|
|
1705
1720
|
function createCompilationLike(opts) {
|
|
1706
1721
|
return {
|
|
1707
1722
|
options: {
|
|
@@ -1750,7 +1765,7 @@ var __webpack_modules__ = {
|
|
|
1750
1765
|
logTab: opts.logTab,
|
|
1751
1766
|
logSink: opts.logSink
|
|
1752
1767
|
};
|
|
1753
|
-
const ctx = (0,
|
|
1768
|
+
const ctx = (0, _run_chromium_chromium_context__rspack_import_8.g)();
|
|
1754
1769
|
const launcher = new _run_chromium_chromium_launch__rspack_import_2.f(chromiumOpts, ctx);
|
|
1755
1770
|
const enableCdp = 'development' === mode;
|
|
1756
1771
|
await launcher.runOnce(compilationLike, {
|
|
@@ -1824,9 +1839,9 @@ var __webpack_modules__ = {
|
|
|
1824
1839
|
port: opts.port,
|
|
1825
1840
|
dryRun: opts.dryRun
|
|
1826
1841
|
};
|
|
1827
|
-
const ctx = (0,
|
|
1842
|
+
const ctx = (0, _run_firefox_firefox_context__rspack_import_9.D)();
|
|
1828
1843
|
const launcher = new _run_firefox_firefox_launch__rspack_import_3.c(firefoxOpts, ctx);
|
|
1829
|
-
const launchRequest = (0,
|
|
1844
|
+
const launchRequest = (0, _browsers_lib_runtime_options__rspack_import_10.zU)(pluginOptions, mode, {
|
|
1830
1845
|
persistProfile: opts.persistProfile,
|
|
1831
1846
|
geckoBinary: opts.geckoBinary
|
|
1832
1847
|
});
|
|
@@ -2618,10 +2633,13 @@ var __webpack_modules__ = {
|
|
|
2618
2633
|
const loadExtensionFlag = args.chromiumConfig.find((flag)=>flag.startsWith('--load-extension='));
|
|
2619
2634
|
const extensionOutputPath = (0, extension_output_path.W)(args.compilation, loadExtensionFlag);
|
|
2620
2635
|
if (!extensionOutputPath) return;
|
|
2636
|
+
const userDataDirFlag = args.chromiumConfig.find((flag)=>flag.startsWith('--user-data-dir='));
|
|
2637
|
+
const profilePath = userDataDirFlag ? userDataDirFlag.replace('--user-data-dir=', '').replace(/^"|"$/g, '') : void 0;
|
|
2621
2638
|
if ('production' === mode) return void await (0, banner.MK)({
|
|
2622
2639
|
browser: args.browser,
|
|
2623
2640
|
outPath: extensionOutputPath,
|
|
2624
|
-
browserVersionLine: args.browserVersionLine
|
|
2641
|
+
browserVersionLine: args.browserVersionLine,
|
|
2642
|
+
profilePath
|
|
2625
2643
|
});
|
|
2626
2644
|
if ('development' !== mode) return;
|
|
2627
2645
|
const ready = await (0, manifest_readiness.fR)(extensionOutputPath, {
|
|
@@ -2634,7 +2652,8 @@ var __webpack_modules__ = {
|
|
|
2634
2652
|
outPath: extensionOutputPath,
|
|
2635
2653
|
hostPort: args.hostPort,
|
|
2636
2654
|
getInfo: async ()=>null,
|
|
2637
|
-
browserVersionLine: args.browserVersionLine
|
|
2655
|
+
browserVersionLine: args.browserVersionLine,
|
|
2656
|
+
profilePath
|
|
2638
2657
|
});
|
|
2639
2658
|
}
|
|
2640
2659
|
class ChromiumLaunchPlugin {
|
|
@@ -5128,1801 +5147,1880 @@ var __webpack_modules__ = {
|
|
|
5128
5147
|
E: ()=>runOnlyPreviewBrowser
|
|
5129
5148
|
});
|
|
5130
5149
|
},
|
|
5131
|
-
"./
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
const raw = process.env.EXTENSION_DEBUG ?? process.env.EXTENSION_AUTHOR_MODE;
|
|
5147
|
-
return DEBUG_VALUES.has(String(raw ?? '').trim().toLowerCase());
|
|
5150
|
+
"./browsers/run-safari/safari-launch/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5151
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5152
|
+
Ah: ()=>packageSafariExtension,
|
|
5153
|
+
QW: ()=>safariBuildPreflight,
|
|
5154
|
+
iF: ()=>safariPreflightError
|
|
5155
|
+
});
|
|
5156
|
+
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
5157
|
+
var external_node_fs_ = __webpack_require__("node:fs");
|
|
5158
|
+
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
5159
|
+
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
5160
|
+
function logSafariDryRun(converterCmd, xcodebuildCmd) {
|
|
5161
|
+
if ((0, messaging._o)()) console.log(messages.KP());
|
|
5162
|
+
console.log(messages.yc());
|
|
5163
|
+
console.log(messages.fL(converterCmd));
|
|
5164
|
+
console.log(messages.Aj(xcodebuildCmd));
|
|
5148
5165
|
}
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
if ('success' === type) return pintor__rspack_import_0_default().green(GLYPH);
|
|
5153
|
-
if ('debug' === type) return pintor__rspack_import_0_default().dim(pintor__rspack_import_0_default().gray(DEBUG_GLYPH));
|
|
5154
|
-
return pintor__rspack_import_0_default().gray(GLYPH);
|
|
5166
|
+
var safari_config = __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
|
|
5167
|
+
function isMacOS() {
|
|
5168
|
+
return 'darwin' === process.platform;
|
|
5155
5169
|
}
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
try {
|
|
5170
|
-
return 'string' == typeof input ? input : JSON.stringify(input);
|
|
5171
|
-
} catch {
|
|
5172
|
-
return String(input);
|
|
5173
|
-
}
|
|
5174
|
-
})();
|
|
5175
|
-
return s.length > max ? `${s.slice(0, max)}…` : s;
|
|
5170
|
+
function activeDeveloperDir() {
|
|
5171
|
+
try {
|
|
5172
|
+
const result = (0, external_node_child_process_.spawnSync)('xcode-select', [
|
|
5173
|
+
'-p'
|
|
5174
|
+
], {
|
|
5175
|
+
encoding: 'utf8',
|
|
5176
|
+
timeout: 15000
|
|
5177
|
+
});
|
|
5178
|
+
if (0 !== result.status) return null;
|
|
5179
|
+
const resolved = String(result.stdout || '').trim();
|
|
5180
|
+
return resolved.length > 0 ? resolved : null;
|
|
5181
|
+
} catch {
|
|
5182
|
+
return null;
|
|
5176
5183
|
}
|
|
5177
|
-
}
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5184
|
+
}
|
|
5185
|
+
function findWithXcrun(tool) {
|
|
5186
|
+
try {
|
|
5187
|
+
const result = (0, external_node_child_process_.spawnSync)('xcrun', [
|
|
5188
|
+
'--find',
|
|
5189
|
+
tool
|
|
5190
|
+
], {
|
|
5191
|
+
encoding: 'utf8',
|
|
5192
|
+
timeout: 15000
|
|
5193
|
+
});
|
|
5194
|
+
if (0 !== result.status) return null;
|
|
5195
|
+
const resolved = String(result.stdout || '').trim();
|
|
5196
|
+
return resolved.length > 0 ? resolved : null;
|
|
5197
|
+
} catch {
|
|
5198
|
+
return null;
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
function detectSafariToolchain() {
|
|
5202
|
+
const platformOk = isMacOS();
|
|
5203
|
+
if (!platformOk) return {
|
|
5204
|
+
platformOk: false,
|
|
5205
|
+
developerDir: null,
|
|
5206
|
+
needsFullXcode: false,
|
|
5207
|
+
converter: null,
|
|
5208
|
+
xcodebuild: null,
|
|
5209
|
+
ok: false
|
|
5210
|
+
};
|
|
5211
|
+
const developerDir = activeDeveloperDir();
|
|
5212
|
+
const needsFullXcode = !developerDir || /CommandLineTools/i.test(developerDir);
|
|
5213
|
+
const converter = findWithXcrun('safari-web-extension-converter');
|
|
5214
|
+
const xcodebuild = findWithXcrun('xcodebuild');
|
|
5215
|
+
return {
|
|
5216
|
+
platformOk,
|
|
5217
|
+
developerDir,
|
|
5218
|
+
needsFullXcode,
|
|
5219
|
+
converter,
|
|
5220
|
+
xcodebuild,
|
|
5221
|
+
ok: Boolean(converter && xcodebuild)
|
|
5222
|
+
};
|
|
5223
|
+
}
|
|
5224
|
+
function fallbackLogger() {
|
|
5225
|
+
return {
|
|
5226
|
+
info: (...a)=>console.log(...a),
|
|
5227
|
+
warn: (...a)=>console.warn(...a),
|
|
5228
|
+
error: (...a)=>console.error(...a),
|
|
5229
|
+
debug: (...a)=>console?.debug?.(...a)
|
|
5230
|
+
};
|
|
5231
|
+
}
|
|
5232
|
+
function isTestEnv() {
|
|
5233
|
+
return Boolean(process.env.VITEST || process.env.VITEST_WORKER_ID);
|
|
5234
|
+
}
|
|
5235
|
+
function delay(ms) {
|
|
5236
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
5237
|
+
}
|
|
5238
|
+
const TOOL_TAIL_LINES = 50;
|
|
5239
|
+
const TOOL_TAIL_BYTES = 8192;
|
|
5240
|
+
function toolOutputTail(output) {
|
|
5241
|
+
const lines = output.slice(4 * -TOOL_TAIL_BYTES).split(/\r?\n/).filter((line)=>line.trim().length > 0);
|
|
5242
|
+
const tail = lines.slice(-TOOL_TAIL_LINES).join('\n');
|
|
5243
|
+
return tail.length > TOOL_TAIL_BYTES ? tail.slice(-TOOL_TAIL_BYTES) : tail;
|
|
5244
|
+
}
|
|
5245
|
+
function runTool(bin, args, opts) {
|
|
5246
|
+
const streamOutput = (0, messaging._o)() && !opts?.quiet;
|
|
5247
|
+
return new Promise((resolve)=>{
|
|
5248
|
+
let output = '';
|
|
5249
|
+
const child = (0, external_node_child_process_.spawn)(bin, args, {
|
|
5250
|
+
stdio: [
|
|
5251
|
+
'ignore',
|
|
5252
|
+
'pipe',
|
|
5253
|
+
'pipe'
|
|
5254
|
+
]
|
|
5255
|
+
});
|
|
5256
|
+
const onChunk = (chunk)=>{
|
|
5257
|
+
const text = String(chunk);
|
|
5258
|
+
output += text;
|
|
5259
|
+
if (output.length > 8 * TOOL_TAIL_BYTES) output = output.slice(4 * -TOOL_TAIL_BYTES);
|
|
5260
|
+
if (streamOutput) process.stdout.write(text);
|
|
5261
|
+
};
|
|
5262
|
+
child.stdout?.on('data', onChunk);
|
|
5263
|
+
child.stderr?.on('data', onChunk);
|
|
5264
|
+
child.on('error', (error)=>resolve({
|
|
5265
|
+
ok: false,
|
|
5266
|
+
code: null,
|
|
5267
|
+
output: `${output}${String(error)}`
|
|
5268
|
+
}));
|
|
5269
|
+
child.on('close', (code)=>resolve({
|
|
5270
|
+
ok: 0 === code,
|
|
5271
|
+
code,
|
|
5272
|
+
output
|
|
5273
|
+
}));
|
|
5186
5274
|
});
|
|
5187
|
-
return [
|
|
5188
|
-
head,
|
|
5189
|
-
...body
|
|
5190
|
-
].join('\n');
|
|
5191
5275
|
}
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
function isCardKeyClaimed(key) {
|
|
5195
|
-
const claimed = String(process.env[CARD_KEYS_ENV] || '');
|
|
5196
|
-
if (!claimed) return false;
|
|
5197
|
-
return claimed.split(CARD_KEYS_SEPARATOR).includes(key);
|
|
5276
|
+
function converterWarnings(output) {
|
|
5277
|
+
return output.split(/\r?\n/).filter((line)=>/warning/i.test(line)).map((line)=>line.trim()).filter((line)=>line.length > 0);
|
|
5198
5278
|
}
|
|
5199
|
-
function
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5279
|
+
async function confirmRegisteredWithSafari(bundleIdentifier) {
|
|
5280
|
+
const needle = `${bundleIdentifier}.Extension`;
|
|
5281
|
+
for(let attempt = 0; attempt < 6; attempt += 1){
|
|
5282
|
+
const { ok, output } = await runTool('pluginkit', [
|
|
5283
|
+
'-m'
|
|
5284
|
+
], {
|
|
5285
|
+
quiet: true
|
|
5286
|
+
});
|
|
5287
|
+
if (ok && output.includes(needle)) return true;
|
|
5288
|
+
await delay(800);
|
|
5289
|
+
}
|
|
5290
|
+
return false;
|
|
5204
5291
|
}
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
if (GECKO_BROWSERS.has(name)) return 'Add-on';
|
|
5215
|
-
if (name.includes('gecko') || name.includes('firefox')) return 'Add-on';
|
|
5216
|
-
return 'Extension';
|
|
5292
|
+
function describePackage(config) {
|
|
5293
|
+
return {
|
|
5294
|
+
appName: config.appName,
|
|
5295
|
+
bundleId: config.bundleIdentifier,
|
|
5296
|
+
bundleIdDerived: config.bundleIdDerived,
|
|
5297
|
+
appPath: (0, safari_config.fd)(config),
|
|
5298
|
+
xcodeProjectPath: (0, safari_config.Gi)(config),
|
|
5299
|
+
macOsOnly: config.macOsOnly
|
|
5300
|
+
};
|
|
5217
5301
|
}
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
E_INTERNAL: 'E_INTERNAL',
|
|
5238
|
-
E_UNSUPPORTED_BROWSER: 'E_UNSUPPORTED_BROWSER',
|
|
5239
|
-
E_INVALID_OPTION: 'E_INVALID_OPTION',
|
|
5240
|
-
E_PORT_UNAVAILABLE: 'E_PORT_UNAVAILABLE',
|
|
5241
|
-
E_DEPENDENCY_INSTALL: 'E_DEPENDENCY_INSTALL',
|
|
5242
|
-
E_TEMPLATE_NOT_FOUND: 'E_TEMPLATE_NOT_FOUND',
|
|
5243
|
-
E_DESTINATION_NOT_EMPTY: 'E_DESTINATION_NOT_EMPTY',
|
|
5244
|
-
E_DESTINATION_NOT_WRITABLE: 'E_DESTINATION_NOT_WRITABLE',
|
|
5245
|
-
E_BROWSER_DOWNLOAD: 'E_BROWSER_DOWNLOAD',
|
|
5246
|
-
E_SESSION_NOT_FOUND: 'E_SESSION_NOT_FOUND',
|
|
5247
|
-
E_EVAL_REFUSED: 'E_EVAL_REFUSED',
|
|
5248
|
-
E_TARGET_NOT_FOUND: 'E_TARGET_NOT_FOUND',
|
|
5249
|
-
E_TIMEOUT: 'E_TIMEOUT',
|
|
5250
|
-
E_PUBLISH_REJECTED: 'E_PUBLISH_REJECTED',
|
|
5251
|
-
E_AUTH_REQUIRED: 'E_AUTH_REQUIRED',
|
|
5252
|
-
E_SAFARI_TOOLCHAIN: 'E_SAFARI_TOOLCHAIN',
|
|
5253
|
-
E_EVAL: 'E_EVAL',
|
|
5254
|
-
E_INSPECT: 'E_INSPECT',
|
|
5255
|
-
E_STORAGE: 'E_STORAGE',
|
|
5256
|
-
E_LOGS_NOT_FOUND: 'E_LOGS_NOT_FOUND',
|
|
5257
|
-
E_READY_ERROR_STATUS: 'E_READY_ERROR_STATUS',
|
|
5258
|
-
E_COMMAND_UNSUPPORTED_FOR_TARGET: 'E_COMMAND_UNSUPPORTED_FOR_TARGET',
|
|
5259
|
-
E_FLAG_VALUE_INVALID: 'E_FLAG_VALUE_INVALID',
|
|
5260
|
-
E_FLAG_NOT_SUPPORTED_HERE: 'E_FLAG_NOT_SUPPORTED_HERE',
|
|
5261
|
-
E_DEV_SERVER_START: 'E_DEV_SERVER_START',
|
|
5262
|
-
E_DOCTOR_CHECKS_FAILED: 'E_DOCTOR_CHECKS_FAILED',
|
|
5263
|
-
E_TELEMETRY_WRITE: 'E_TELEMETRY_WRITE',
|
|
5264
|
-
E_PREVIEW_NO_DIST: 'E_PREVIEW_NO_DIST',
|
|
5265
|
-
E_BROWSER_UNINSTALL: 'E_BROWSER_UNINSTALL',
|
|
5266
|
-
E_NODE_VERSION: 'E_NODE_VERSION',
|
|
5267
|
-
E_UNKNOWN_COMMAND: 'E_UNKNOWN_COMMAND',
|
|
5268
|
-
E_REMOVED_FLAG: 'E_REMOVED_FLAG',
|
|
5269
|
-
E_BROWSER_NOT_INSTALLABLE: 'E_BROWSER_NOT_INSTALLABLE',
|
|
5270
|
-
E_PARENT_GONE: 'E_PARENT_GONE',
|
|
5271
|
-
E_REMOTE_URL_UNSUPPORTED: 'E_REMOTE_URL_UNSUPPORTED',
|
|
5272
|
-
E_CONFIG_LOAD: 'E_CONFIG_LOAD',
|
|
5273
|
-
E_MANAGED_DEP_CONFLICT: 'E_MANAGED_DEP_CONFLICT',
|
|
5274
|
-
E_TYPES_EMIT: 'E_TYPES_EMIT',
|
|
5275
|
-
E_TSCONFIG_MISSING: 'E_TSCONFIG_MISSING',
|
|
5276
|
-
E_OPTIONAL_DEP_UNRESOLVED: 'E_OPTIONAL_DEP_UNRESOLVED',
|
|
5277
|
-
E_OPTIONAL_DEP_LOAD: 'E_OPTIONAL_DEP_LOAD',
|
|
5278
|
-
E_OPTIONAL_DEP_UNKNOWN: 'E_OPTIONAL_DEP_UNKNOWN',
|
|
5279
|
-
E_COMPANION_EXTENSION_PATH: 'E_COMPANION_EXTENSION_PATH',
|
|
5280
|
-
E_MANIFEST_IN_PUBLIC: 'E_MANIFEST_IN_PUBLIC',
|
|
5281
|
-
E_RUNTIME_NOT_FOUND: 'E_RUNTIME_NOT_FOUND',
|
|
5282
|
-
E_MANIFEST_SHAPE: 'E_MANIFEST_SHAPE',
|
|
5283
|
-
E_MANIFEST_PAGE_MISSING: 'E_MANIFEST_PAGE_MISSING',
|
|
5284
|
-
E_MANIFEST_VERSION_UNSUPPORTED: 'E_MANIFEST_VERSION_UNSUPPORTED',
|
|
5285
|
-
E_MANIFEST_LOAD_BLOCKERS: 'E_MANIFEST_LOAD_BLOCKERS',
|
|
5286
|
-
E_MANIFEST_PERMISSION_MISSING: 'E_MANIFEST_PERMISSION_MISSING',
|
|
5287
|
-
E_MANIFEST_MSG_KEY_MISSING: 'E_MANIFEST_MSG_KEY_MISSING',
|
|
5288
|
-
E_MANIFEST_EMIT: 'E_MANIFEST_EMIT',
|
|
5289
|
-
E_RESTART_REQUIRED: 'E_RESTART_REQUIRED',
|
|
5290
|
-
E_COMPILE_FATAL: 'E_COMPILE_FATAL',
|
|
5291
|
-
E_MODULE_NOT_FOUND: 'E_MODULE_NOT_FOUND',
|
|
5292
|
-
E_ENTRY_NOT_FOUND: 'E_ENTRY_NOT_FOUND',
|
|
5293
|
-
E_ASSET_MISSING: 'E_ASSET_MISSING',
|
|
5294
|
-
E_SCRIPT_DEP_MISSING: 'E_SCRIPT_DEP_MISSING',
|
|
5295
|
-
E_RESERVED_FOLDER: 'E_RESERVED_FOLDER',
|
|
5296
|
-
E_CSS_PARSE: 'E_CSS_PARSE',
|
|
5297
|
-
E_CSS_PREPROCESSOR_MISSING: 'E_CSS_PREPROCESSOR_MISSING',
|
|
5298
|
-
E_CSS_DEAD_REF: 'E_CSS_DEAD_REF',
|
|
5299
|
-
E_INTEGRATION_INSTALL: 'E_INTEGRATION_INSTALL',
|
|
5300
|
-
E_POLYFILL_NOT_FOUND: 'E_POLYFILL_NOT_FOUND',
|
|
5301
|
-
E_LOCALES_LAYOUT: 'E_LOCALES_LAYOUT',
|
|
5302
|
-
E_WAR_INVALID: 'E_WAR_INVALID',
|
|
5303
|
-
E_MATCH_PATTERN_INVALID: 'E_MATCH_PATTERN_INVALID',
|
|
5304
|
-
E_BACKGROUND_REQUIRED: 'E_BACKGROUND_REQUIRED',
|
|
5305
|
-
E_CONTENT_SCRIPT_SYNTAX: 'E_CONTENT_SCRIPT_SYNTAX',
|
|
5306
|
-
E_NO_ENTRYPOINTS: 'E_NO_ENTRYPOINTS',
|
|
5307
|
-
E_REMOTE_RESOURCE_BLOCKED: 'E_REMOTE_RESOURCE_BLOCKED',
|
|
5308
|
-
E_PERF_BUDGET: 'E_PERF_BUDGET',
|
|
5309
|
-
E_ZIP_SKIPPED: 'E_ZIP_SKIPPED',
|
|
5310
|
-
E_ENV_NO_MATCH: 'E_ENV_NO_MATCH',
|
|
5311
|
-
E_REMOTE_FETCH_TIMEOUT: 'E_REMOTE_FETCH_TIMEOUT',
|
|
5312
|
-
E_REMOTE_DOWNLOAD: 'E_REMOTE_DOWNLOAD',
|
|
5313
|
-
E_REMOTE_ZIP_INVALID: 'E_REMOTE_ZIP_INVALID',
|
|
5314
|
-
E_LOCAL_ZIP_NOT_FOUND: 'E_LOCAL_ZIP_NOT_FOUND',
|
|
5315
|
-
E_PROJECT_DOWNLOAD_EMPTY: 'E_PROJECT_DOWNLOAD_EMPTY',
|
|
5316
|
-
E_BROWSER_BINARY_REQUIRED: 'E_BROWSER_BINARY_REQUIRED',
|
|
5317
|
-
E_BROWSER_BINARY_INVALID: 'E_BROWSER_BINARY_INVALID',
|
|
5318
|
-
E_BROWSER_EXITED: 'E_BROWSER_EXITED',
|
|
5319
|
-
E_BROWSER_START_TIMEOUT: 'E_BROWSER_START_TIMEOUT',
|
|
5320
|
-
E_LAUNCH_SKIPPED_COMPILE_ERRORS: 'E_LAUNCH_SKIPPED_COMPILE_ERRORS',
|
|
5321
|
-
E_INSTANCE_AMBIGUOUS: 'E_INSTANCE_AMBIGUOUS',
|
|
5322
|
-
E_WSL_INTEROP: 'E_WSL_INTEROP',
|
|
5323
|
-
E_EXTENSION_LOAD_REFUSED: 'E_EXTENSION_LOAD_REFUSED',
|
|
5324
|
-
E_ADDON_INSTALL: 'E_ADDON_INSTALL',
|
|
5325
|
-
E_BROWSER_CONNECT: 'E_BROWSER_CONNECT',
|
|
5326
|
-
E_BROWSER_CONNECTION_CLOSED: 'E_BROWSER_CONNECTION_CLOSED',
|
|
5327
|
-
E_CDP_NOT_CONNECTED: 'E_CDP_NOT_CONNECTED',
|
|
5328
|
-
E_CDP_TIMEOUT: 'E_CDP_TIMEOUT',
|
|
5329
|
-
E_CDP_OP_FAILED: 'E_CDP_OP_FAILED',
|
|
5330
|
-
E_EXTENSION_ID_UNKNOWN: 'E_EXTENSION_ID_UNKNOWN',
|
|
5331
|
-
E_RDP_PROTOCOL: 'E_RDP_PROTOCOL',
|
|
5332
|
-
E_DEV_SERVER_TIMEOUT: 'E_DEV_SERVER_TIMEOUT',
|
|
5333
|
-
E_PORT_IN_USE: 'E_PORT_IN_USE',
|
|
5334
|
-
E_SESSION_STOPPED: 'E_SESSION_STOPPED',
|
|
5335
|
-
E_LOGS_STREAM_GAP: 'E_LOGS_STREAM_GAP',
|
|
5336
|
-
E_CREATE_DIR: 'E_CREATE_DIR',
|
|
5337
|
-
E_CREATE_WRITE: 'E_CREATE_WRITE',
|
|
5338
|
-
E_CREATE_TESTS_SETUP: 'E_CREATE_TESTS_SETUP',
|
|
5339
|
-
E_GIT_SKIPPED: 'E_GIT_SKIPPED',
|
|
5340
|
-
E_BROWSER_INSTALL_PRIVILEGE: 'E_BROWSER_INSTALL_PRIVILEGE',
|
|
5341
|
-
E_UNINSTALL_NOOP: 'E_UNINSTALL_NOOP'
|
|
5342
|
-
};
|
|
5343
|
-
function withExtras(base, extras) {
|
|
5302
|
+
function safariPreflightError() {
|
|
5303
|
+
const tc = detectSafariToolchain();
|
|
5304
|
+
if (!tc.platformOk) return messages.G3(process.platform);
|
|
5305
|
+
if (!tc.ok) {
|
|
5306
|
+
if (tc.needsFullXcode) return messages.Xi(tc.developerDir);
|
|
5307
|
+
return messages.Cs(tc.converter ? 'xcodebuild' : 'safari-web-extension-converter');
|
|
5308
|
+
}
|
|
5309
|
+
return null;
|
|
5310
|
+
}
|
|
5311
|
+
function safariBuildPreflight() {
|
|
5312
|
+
const tc = detectSafariToolchain();
|
|
5313
|
+
if (!tc.platformOk) return {
|
|
5314
|
+
severity: 'skip',
|
|
5315
|
+
message: messages.UW(process.platform)
|
|
5316
|
+
};
|
|
5317
|
+
if (!tc.ok) return {
|
|
5318
|
+
severity: 'fatal',
|
|
5319
|
+
message: tc.needsFullXcode ? messages.Xi(tc.developerDir) : messages.Cs(tc.converter ? 'xcodebuild' : 'safari-web-extension-converter')
|
|
5320
|
+
};
|
|
5344
5321
|
return {
|
|
5345
|
-
|
|
5346
|
-
...extras.hint ? {
|
|
5347
|
-
hint: extras.hint
|
|
5348
|
-
} : {},
|
|
5349
|
-
...extras.truncated ? {
|
|
5350
|
-
truncated: true
|
|
5351
|
-
} : {},
|
|
5352
|
-
warnings: extras.warnings || []
|
|
5322
|
+
severity: 'ok'
|
|
5353
5323
|
};
|
|
5354
5324
|
}
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
status,
|
|
5363
|
-
value,
|
|
5364
|
-
error: null,
|
|
5365
|
-
warnings: []
|
|
5366
|
-
}, extras);
|
|
5367
|
-
},
|
|
5368
|
-
fail (command, status, error, extras = {}) {
|
|
5369
|
-
return withExtras({
|
|
5370
|
-
schema: ENVELOPE_SCHEMA,
|
|
5371
|
-
ok: false,
|
|
5372
|
-
command,
|
|
5373
|
-
status,
|
|
5374
|
-
value: extras.value ?? null,
|
|
5375
|
-
error,
|
|
5376
|
-
warnings: []
|
|
5377
|
-
}, extras);
|
|
5325
|
+
async function runSafariPipeline(compilation, host, logger, mode) {
|
|
5326
|
+
const config = (0, safari_config.F7)(compilation, host);
|
|
5327
|
+
const converterArgs = (0, safari_config.w7)(config);
|
|
5328
|
+
const xcodebuildArgs = (0, safari_config.vx)(config);
|
|
5329
|
+
if (host.dryRun || isTestEnv()) {
|
|
5330
|
+
logSafariDryRun(`xcrun ${converterArgs.join(' ')}`, `xcodebuild ${xcodebuildArgs.join(' ')}`);
|
|
5331
|
+
return describePackage(config);
|
|
5378
5332
|
}
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5333
|
+
const toolchain = detectSafariToolchain();
|
|
5334
|
+
if (!toolchain.platformOk) {
|
|
5335
|
+
logger.warn?.(messages.G3(process.platform));
|
|
5336
|
+
return describePackage(config);
|
|
5337
|
+
}
|
|
5338
|
+
if (!toolchain.ok) {
|
|
5339
|
+
if (toolchain.needsFullXcode) logger.error?.(messages.Xi(toolchain.developerDir));
|
|
5340
|
+
else {
|
|
5341
|
+
const missing = toolchain.converter ? 'xcodebuild' : 'safari-web-extension-converter';
|
|
5342
|
+
logger.error?.(messages.Cs(missing));
|
|
5343
|
+
}
|
|
5344
|
+
return describePackage(config);
|
|
5345
|
+
}
|
|
5346
|
+
const projectExists = external_node_fs_.existsSync((0, safari_config.Gi)(config));
|
|
5347
|
+
const needsConversion = !projectExists || host.forceRegenerate || (0, safari_config.vk)(config);
|
|
5348
|
+
if (needsConversion) {
|
|
5349
|
+
if (projectExists) {
|
|
5350
|
+
logger.info?.(host.forceRegenerate ? messages.Tq() : messages.jc());
|
|
5351
|
+
logger.warn?.(messages.H1([
|
|
5352
|
+
...safari_config.X9
|
|
5353
|
+
]));
|
|
5354
|
+
}
|
|
5355
|
+
const { saved, restore } = (0, safari_config._D)(config);
|
|
5356
|
+
logger.info?.(messages.uK(config.extensionDir));
|
|
5357
|
+
const converted = await runTool('xcrun', converterArgs);
|
|
5358
|
+
if (!converted.ok) {
|
|
5359
|
+
const tail = toolOutputTail(converted.output);
|
|
5360
|
+
logger.error?.(messages.A('safari-web-extension-converter', converted.code, tail));
|
|
5361
|
+
throw new Error(`safari-web-extension-converter failed (exit ${converted.code})\n${tail}`);
|
|
5362
|
+
}
|
|
5363
|
+
const warnings = converterWarnings(converted.output);
|
|
5364
|
+
if (warnings.length > 0) logger.warn?.(messages.y1(warnings));
|
|
5365
|
+
const projFile = (0, safari_config.vh)(config);
|
|
5366
|
+
if (external_node_fs_.existsSync(projFile)) external_node_fs_.writeFileSync(projFile, (0, safari_config.IA)(external_node_fs_.readFileSync(projFile, 'utf8'), config.bundleIdentifier), 'utf8');
|
|
5367
|
+
restore();
|
|
5368
|
+
const preservedKeys = Object.keys(saved);
|
|
5369
|
+
if (preservedKeys.length > 0) logger.info?.(messages.oB(preservedKeys));
|
|
5370
|
+
(0, safari_config.x7)(config);
|
|
5371
|
+
logger.info?.(messages.l_(config.projectLocation));
|
|
5372
|
+
} else logger.info?.(messages.oM());
|
|
5373
|
+
if ('full' === mode) logger.info?.(messages.jR((0, safari_config.aD)(config)));
|
|
5374
|
+
const built = await runTool('xcodebuild', xcodebuildArgs);
|
|
5375
|
+
if (!built.ok) {
|
|
5376
|
+
const tail = toolOutputTail(built.output);
|
|
5377
|
+
logger.error?.(messages.A('xcodebuild', built.code, tail));
|
|
5378
|
+
throw new Error(`xcodebuild failed (exit ${built.code})\n${tail}`);
|
|
5379
|
+
}
|
|
5380
|
+
const appPath = (0, safari_config.fd)(config);
|
|
5381
|
+
if ('resync' === mode) {
|
|
5382
|
+
logger.info?.(messages.cF(config.appName));
|
|
5383
|
+
return describePackage(config);
|
|
5384
|
+
}
|
|
5385
|
+
logger.info?.(messages.Rl(appPath));
|
|
5386
|
+
if (config.bundleIdDerived) logger.info?.(messages.$q(config.bundleIdentifier));
|
|
5387
|
+
if (!config.open) {
|
|
5388
|
+
logger.info?.(messages.aO(appPath, config.appName));
|
|
5389
|
+
return describePackage(config);
|
|
5390
|
+
}
|
|
5391
|
+
const target = external_node_fs_.existsSync(appPath) ? appPath : (0, safari_config.Gi)(config);
|
|
5392
|
+
logger.info?.(messages.fw(target));
|
|
5393
|
+
await runTool('open', [
|
|
5394
|
+
target
|
|
5395
|
+
]);
|
|
5396
|
+
if (config.safariBinary) await runTool('open', [
|
|
5397
|
+
'-a',
|
|
5398
|
+
config.safariBinary
|
|
5399
|
+
]);
|
|
5400
|
+
logger.info?.(messages.fO(config.appName));
|
|
5401
|
+
if (await confirmRegisteredWithSafari(config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
|
|
5402
|
+
else logger.warn?.(messages.qY(config.appName));
|
|
5403
|
+
return describePackage(config);
|
|
5404
|
+
}
|
|
5405
|
+
async function packageSafariExtension(host, outputPath, logger, mode = 'full') {
|
|
5406
|
+
const compilation = {
|
|
5407
|
+
options: {
|
|
5408
|
+
output: {
|
|
5409
|
+
path: outputPath
|
|
5410
|
+
}
|
|
5411
|
+
},
|
|
5412
|
+
outputOptions: {
|
|
5413
|
+
path: outputPath
|
|
5414
|
+
}
|
|
5415
|
+
};
|
|
5416
|
+
return await runSafariPipeline(compilation, host, logger || fallbackLogger(), mode);
|
|
5417
|
+
}
|
|
5392
5418
|
},
|
|
5393
|
-
"./
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
function
|
|
5397
|
-
const
|
|
5398
|
-
|
|
5399
|
-
if (major !== MIN_NODE_MAJOR) return major > MIN_NODE_MAJOR;
|
|
5400
|
-
return (Number.isFinite(minor) ? minor : 0) >= MIN_NODE_MINOR;
|
|
5419
|
+
"./browsers/run-safari/safari-launch/safari-config.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5420
|
+
var node_fs__rspack_import_0 = __webpack_require__("node:fs");
|
|
5421
|
+
var node_path__rspack_import_1 = __webpack_require__("node:path");
|
|
5422
|
+
function sanitizeAppName(value) {
|
|
5423
|
+
const cleaned = String(value || '').replace(/[\\/:*?"<>|]+/g, ' ').replace(/\s+/g, ' ').trim();
|
|
5424
|
+
return cleaned.length > 0 ? cleaned : 'Extension';
|
|
5401
5425
|
}
|
|
5402
|
-
function
|
|
5403
|
-
return
|
|
5426
|
+
function bundleSegment(appName) {
|
|
5427
|
+
return String(appName || '').replace(/[^A-Za-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'extension';
|
|
5404
5428
|
}
|
|
5405
|
-
function
|
|
5406
|
-
|
|
5407
|
-
console.error(unsupportedNodeVersionMessage(version));
|
|
5408
|
-
process.exit(1);
|
|
5429
|
+
function deriveBundleId(appName) {
|
|
5430
|
+
return `dev.extensionjs.${bundleSegment(appName)}`;
|
|
5409
5431
|
}
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
var external_node_fs_ = __webpack_require__("node:fs");
|
|
5413
|
-
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_);
|
|
5414
|
-
var external_node_path_ = __webpack_require__("node:path");
|
|
5415
|
-
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_);
|
|
5416
|
-
async function exitAfterDrain(code) {
|
|
5417
|
-
await Promise.all([
|
|
5418
|
-
process.stdout,
|
|
5419
|
-
process.stderr
|
|
5420
|
-
].map((stream)=>new Promise((resolve)=>{
|
|
5421
|
-
if (0 === stream.writableLength) return resolve();
|
|
5422
|
-
stream.write('', ()=>resolve());
|
|
5423
|
-
})));
|
|
5424
|
-
process.exit(code);
|
|
5432
|
+
function isValidBundleId(value) {
|
|
5433
|
+
return /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/.test(value);
|
|
5425
5434
|
}
|
|
5426
|
-
|
|
5427
|
-
const external_node_url_namespaceObject = require("node:url");
|
|
5428
|
-
const extension_develop_runtime_require = (0, external_node_module_.createRequire)(__rslib_import_meta_url__);
|
|
5429
|
-
function parseJsonSafe(filePath) {
|
|
5430
|
-
return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf8'));
|
|
5431
|
-
}
|
|
5432
|
-
function resolveDevelopRootFromDir(dir) {
|
|
5433
|
-
try {
|
|
5434
|
-
const packageJsonPath = external_node_path_default().join(dir, 'package.json');
|
|
5435
|
-
if (!external_node_fs_default().existsSync(packageJsonPath)) return;
|
|
5436
|
-
const pkg = parseJsonSafe(packageJsonPath);
|
|
5437
|
-
return pkg?.name === 'extension-develop' ? dir : void 0;
|
|
5438
|
-
} catch {
|
|
5439
|
-
return;
|
|
5440
|
-
}
|
|
5441
|
-
}
|
|
5442
|
-
function resolveWorkspaceDevelopRoot(startDir) {
|
|
5443
|
-
let currentDir = external_node_path_default().resolve(startDir);
|
|
5444
|
-
if (currentDir.split(external_node_path_default().sep).includes('node_modules')) return;
|
|
5445
|
-
for(let depth = 0; depth < 8; depth += 1){
|
|
5446
|
-
const candidate = external_node_path_default().join(currentDir, 'programs', 'develop');
|
|
5447
|
-
const resolved = resolveDevelopRootFromDir(candidate);
|
|
5448
|
-
if (resolved) return resolved;
|
|
5449
|
-
const parent = external_node_path_default().dirname(currentDir);
|
|
5450
|
-
if (parent === currentDir) break;
|
|
5451
|
-
currentDir = parent;
|
|
5452
|
-
}
|
|
5453
|
-
}
|
|
5454
|
-
function resolveInstalledDevelopRoot() {
|
|
5435
|
+
function readManifest(extensionDir) {
|
|
5455
5436
|
try {
|
|
5456
|
-
const
|
|
5457
|
-
|
|
5458
|
-
} catch {
|
|
5459
|
-
|
|
5460
|
-
const entryPath = extension_develop_runtime_require.resolve('extension-develop');
|
|
5461
|
-
return resolveDevelopRootFromDir(external_node_path_default().dirname(external_node_path_default().dirname(entryPath)));
|
|
5462
|
-
} catch {
|
|
5463
|
-
return;
|
|
5464
|
-
}
|
|
5465
|
-
}
|
|
5437
|
+
const manifestPath = node_path__rspack_import_1.join(extensionDir, 'manifest.json');
|
|
5438
|
+
if (node_fs__rspack_import_0.existsSync(manifestPath)) return JSON.parse(node_fs__rspack_import_0.readFileSync(manifestPath, 'utf8')) || {};
|
|
5439
|
+
} catch {}
|
|
5440
|
+
return {};
|
|
5466
5441
|
}
|
|
5467
|
-
function
|
|
5468
|
-
const
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
const
|
|
5474
|
-
|
|
5475
|
-
root: envRoot,
|
|
5476
|
-
source: 'env'
|
|
5477
|
-
};
|
|
5478
|
-
const installedRoot = resolveInstalledDevelopRoot();
|
|
5479
|
-
if (installedRoot) return {
|
|
5480
|
-
root: installedRoot,
|
|
5481
|
-
source: 'installed'
|
|
5482
|
-
};
|
|
5442
|
+
function resolveSafariBuildConfig(compilation, host) {
|
|
5443
|
+
const extensionDir = String(compilation?.options?.output?.path || '');
|
|
5444
|
+
const manifest = readManifest(extensionDir);
|
|
5445
|
+
const appName = sanitizeAppName(String(host.appName || manifest?.name || 'Extension'));
|
|
5446
|
+
const userBundleId = String(host.bundleId || '').trim();
|
|
5447
|
+
const bundleIdDerived = !userBundleId;
|
|
5448
|
+
const bundleIdentifier = bundleIdDerived ? deriveBundleId(appName) : userBundleId;
|
|
5449
|
+
const projectLocation = `${extensionDir.replace(/[\\/]+$/, '')}-xcode`;
|
|
5483
5450
|
return {
|
|
5484
|
-
|
|
5485
|
-
|
|
5451
|
+
extensionDir,
|
|
5452
|
+
projectLocation,
|
|
5453
|
+
appName,
|
|
5454
|
+
bundleIdentifier,
|
|
5455
|
+
bundleIdDerived,
|
|
5456
|
+
macOsOnly: false !== host.macOsOnly,
|
|
5457
|
+
language: 'swift',
|
|
5458
|
+
open: !host.noOpen,
|
|
5459
|
+
safariBinary: host.safariBinary
|
|
5486
5460
|
};
|
|
5487
5461
|
}
|
|
5488
|
-
function
|
|
5489
|
-
const
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5462
|
+
function composeConverterArgs(config) {
|
|
5463
|
+
const args = [
|
|
5464
|
+
'safari-web-extension-converter',
|
|
5465
|
+
config.extensionDir,
|
|
5466
|
+
'--project-location',
|
|
5467
|
+
config.projectLocation,
|
|
5468
|
+
'--app-name',
|
|
5469
|
+
config.appName,
|
|
5470
|
+
'--bundle-identifier',
|
|
5471
|
+
config.bundleIdentifier,
|
|
5472
|
+
'--no-prompt',
|
|
5473
|
+
'--no-open',
|
|
5474
|
+
'--force',
|
|
5475
|
+
'objc' === config.language ? '--objc' : '--swift'
|
|
5495
5476
|
];
|
|
5496
|
-
|
|
5477
|
+
if (config.macOsOnly) args.push('--macos-only');
|
|
5478
|
+
return args;
|
|
5497
5479
|
}
|
|
5498
|
-
function
|
|
5499
|
-
|
|
5500
|
-
if (!root) throw new Error('Unable to locate the extension-develop runtime.');
|
|
5501
|
-
process.env.EXTENSION_DEVELOP_ROOT = root;
|
|
5502
|
-
if ('workspace' === source) process.env.EXTENSION_CREATE_DEVELOP_ROOT = root;
|
|
5503
|
-
return root;
|
|
5480
|
+
function macOsSchemeName(config) {
|
|
5481
|
+
return config.macOsOnly ? config.appName : `${config.appName} (macOS)`;
|
|
5504
5482
|
}
|
|
5505
|
-
function
|
|
5483
|
+
function xcodeProjectPath(config) {
|
|
5484
|
+
return node_path__rspack_import_1.join(config.projectLocation, config.appName, `${config.appName}.xcodeproj`);
|
|
5485
|
+
}
|
|
5486
|
+
function derivedDataPath(config) {
|
|
5487
|
+
return node_path__rspack_import_1.join(config.projectLocation, '.derived');
|
|
5488
|
+
}
|
|
5489
|
+
function builtAppPath(config) {
|
|
5490
|
+
return node_path__rspack_import_1.join(derivedDataPath(config), 'Build', 'Products', 'Release', `${config.appName}.app`);
|
|
5491
|
+
}
|
|
5492
|
+
function composeXcodebuildArgs(config) {
|
|
5493
|
+
return [
|
|
5494
|
+
'-project',
|
|
5495
|
+
xcodeProjectPath(config),
|
|
5496
|
+
'-scheme',
|
|
5497
|
+
macOsSchemeName(config),
|
|
5498
|
+
'-configuration',
|
|
5499
|
+
'Release',
|
|
5500
|
+
'-derivedDataPath',
|
|
5501
|
+
derivedDataPath(config),
|
|
5502
|
+
'CODE_SIGN_IDENTITY=-',
|
|
5503
|
+
'CODE_SIGNING_REQUIRED=NO',
|
|
5504
|
+
'CODE_SIGNING_ALLOWED=YES',
|
|
5505
|
+
'build'
|
|
5506
|
+
];
|
|
5507
|
+
}
|
|
5508
|
+
function manifestFingerprintPath(config) {
|
|
5509
|
+
return node_path__rspack_import_1.join(config.projectLocation, '.manifest-fingerprint');
|
|
5510
|
+
}
|
|
5511
|
+
function stableStringify(obj) {
|
|
5512
|
+
if (null == obj) return JSON.stringify(obj);
|
|
5513
|
+
if ('object' != typeof obj) return JSON.stringify(obj);
|
|
5514
|
+
if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(',')}]`;
|
|
5515
|
+
const keys = Object.keys(obj).sort();
|
|
5516
|
+
return `{${keys.map((k)=>`${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',')}}`;
|
|
5517
|
+
}
|
|
5518
|
+
function readManifestRaw(extensionDir) {
|
|
5506
5519
|
try {
|
|
5507
|
-
|
|
5508
|
-
const packageJsonPath = external_node_path_default().join(root, 'package.json');
|
|
5509
|
-
const pkg = parseJsonSafe(packageJsonPath);
|
|
5510
|
-
return pkg?.version || fallbackVersion || '0.0.0';
|
|
5520
|
+
return node_fs__rspack_import_0.readFileSync(node_path__rspack_import_1.join(extensionDir, 'manifest.json'), 'utf8');
|
|
5511
5521
|
} catch {
|
|
5512
|
-
return
|
|
5522
|
+
return '';
|
|
5513
5523
|
}
|
|
5514
5524
|
}
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
}
|
|
5525
|
+
function normalizeManifest(raw) {
|
|
5526
|
+
try {
|
|
5527
|
+
return stableStringify(JSON.parse(raw));
|
|
5528
|
+
} catch {
|
|
5529
|
+
return raw;
|
|
5530
|
+
}
|
|
5521
5531
|
}
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5532
|
+
function composeProjectFingerprint(config) {
|
|
5533
|
+
return JSON.stringify({
|
|
5534
|
+
v: 2,
|
|
5535
|
+
identity: {
|
|
5536
|
+
appName: config.appName,
|
|
5537
|
+
bundleId: config.bundleIdentifier,
|
|
5538
|
+
macOsOnly: config.macOsOnly
|
|
5539
|
+
},
|
|
5540
|
+
manifest: normalizeManifest(readManifestRaw(config.extensionDir))
|
|
5541
|
+
});
|
|
5529
5542
|
}
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
const fullEntry = resolveDevelopDistEntry(root);
|
|
5536
|
-
if (fullEntry) return importModule(fullEntry);
|
|
5537
|
-
if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_node_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
|
|
5538
|
-
return await import("extension-develop/preview");
|
|
5543
|
+
function saveManifestFingerprint(config) {
|
|
5544
|
+
node_fs__rspack_import_0.mkdirSync(node_path__rspack_import_1.dirname(manifestFingerprintPath(config)), {
|
|
5545
|
+
recursive: true
|
|
5546
|
+
});
|
|
5547
|
+
node_fs__rspack_import_0.writeFileSync(manifestFingerprintPath(config), composeProjectFingerprint(config), 'utf8');
|
|
5539
5548
|
}
|
|
5540
|
-
|
|
5541
|
-
const
|
|
5542
|
-
|
|
5543
|
-
const
|
|
5544
|
-
|
|
5545
|
-
if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_node_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
|
|
5546
|
-
const bridgeSpecifier = 'extension-develop/bridge';
|
|
5547
|
-
return await import(bridgeSpecifier);
|
|
5549
|
+
function isProjectStale(config) {
|
|
5550
|
+
const fpPath = manifestFingerprintPath(config);
|
|
5551
|
+
if (!node_fs__rspack_import_0.existsSync(fpPath)) return true;
|
|
5552
|
+
const stored = node_fs__rspack_import_0.readFileSync(fpPath, 'utf8');
|
|
5553
|
+
return stored !== composeProjectFingerprint(config);
|
|
5548
5554
|
}
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
5552
|
-
function getLoggingPrefix(type) {
|
|
5553
|
-
return (0, messaging.Pl)(type);
|
|
5555
|
+
function alignBundleIdentifiers(pbxprojContent, bundleId) {
|
|
5556
|
+
return pbxprojContent.replace(/PRODUCT_BUNDLE_IDENTIFIER = ("?)([^;"]+)\1;/g, (_match, _quote, value)=>/\.Extension$/.test(String(value)) ? `PRODUCT_BUNDLE_IDENTIFIER = "${bundleId}.Extension";` : `PRODUCT_BUNDLE_IDENTIFIER = "${bundleId}";`);
|
|
5554
5557
|
}
|
|
5555
|
-
const
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5558
|
+
const PRESERVED_SETTINGS = [
|
|
5559
|
+
'DEVELOPMENT_TEAM',
|
|
5560
|
+
'CODE_SIGN_STYLE',
|
|
5561
|
+
'PROVISIONING_PROFILE_SPECIFIER'
|
|
5562
|
+
];
|
|
5563
|
+
function pbxprojPath(config) {
|
|
5564
|
+
return node_path__rspack_import_1.join(xcodeProjectPath(config), 'project.pbxproj');
|
|
5560
5565
|
}
|
|
5561
|
-
function
|
|
5562
|
-
|
|
5566
|
+
function extractXcodeUserSettings(pbxprojContent) {
|
|
5567
|
+
const found = {};
|
|
5568
|
+
for (const key of PRESERVED_SETTINGS){
|
|
5569
|
+
const m = new RegExp(`\\b${key}\\s*=\\s*([^;]+);`).exec(pbxprojContent);
|
|
5570
|
+
if (m) {
|
|
5571
|
+
const val = m[1].trim();
|
|
5572
|
+
if (val && '""' !== val && "''" !== val) found[key] = val;
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
return found;
|
|
5563
5576
|
}
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
name: 'project-name|project-path',
|
|
5570
|
-
required: true
|
|
5571
|
-
}
|
|
5572
|
-
],
|
|
5573
|
-
description: 'Create a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
|
|
5574
|
-
supportsSourceInspection: false
|
|
5575
|
-
},
|
|
5576
|
-
{
|
|
5577
|
-
name: 'dev',
|
|
5578
|
-
positionals: [
|
|
5579
|
-
{
|
|
5580
|
-
name: 'project-path|remote-url',
|
|
5581
|
-
required: false
|
|
5582
|
-
}
|
|
5583
|
-
],
|
|
5584
|
-
description: 'Start the development server with hot reloading',
|
|
5585
|
-
supportsSourceInspection: true
|
|
5586
|
-
},
|
|
5587
|
-
{
|
|
5588
|
-
name: 'start',
|
|
5589
|
-
positionals: [
|
|
5590
|
-
{
|
|
5591
|
-
name: 'project-path|remote-url',
|
|
5592
|
-
required: false
|
|
5593
|
-
}
|
|
5594
|
-
],
|
|
5595
|
-
description: 'Build and start the extension in production mode',
|
|
5596
|
-
supportsSourceInspection: false
|
|
5597
|
-
},
|
|
5598
|
-
{
|
|
5599
|
-
name: 'preview',
|
|
5600
|
-
positionals: [
|
|
5601
|
-
{
|
|
5602
|
-
name: 'project-name',
|
|
5603
|
-
required: false,
|
|
5604
|
-
label: 'project-path|remote-url'
|
|
5605
|
-
}
|
|
5606
|
-
],
|
|
5607
|
-
description: 'Preview the extension in production mode without building',
|
|
5608
|
-
supportsSourceInspection: false
|
|
5609
|
-
},
|
|
5610
|
-
{
|
|
5611
|
-
name: 'build',
|
|
5612
|
-
positionals: [
|
|
5613
|
-
{
|
|
5614
|
-
name: 'project-name',
|
|
5615
|
-
required: false,
|
|
5616
|
-
label: 'project-path|remote-url'
|
|
5617
|
-
}
|
|
5618
|
-
],
|
|
5619
|
-
description: 'Build the extension for packaging and distribution',
|
|
5620
|
-
supportsSourceInspection: false
|
|
5621
|
-
},
|
|
5622
|
-
{
|
|
5623
|
-
name: 'logs',
|
|
5624
|
-
positionals: [
|
|
5625
|
-
{
|
|
5626
|
-
name: 'project-path',
|
|
5627
|
-
required: false
|
|
5628
|
-
}
|
|
5629
|
-
],
|
|
5630
|
-
description: 'Print or stream logs from every context of a running dev session',
|
|
5631
|
-
supportsSourceInspection: false
|
|
5632
|
-
},
|
|
5633
|
-
{
|
|
5634
|
-
name: 'eval',
|
|
5635
|
-
positionals: [
|
|
5636
|
-
{
|
|
5637
|
-
name: 'expression',
|
|
5638
|
-
required: true
|
|
5639
|
-
},
|
|
5640
|
-
{
|
|
5641
|
-
name: 'project-path',
|
|
5642
|
-
required: false
|
|
5643
|
-
}
|
|
5644
|
-
],
|
|
5645
|
-
description: 'Evaluate an expression in a running extension context (requires --allow-eval)',
|
|
5646
|
-
supportsSourceInspection: false
|
|
5647
|
-
},
|
|
5648
|
-
{
|
|
5649
|
-
name: 'storage',
|
|
5650
|
-
positionals: [
|
|
5651
|
-
{
|
|
5652
|
-
name: 'action',
|
|
5653
|
-
required: true,
|
|
5654
|
-
values: [
|
|
5655
|
-
'get',
|
|
5656
|
-
'set'
|
|
5657
|
-
]
|
|
5658
|
-
},
|
|
5659
|
-
{
|
|
5660
|
-
name: 'project-path',
|
|
5661
|
-
required: false
|
|
5662
|
-
}
|
|
5663
|
-
],
|
|
5664
|
-
description: 'Read or write chrome.storage in a running extension (requires --allow-control)',
|
|
5665
|
-
supportsSourceInspection: false
|
|
5666
|
-
},
|
|
5667
|
-
{
|
|
5668
|
-
name: 'reload',
|
|
5669
|
-
positionals: [
|
|
5670
|
-
{
|
|
5671
|
-
name: 'project-path',
|
|
5672
|
-
required: false
|
|
5673
|
-
}
|
|
5674
|
-
],
|
|
5675
|
-
description: 'Reload a running extension or tab (requires --allow-control)',
|
|
5676
|
-
supportsSourceInspection: false
|
|
5677
|
-
},
|
|
5678
|
-
{
|
|
5679
|
-
name: 'open',
|
|
5680
|
-
positionals: [
|
|
5681
|
-
{
|
|
5682
|
-
name: 'surface',
|
|
5683
|
-
required: true,
|
|
5684
|
-
values: [
|
|
5685
|
-
'popup',
|
|
5686
|
-
'options',
|
|
5687
|
-
'sidebar',
|
|
5688
|
-
'action',
|
|
5689
|
-
'command'
|
|
5690
|
-
]
|
|
5691
|
-
},
|
|
5692
|
-
{
|
|
5693
|
-
name: 'project-path',
|
|
5694
|
-
required: false
|
|
5695
|
-
}
|
|
5696
|
-
],
|
|
5697
|
-
description: 'Open an extension surface: popup, options, sidebar, action, or command (requires --allow-control)',
|
|
5698
|
-
supportsSourceInspection: false
|
|
5699
|
-
},
|
|
5700
|
-
{
|
|
5701
|
-
name: 'inspect',
|
|
5702
|
-
positionals: [
|
|
5703
|
-
{
|
|
5704
|
-
name: 'project-path',
|
|
5705
|
-
required: false
|
|
5706
|
-
}
|
|
5707
|
-
],
|
|
5708
|
-
description: 'Inspect a page or content DOM through the agent bridge (CDP-free; requires --allow-control)',
|
|
5709
|
-
supportsSourceInspection: true
|
|
5710
|
-
},
|
|
5711
|
-
{
|
|
5712
|
-
name: 'publish',
|
|
5713
|
-
positionals: [
|
|
5714
|
-
{
|
|
5715
|
-
name: 'project-path',
|
|
5716
|
-
required: false
|
|
5717
|
-
}
|
|
5718
|
-
],
|
|
5719
|
-
description: 'Publish to extension.dev and print a shareable URL (requires EXTENSION_DEV_TOKEN)',
|
|
5720
|
-
supportsSourceInspection: false
|
|
5721
|
-
},
|
|
5722
|
-
{
|
|
5723
|
-
name: 'install',
|
|
5724
|
-
positionals: [
|
|
5725
|
-
{
|
|
5726
|
-
name: 'browser-name',
|
|
5727
|
-
required: false
|
|
5728
|
-
}
|
|
5729
|
-
],
|
|
5730
|
-
description: 'Install a managed browser binary into the Extension.js cache',
|
|
5731
|
-
detail: 'Defaults to chromium when no browser is named.',
|
|
5732
|
-
supportsSourceInspection: false,
|
|
5733
|
-
notes: [
|
|
5734
|
-
{
|
|
5735
|
-
usage: '--browser <chrome|chromium|edge|firefox|chromium-based|gecko-based|firefox-based|all>',
|
|
5736
|
-
description: 'Install multiple browsers, browser families, or all'
|
|
5737
|
-
},
|
|
5738
|
-
{
|
|
5739
|
-
usage: '--where',
|
|
5740
|
-
description: 'Print the managed browser cache root (or browser install path(s) when a browser name or --browser is provided)'
|
|
5741
|
-
}
|
|
5742
|
-
]
|
|
5743
|
-
},
|
|
5744
|
-
{
|
|
5745
|
-
name: 'uninstall',
|
|
5746
|
-
positionals: [
|
|
5747
|
-
{
|
|
5748
|
-
name: 'browser-name',
|
|
5749
|
-
required: false
|
|
5750
|
-
}
|
|
5751
|
-
],
|
|
5752
|
-
description: 'Remove managed browser binaries from the Extension.js cache',
|
|
5753
|
-
supportsSourceInspection: false,
|
|
5754
|
-
notes: [
|
|
5755
|
-
{
|
|
5756
|
-
usage: '--all',
|
|
5757
|
-
description: 'Remove every managed browser binary'
|
|
5758
|
-
},
|
|
5759
|
-
{
|
|
5760
|
-
usage: '--where',
|
|
5761
|
-
description: 'Print the managed browser cache root (or browser install path(s) when --browser/--all is provided)'
|
|
5762
|
-
}
|
|
5763
|
-
]
|
|
5764
|
-
},
|
|
5765
|
-
{
|
|
5766
|
-
name: 'telemetry',
|
|
5767
|
-
positionals: [
|
|
5768
|
-
{
|
|
5769
|
-
name: 'action',
|
|
5770
|
-
required: false,
|
|
5771
|
-
values: [
|
|
5772
|
-
'enable',
|
|
5773
|
-
'disable',
|
|
5774
|
-
'status'
|
|
5775
|
-
]
|
|
5776
|
-
}
|
|
5777
|
-
],
|
|
5778
|
-
description: 'Manage anonymous telemetry consent (enable, disable, or show status)',
|
|
5779
|
-
supportsSourceInspection: false
|
|
5780
|
-
},
|
|
5781
|
-
{
|
|
5782
|
-
name: 'doctor',
|
|
5783
|
-
positionals: [
|
|
5784
|
-
{
|
|
5785
|
-
name: 'project-path',
|
|
5786
|
-
required: false
|
|
5787
|
-
}
|
|
5788
|
-
],
|
|
5789
|
-
description: 'Diagnose a dev session: ready contract, control channel, token, executor, browser',
|
|
5790
|
-
supportsSourceInspection: false
|
|
5577
|
+
function applyXcodeUserSettings(pbxprojContent, settings) {
|
|
5578
|
+
let result = pbxprojContent;
|
|
5579
|
+
for (const [key, value] of Object.entries(settings)){
|
|
5580
|
+
const existing = new RegExp(`\\b${key}\\s*=\\s*[^;]+;`, 'g');
|
|
5581
|
+
result = existing.test(result) ? result.replace(existing, `${key} = ${value};`) : result.replace(/buildSettings\s*=\s*\{/g, `buildSettings = {\n\t\t\t\t${key} = ${value};`);
|
|
5791
5582
|
}
|
|
5792
|
-
|
|
5793
|
-
const COMMANDS = COMMAND_TABLE.map((entry)=>({
|
|
5794
|
-
...entry,
|
|
5795
|
-
args: commandArgSignature(entry.positionals)
|
|
5796
|
-
}));
|
|
5797
|
-
const commandDescriptions = Object.fromEntries(COMMANDS.map((spec)=>[
|
|
5798
|
-
spec.name,
|
|
5799
|
-
spec.description
|
|
5800
|
-
]));
|
|
5801
|
-
function commandHelpEntry(spec) {
|
|
5802
|
-
const signature = spec.args ? ` ${messages_arg(spec.args)}` : '';
|
|
5803
|
-
const lines = [
|
|
5804
|
-
`- ${messages_code(`extension ${spec.name}`)}${signature}`,
|
|
5805
|
-
` ${spec.description}`
|
|
5806
|
-
];
|
|
5807
|
-
if (spec.detail) lines.push(` ${spec.detail}`);
|
|
5808
|
-
for (const note of spec.notes ?? [])lines.push('', `- ${messages_code(`extension ${spec.name}`)} ${messages_arg(note.usage)}`, ` ${note.description}`);
|
|
5809
|
-
return lines.join('\n');
|
|
5810
|
-
}
|
|
5811
|
-
function availableCommandsBlock() {
|
|
5812
|
-
return COMMANDS.map(commandHelpEntry).join('\n\n');
|
|
5813
|
-
}
|
|
5814
|
-
function unhandledError(err) {
|
|
5815
|
-
const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : messaging.Sc.truncate(err);
|
|
5816
|
-
return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
|
|
5817
|
-
}
|
|
5818
|
-
function updateFailed(err) {
|
|
5819
|
-
return `${getLoggingPrefix('warn')} Couldn't check for updates.\n${external_pintor_default().yellow('The command continues without the update check.')}\n${external_pintor_default().yellow(String(err?.message || err))}`;
|
|
5583
|
+
return result;
|
|
5820
5584
|
}
|
|
5821
|
-
function
|
|
5822
|
-
const
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
const message = `${getLoggingPrefix('info')} 🧩 An ${external_pintor_default().blue('Extension.js')} update is available.\n\nYou are on version ${external_pintor_default().red(String(packageJson.version))}.\nThe latest stable is ${external_pintor_default().green(latest)}.\nSee what's new: ${external_pintor_default().underline(releaseNotesUrl)}\nUpdate to the latest stable to get fixes and new features.`;
|
|
5585
|
+
function backupAndRestoreXcodeSettings(config) {
|
|
5586
|
+
const projFile = pbxprojPath(config);
|
|
5587
|
+
let saved = {};
|
|
5588
|
+
if (node_fs__rspack_import_0.existsSync(projFile)) saved = extractXcodeUserSettings(node_fs__rspack_import_0.readFileSync(projFile, 'utf8'));
|
|
5826
5589
|
return {
|
|
5827
|
-
|
|
5828
|
-
|
|
5590
|
+
saved,
|
|
5591
|
+
restore () {
|
|
5592
|
+
if (0 === Object.keys(saved).length) return;
|
|
5593
|
+
if (!node_fs__rspack_import_0.existsSync(projFile)) return;
|
|
5594
|
+
const content = node_fs__rspack_import_0.readFileSync(projFile, 'utf8');
|
|
5595
|
+
node_fs__rspack_import_0.writeFileSync(projFile, applyXcodeUserSettings(content, saved), 'utf8');
|
|
5596
|
+
}
|
|
5829
5597
|
};
|
|
5830
5598
|
}
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
Build Options
|
|
5867
|
-
- ${messages_code('--zip')} ${messages_arg('[boolean]')} Create ZIP archive of built extension
|
|
5868
|
-
- ${messages_code('--zip-source')} ${messages_arg('[boolean]')} Include source files in ZIP
|
|
5869
|
-
- ${messages_code('--zip-filename')} ${messages_arg('<name>')} Custom ZIP filename
|
|
5870
|
-
|
|
5871
|
-
${external_pintor_default().underline('Centralized Logger (terminal output)')}
|
|
5872
|
-
- The manager extension embeds a centralized logger that streams events to the CLI.
|
|
5873
|
-
- Enable and filter logs directly via ${messages_code('extension dev')} flags:
|
|
5874
|
-
- ${messages_code('--logs')} ${messages_arg('<off|error|warn|info|debug|trace>')} Minimum level (default: off)
|
|
5875
|
-
- ${messages_code('--log-context')} ${messages_arg('<list|all>')} Contexts: background,content,page,sidebar,popup,options,devtools
|
|
5876
|
-
- ${messages_code('--log-format')} ${messages_arg('<pretty|json|ndjson>')} Output format (default: pretty)
|
|
5877
|
-
- ${messages_code('--no-log-timestamps')} Hide ISO timestamps in pretty output
|
|
5878
|
-
- ${messages_code('--no-log-color')} Disable color in pretty output
|
|
5879
|
-
- ${messages_code('--log-url')} ${messages_arg('<substring|/regex/>')} Filter by event.url
|
|
5880
|
-
- ${messages_code('--log-tab')} ${messages_arg('<id>')} Filter by tabId
|
|
5881
|
-
- Example: ${messages_code('extension dev ./my-ext --logs=debug --log-context=all --log-format=pretty')}
|
|
5882
|
-
|
|
5883
|
-
${messages_code('extension --help')}
|
|
5884
|
-
This command outputs a help file with key command options.
|
|
5885
|
-
|
|
5886
|
-
${external_pintor_default().underline('Path Resolution (important)')}
|
|
5887
|
-
- Leading ${messages_code('/')} in manifest/HTML means extension root (the directory containing ${messages_code('manifest.json')}).
|
|
5888
|
-
- Relative paths resolve from the ${messages_code('manifest.json')} directory.
|
|
5889
|
-
- Absolute OS paths are used as-is.
|
|
5890
|
-
|
|
5891
|
-
AI Assistants
|
|
5892
|
-
- For AI-oriented guidance and deeper tips, run ${messages_code('extension --ai-help')}
|
|
5893
|
-
- For machine-readable AI guidance, run ${messages_code('extension --ai-help --output json')}
|
|
5894
|
-
|
|
5895
|
-
Report issues
|
|
5896
|
-
- ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
|
|
5599
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5600
|
+
F7: ()=>resolveSafariBuildConfig,
|
|
5601
|
+
Gi: ()=>xcodeProjectPath,
|
|
5602
|
+
IA: ()=>alignBundleIdentifiers,
|
|
5603
|
+
OA: ()=>isValidBundleId,
|
|
5604
|
+
_D: ()=>backupAndRestoreXcodeSettings,
|
|
5605
|
+
aD: ()=>macOsSchemeName,
|
|
5606
|
+
fd: ()=>builtAppPath,
|
|
5607
|
+
vh: ()=>pbxprojPath,
|
|
5608
|
+
vk: ()=>isProjectStale,
|
|
5609
|
+
vx: ()=>composeXcodebuildArgs,
|
|
5610
|
+
w7: ()=>composeConverterArgs,
|
|
5611
|
+
x7: ()=>saveManifestFingerprint
|
|
5612
|
+
}, {
|
|
5613
|
+
X9: PRESERVED_SETTINGS
|
|
5614
|
+
});
|
|
5615
|
+
},
|
|
5616
|
+
"./browsers/run-safari/safari-packager.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5617
|
+
var _safari_launch__rspack_import_0 = __webpack_require__("./browsers/run-safari/safari-launch/index.ts");
|
|
5618
|
+
function withoutUndefined(input) {
|
|
5619
|
+
if (!input) return {};
|
|
5620
|
+
return Object.fromEntries(Object.entries(input).filter(([, value])=>void 0 !== value));
|
|
5621
|
+
}
|
|
5622
|
+
function createSafariPackager(options = {}) {
|
|
5623
|
+
const { browser = 'safari', noOpen = true, dryRun = false, logger, ...identity } = options;
|
|
5624
|
+
return async (distPath, mode = 'full', overrides)=>await (0, _safari_launch__rspack_import_0.Ah)({
|
|
5625
|
+
extension: [
|
|
5626
|
+
distPath
|
|
5627
|
+
],
|
|
5628
|
+
browser,
|
|
5629
|
+
noOpen,
|
|
5630
|
+
dryRun,
|
|
5631
|
+
...withoutUndefined(identity),
|
|
5632
|
+
...withoutUndefined(overrides)
|
|
5633
|
+
}, distPath, logger, mode);
|
|
5897
5634
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
5635
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5636
|
+
P: ()=>createSafariPackager
|
|
5637
|
+
});
|
|
5638
|
+
},
|
|
5639
|
+
"./helpers/messaging.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
5640
|
+
var pintor__rspack_import_0 = __webpack_require__("pintor");
|
|
5641
|
+
var pintor__rspack_import_0_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_0);
|
|
5642
|
+
const GLYPH = '⏵⏵⏵';
|
|
5643
|
+
const DEBUG_GLYPH = '···';
|
|
5644
|
+
const DEBUG_VALUES = new Set([
|
|
5645
|
+
'1',
|
|
5646
|
+
'true',
|
|
5647
|
+
'yes',
|
|
5648
|
+
'on',
|
|
5649
|
+
'debug',
|
|
5650
|
+
'dev',
|
|
5651
|
+
'development'
|
|
5652
|
+
]);
|
|
5653
|
+
function isDebug() {
|
|
5654
|
+
const raw = process.env.EXTENSION_DEBUG ?? process.env.EXTENSION_AUTHOR_MODE;
|
|
5655
|
+
return DEBUG_VALUES.has(String(raw ?? '').trim().toLowerCase());
|
|
5900
5656
|
}
|
|
5901
|
-
function
|
|
5902
|
-
|
|
5657
|
+
function prefix(type) {
|
|
5658
|
+
if ('error' === type) return pintor__rspack_import_0_default().red(GLYPH);
|
|
5659
|
+
if ('warn' === type) return pintor__rspack_import_0_default().brightYellow(GLYPH);
|
|
5660
|
+
if ('success' === type) return pintor__rspack_import_0_default().green(GLYPH);
|
|
5661
|
+
if ('debug' === type) return pintor__rspack_import_0_default().dim(pintor__rspack_import_0_default().gray(DEBUG_GLYPH));
|
|
5662
|
+
return pintor__rspack_import_0_default().gray(GLYPH);
|
|
5903
5663
|
}
|
|
5904
|
-
|
|
5905
|
-
|
|
5664
|
+
const fmt = {
|
|
5665
|
+
heading: (title)=>pintor__rspack_import_0_default().underline(pintor__rspack_import_0_default().blue(title)),
|
|
5666
|
+
label: (key)=>pintor__rspack_import_0_default().gray(key.toUpperCase()),
|
|
5667
|
+
val: (value)=>pintor__rspack_import_0_default().underline(value),
|
|
5668
|
+
code: (value)=>pintor__rspack_import_0_default().blue(value),
|
|
5669
|
+
bullet: (value)=>`- ${value}`,
|
|
5670
|
+
block (title, rows) {
|
|
5671
|
+
const head = fmt.heading(title);
|
|
5672
|
+
const body = rows.map(([key, value])=>`${fmt.label(key)} ${value}`).join('\n');
|
|
5673
|
+
return `${head}\n${body}`;
|
|
5674
|
+
},
|
|
5675
|
+
truncate (input, max = 800) {
|
|
5676
|
+
const s = (()=>{
|
|
5677
|
+
try {
|
|
5678
|
+
return 'string' == typeof input ? input : JSON.stringify(input);
|
|
5679
|
+
} catch {
|
|
5680
|
+
return String(input);
|
|
5681
|
+
}
|
|
5682
|
+
})();
|
|
5683
|
+
return s.length > max ? `${s.slice(0, max)}…` : s;
|
|
5684
|
+
}
|
|
5685
|
+
};
|
|
5686
|
+
const CARD_LABEL_WIDTH = 15;
|
|
5687
|
+
function card(input = {}) {
|
|
5688
|
+
const version = String(input.version || '').trim();
|
|
5689
|
+
const suffix = String(input.suffix || '').trim();
|
|
5690
|
+
const head = ` 🧩 ${pintor__rspack_import_0_default().brightBlue('Extension.js')}` + (version ? ` ${pintor__rspack_import_0_default().gray(version)}` : '') + (suffix ? ` ${suffix}` : '');
|
|
5691
|
+
const body = (input.rows || []).filter((row)=>String(row.value || '').trim().length > 0).map((row)=>{
|
|
5692
|
+
const label = row.label.padEnd(CARD_LABEL_WIDTH);
|
|
5693
|
+
return ` ${label}${pintor__rspack_import_0_default().gray(String(row.value).trim())}`;
|
|
5694
|
+
});
|
|
5695
|
+
return [
|
|
5696
|
+
head,
|
|
5697
|
+
...body
|
|
5698
|
+
].join('\n');
|
|
5906
5699
|
}
|
|
5907
|
-
|
|
5908
|
-
|
|
5700
|
+
const CARD_KEYS_ENV = 'EXTENSION_CLI_CARD_KEYS';
|
|
5701
|
+
const CARD_KEYS_SEPARATOR = '\u001f';
|
|
5702
|
+
function isCardKeyClaimed(key) {
|
|
5703
|
+
const claimed = String(process.env[CARD_KEYS_ENV] || '');
|
|
5704
|
+
if (!claimed) return false;
|
|
5705
|
+
return claimed.split(CARD_KEYS_SEPARATOR).includes(key);
|
|
5909
5706
|
}
|
|
5910
|
-
function
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
5707
|
+
function claimCardKey(key) {
|
|
5708
|
+
if (isCardKeyClaimed(key)) return false;
|
|
5709
|
+
const claimed = String(process.env[CARD_KEYS_ENV] || '');
|
|
5710
|
+
process.env[CARD_KEYS_ENV] = claimed ? `${claimed}${CARD_KEYS_SEPARATOR}${key}` : key;
|
|
5711
|
+
return true;
|
|
5712
|
+
}
|
|
5713
|
+
const GECKO_BROWSERS = new Set([
|
|
5714
|
+
'firefox',
|
|
5715
|
+
'firefox-based',
|
|
5716
|
+
'gecko-based',
|
|
5717
|
+
'librewolf',
|
|
5718
|
+
'waterfox'
|
|
5719
|
+
]);
|
|
5720
|
+
function artifactNoun(browser) {
|
|
5721
|
+
const name = String(browser || '').trim().toLowerCase();
|
|
5722
|
+
if (GECKO_BROWSERS.has(name)) return 'Add-on';
|
|
5723
|
+
if (name.includes('gecko') || name.includes('firefox')) return 'Add-on';
|
|
5724
|
+
return 'Extension';
|
|
5725
|
+
}
|
|
5726
|
+
const ENVELOPE_SCHEMA = 1;
|
|
5727
|
+
const CODES = {
|
|
5728
|
+
E_ARGS: 'E_ARGS',
|
|
5729
|
+
E_PROJECT_NOT_FOUND: 'E_PROJECT_NOT_FOUND',
|
|
5730
|
+
E_MANIFEST_NOT_FOUND: 'E_MANIFEST_NOT_FOUND',
|
|
5731
|
+
E_MANIFEST_INVALID: 'E_MANIFEST_INVALID',
|
|
5732
|
+
E_FIRST_COMPILE: 'E_FIRST_COMPILE',
|
|
5733
|
+
E_COMPILE: 'E_COMPILE',
|
|
5734
|
+
E_BROWSER_NOT_FOUND: 'E_BROWSER_NOT_FOUND',
|
|
5735
|
+
E_BROWSER_LAUNCH: 'E_BROWSER_LAUNCH',
|
|
5736
|
+
E_PROFILE_LOCKED: 'E_PROFILE_LOCKED',
|
|
5737
|
+
E_READY_TIMEOUT: 'E_READY_TIMEOUT',
|
|
5738
|
+
E_SESSION_EXISTS: 'E_SESSION_EXISTS',
|
|
5739
|
+
E_CONTROL_DENIED: 'E_CONTROL_DENIED',
|
|
5740
|
+
E_CONTROL_UNAVAILABLE: 'E_CONTROL_UNAVAILABLE',
|
|
5741
|
+
E_TOKEN_MISSING: 'E_TOKEN_MISSING',
|
|
5742
|
+
E_NETWORK: 'E_NETWORK',
|
|
5743
|
+
E_INTERRUPTED: 'E_INTERRUPTED',
|
|
5744
|
+
E_NOT_IMPLEMENTED: 'E_NOT_IMPLEMENTED',
|
|
5745
|
+
E_INTERNAL: 'E_INTERNAL',
|
|
5746
|
+
E_UNSUPPORTED_BROWSER: 'E_UNSUPPORTED_BROWSER',
|
|
5747
|
+
E_INVALID_OPTION: 'E_INVALID_OPTION',
|
|
5748
|
+
E_PORT_UNAVAILABLE: 'E_PORT_UNAVAILABLE',
|
|
5749
|
+
E_DEPENDENCY_INSTALL: 'E_DEPENDENCY_INSTALL',
|
|
5750
|
+
E_TEMPLATE_NOT_FOUND: 'E_TEMPLATE_NOT_FOUND',
|
|
5751
|
+
E_DESTINATION_NOT_EMPTY: 'E_DESTINATION_NOT_EMPTY',
|
|
5752
|
+
E_DESTINATION_NOT_WRITABLE: 'E_DESTINATION_NOT_WRITABLE',
|
|
5753
|
+
E_BROWSER_DOWNLOAD: 'E_BROWSER_DOWNLOAD',
|
|
5754
|
+
E_SESSION_NOT_FOUND: 'E_SESSION_NOT_FOUND',
|
|
5755
|
+
E_EVAL_REFUSED: 'E_EVAL_REFUSED',
|
|
5756
|
+
E_TARGET_NOT_FOUND: 'E_TARGET_NOT_FOUND',
|
|
5757
|
+
E_TIMEOUT: 'E_TIMEOUT',
|
|
5758
|
+
E_PUBLISH_REJECTED: 'E_PUBLISH_REJECTED',
|
|
5759
|
+
E_AUTH_REQUIRED: 'E_AUTH_REQUIRED',
|
|
5760
|
+
E_SAFARI_TOOLCHAIN: 'E_SAFARI_TOOLCHAIN',
|
|
5761
|
+
E_EVAL: 'E_EVAL',
|
|
5762
|
+
E_INSPECT: 'E_INSPECT',
|
|
5763
|
+
E_STORAGE: 'E_STORAGE',
|
|
5764
|
+
E_LOGS_NOT_FOUND: 'E_LOGS_NOT_FOUND',
|
|
5765
|
+
E_READY_ERROR_STATUS: 'E_READY_ERROR_STATUS',
|
|
5766
|
+
E_COMMAND_UNSUPPORTED_FOR_TARGET: 'E_COMMAND_UNSUPPORTED_FOR_TARGET',
|
|
5767
|
+
E_FLAG_VALUE_INVALID: 'E_FLAG_VALUE_INVALID',
|
|
5768
|
+
E_FLAG_NOT_SUPPORTED_HERE: 'E_FLAG_NOT_SUPPORTED_HERE',
|
|
5769
|
+
E_DEV_SERVER_START: 'E_DEV_SERVER_START',
|
|
5770
|
+
E_DOCTOR_CHECKS_FAILED: 'E_DOCTOR_CHECKS_FAILED',
|
|
5771
|
+
E_TELEMETRY_WRITE: 'E_TELEMETRY_WRITE',
|
|
5772
|
+
E_PREVIEW_NO_DIST: 'E_PREVIEW_NO_DIST',
|
|
5773
|
+
E_BROWSER_UNINSTALL: 'E_BROWSER_UNINSTALL',
|
|
5774
|
+
E_NODE_VERSION: 'E_NODE_VERSION',
|
|
5775
|
+
E_UNKNOWN_COMMAND: 'E_UNKNOWN_COMMAND',
|
|
5776
|
+
E_REMOVED_FLAG: 'E_REMOVED_FLAG',
|
|
5777
|
+
E_BROWSER_NOT_INSTALLABLE: 'E_BROWSER_NOT_INSTALLABLE',
|
|
5778
|
+
E_PARENT_GONE: 'E_PARENT_GONE',
|
|
5779
|
+
E_REMOTE_URL_UNSUPPORTED: 'E_REMOTE_URL_UNSUPPORTED',
|
|
5780
|
+
E_CONFIG_LOAD: 'E_CONFIG_LOAD',
|
|
5781
|
+
E_MANAGED_DEP_CONFLICT: 'E_MANAGED_DEP_CONFLICT',
|
|
5782
|
+
E_TYPES_EMIT: 'E_TYPES_EMIT',
|
|
5783
|
+
E_TSCONFIG_MISSING: 'E_TSCONFIG_MISSING',
|
|
5784
|
+
E_OPTIONAL_DEP_UNRESOLVED: 'E_OPTIONAL_DEP_UNRESOLVED',
|
|
5785
|
+
E_OPTIONAL_DEP_LOAD: 'E_OPTIONAL_DEP_LOAD',
|
|
5786
|
+
E_OPTIONAL_DEP_UNKNOWN: 'E_OPTIONAL_DEP_UNKNOWN',
|
|
5787
|
+
E_COMPANION_EXTENSION_PATH: 'E_COMPANION_EXTENSION_PATH',
|
|
5788
|
+
E_MANIFEST_IN_PUBLIC: 'E_MANIFEST_IN_PUBLIC',
|
|
5789
|
+
E_RUNTIME_NOT_FOUND: 'E_RUNTIME_NOT_FOUND',
|
|
5790
|
+
E_MANIFEST_SHAPE: 'E_MANIFEST_SHAPE',
|
|
5791
|
+
E_MANIFEST_PAGE_MISSING: 'E_MANIFEST_PAGE_MISSING',
|
|
5792
|
+
E_MANIFEST_VERSION_UNSUPPORTED: 'E_MANIFEST_VERSION_UNSUPPORTED',
|
|
5793
|
+
E_MANIFEST_LOAD_BLOCKERS: 'E_MANIFEST_LOAD_BLOCKERS',
|
|
5794
|
+
E_MANIFEST_PERMISSION_MISSING: 'E_MANIFEST_PERMISSION_MISSING',
|
|
5795
|
+
E_MANIFEST_MSG_KEY_MISSING: 'E_MANIFEST_MSG_KEY_MISSING',
|
|
5796
|
+
E_MANIFEST_EMIT: 'E_MANIFEST_EMIT',
|
|
5797
|
+
E_RESTART_REQUIRED: 'E_RESTART_REQUIRED',
|
|
5798
|
+
E_COMPILE_FATAL: 'E_COMPILE_FATAL',
|
|
5799
|
+
E_MODULE_NOT_FOUND: 'E_MODULE_NOT_FOUND',
|
|
5800
|
+
E_ENTRY_NOT_FOUND: 'E_ENTRY_NOT_FOUND',
|
|
5801
|
+
E_ASSET_MISSING: 'E_ASSET_MISSING',
|
|
5802
|
+
E_SCRIPT_DEP_MISSING: 'E_SCRIPT_DEP_MISSING',
|
|
5803
|
+
E_RESERVED_FOLDER: 'E_RESERVED_FOLDER',
|
|
5804
|
+
E_CSS_PARSE: 'E_CSS_PARSE',
|
|
5805
|
+
E_CSS_PREPROCESSOR_MISSING: 'E_CSS_PREPROCESSOR_MISSING',
|
|
5806
|
+
E_CSS_DEAD_REF: 'E_CSS_DEAD_REF',
|
|
5807
|
+
E_INTEGRATION_INSTALL: 'E_INTEGRATION_INSTALL',
|
|
5808
|
+
E_POLYFILL_NOT_FOUND: 'E_POLYFILL_NOT_FOUND',
|
|
5809
|
+
E_LOCALES_LAYOUT: 'E_LOCALES_LAYOUT',
|
|
5810
|
+
E_WAR_INVALID: 'E_WAR_INVALID',
|
|
5811
|
+
E_MATCH_PATTERN_INVALID: 'E_MATCH_PATTERN_INVALID',
|
|
5812
|
+
E_BACKGROUND_REQUIRED: 'E_BACKGROUND_REQUIRED',
|
|
5813
|
+
E_CONTENT_SCRIPT_SYNTAX: 'E_CONTENT_SCRIPT_SYNTAX',
|
|
5814
|
+
E_NO_ENTRYPOINTS: 'E_NO_ENTRYPOINTS',
|
|
5815
|
+
E_REMOTE_RESOURCE_BLOCKED: 'E_REMOTE_RESOURCE_BLOCKED',
|
|
5816
|
+
E_PERF_BUDGET: 'E_PERF_BUDGET',
|
|
5817
|
+
E_ZIP_SKIPPED: 'E_ZIP_SKIPPED',
|
|
5818
|
+
E_ENV_NO_MATCH: 'E_ENV_NO_MATCH',
|
|
5819
|
+
E_REMOTE_FETCH_TIMEOUT: 'E_REMOTE_FETCH_TIMEOUT',
|
|
5820
|
+
E_REMOTE_DOWNLOAD: 'E_REMOTE_DOWNLOAD',
|
|
5821
|
+
E_REMOTE_ZIP_INVALID: 'E_REMOTE_ZIP_INVALID',
|
|
5822
|
+
E_LOCAL_ZIP_NOT_FOUND: 'E_LOCAL_ZIP_NOT_FOUND',
|
|
5823
|
+
E_PROJECT_DOWNLOAD_EMPTY: 'E_PROJECT_DOWNLOAD_EMPTY',
|
|
5824
|
+
E_BROWSER_BINARY_REQUIRED: 'E_BROWSER_BINARY_REQUIRED',
|
|
5825
|
+
E_BROWSER_BINARY_INVALID: 'E_BROWSER_BINARY_INVALID',
|
|
5826
|
+
E_BROWSER_EXITED: 'E_BROWSER_EXITED',
|
|
5827
|
+
E_BROWSER_START_TIMEOUT: 'E_BROWSER_START_TIMEOUT',
|
|
5828
|
+
E_LAUNCH_SKIPPED_COMPILE_ERRORS: 'E_LAUNCH_SKIPPED_COMPILE_ERRORS',
|
|
5829
|
+
E_INSTANCE_AMBIGUOUS: 'E_INSTANCE_AMBIGUOUS',
|
|
5830
|
+
E_WSL_INTEROP: 'E_WSL_INTEROP',
|
|
5831
|
+
E_EXTENSION_LOAD_REFUSED: 'E_EXTENSION_LOAD_REFUSED',
|
|
5832
|
+
E_ADDON_INSTALL: 'E_ADDON_INSTALL',
|
|
5833
|
+
E_BROWSER_CONNECT: 'E_BROWSER_CONNECT',
|
|
5834
|
+
E_BROWSER_CONNECTION_CLOSED: 'E_BROWSER_CONNECTION_CLOSED',
|
|
5835
|
+
E_CDP_NOT_CONNECTED: 'E_CDP_NOT_CONNECTED',
|
|
5836
|
+
E_CDP_TIMEOUT: 'E_CDP_TIMEOUT',
|
|
5837
|
+
E_CDP_OP_FAILED: 'E_CDP_OP_FAILED',
|
|
5838
|
+
E_EXTENSION_ID_UNKNOWN: 'E_EXTENSION_ID_UNKNOWN',
|
|
5839
|
+
E_RDP_PROTOCOL: 'E_RDP_PROTOCOL',
|
|
5840
|
+
E_DEV_SERVER_TIMEOUT: 'E_DEV_SERVER_TIMEOUT',
|
|
5841
|
+
E_PORT_IN_USE: 'E_PORT_IN_USE',
|
|
5842
|
+
E_SESSION_STOPPED: 'E_SESSION_STOPPED',
|
|
5843
|
+
E_LOGS_STREAM_GAP: 'E_LOGS_STREAM_GAP',
|
|
5844
|
+
E_CREATE_DIR: 'E_CREATE_DIR',
|
|
5845
|
+
E_CREATE_WRITE: 'E_CREATE_WRITE',
|
|
5846
|
+
E_CREATE_TESTS_SETUP: 'E_CREATE_TESTS_SETUP',
|
|
5847
|
+
E_GIT_SKIPPED: 'E_GIT_SKIPPED',
|
|
5848
|
+
E_BROWSER_INSTALL_PRIVILEGE: 'E_BROWSER_INSTALL_PRIVILEGE',
|
|
5849
|
+
E_UNINSTALL_NOOP: 'E_UNINSTALL_NOOP'
|
|
5850
|
+
};
|
|
5851
|
+
function withExtras(base, extras) {
|
|
5852
|
+
return {
|
|
5853
|
+
...base,
|
|
5854
|
+
...extras.hint ? {
|
|
5855
|
+
hint: extras.hint
|
|
5856
|
+
} : {},
|
|
5857
|
+
...extras.truncated ? {
|
|
5858
|
+
truncated: true
|
|
5859
|
+
} : {},
|
|
5860
|
+
warnings: extras.warnings || []
|
|
5861
|
+
};
|
|
5862
|
+
}
|
|
5863
|
+
const ENVELOPE = {
|
|
5864
|
+
schema: ENVELOPE_SCHEMA,
|
|
5865
|
+
ok (command, status, value, extras = {}) {
|
|
5866
|
+
return withExtras({
|
|
5867
|
+
schema: ENVELOPE_SCHEMA,
|
|
5868
|
+
ok: true,
|
|
5869
|
+
command,
|
|
5870
|
+
status,
|
|
5871
|
+
value,
|
|
5872
|
+
error: null,
|
|
5873
|
+
warnings: []
|
|
5874
|
+
}, extras);
|
|
5875
|
+
},
|
|
5876
|
+
fail (command, status, error, extras = {}) {
|
|
5877
|
+
return withExtras({
|
|
5878
|
+
schema: ENVELOPE_SCHEMA,
|
|
5879
|
+
ok: false,
|
|
5880
|
+
command,
|
|
5881
|
+
status,
|
|
5882
|
+
value: extras.value ?? null,
|
|
5883
|
+
error,
|
|
5884
|
+
warnings: []
|
|
5885
|
+
}, extras);
|
|
5886
|
+
}
|
|
5887
|
+
};
|
|
5888
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5889
|
+
Nr: ()=>card,
|
|
5890
|
+
Pl: ()=>prefix,
|
|
5891
|
+
T_: ()=>artifactNoun,
|
|
5892
|
+
VR: ()=>isCardKeyClaimed,
|
|
5893
|
+
_o: ()=>isDebug,
|
|
5894
|
+
od: ()=>claimCardKey
|
|
5895
|
+
}, {
|
|
5896
|
+
Lp: CODES,
|
|
5897
|
+
Pr: ENVELOPE,
|
|
5898
|
+
Sc: fmt
|
|
5899
|
+
});
|
|
5900
|
+
},
|
|
5901
|
+
"./index.ts" (__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
5902
|
+
const MIN_NODE_MAJOR = 22;
|
|
5903
|
+
const MIN_NODE_MINOR = 12;
|
|
5904
|
+
function isSupportedNodeVersion(version) {
|
|
5905
|
+
const [major, minor] = version.split('.').map((part)=>parseInt(part, 10));
|
|
5906
|
+
if (!Number.isFinite(major)) return true;
|
|
5907
|
+
if (major !== MIN_NODE_MAJOR) return major > MIN_NODE_MAJOR;
|
|
5908
|
+
return (Number.isFinite(minor) ? minor : 0) >= MIN_NODE_MINOR;
|
|
5909
|
+
}
|
|
5910
|
+
function unsupportedNodeVersionMessage(version) {
|
|
5911
|
+
return `[Extension.js] Requires Node.js >= ${MIN_NODE_MAJOR}.${MIN_NODE_MINOR} (you are on ${version}). Upgrade Node.js to run the extension CLI.`;
|
|
5912
|
+
}
|
|
5913
|
+
function enforceSupportedNodeVersion(version = process.versions.node) {
|
|
5914
|
+
if (isSupportedNodeVersion(version)) return;
|
|
5915
|
+
console.error(unsupportedNodeVersionMessage(version));
|
|
5916
|
+
process.exit(1);
|
|
5917
|
+
}
|
|
5918
|
+
enforceSupportedNodeVersion();
|
|
5919
|
+
const external_commander_namespaceObject = require("commander");
|
|
5920
|
+
var external_node_fs_ = __webpack_require__("node:fs");
|
|
5921
|
+
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_);
|
|
5922
|
+
var external_node_path_ = __webpack_require__("node:path");
|
|
5923
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_);
|
|
5924
|
+
async function exitAfterDrain(code) {
|
|
5925
|
+
await Promise.all([
|
|
5926
|
+
process.stdout,
|
|
5927
|
+
process.stderr
|
|
5928
|
+
].map((stream)=>new Promise((resolve)=>{
|
|
5929
|
+
if (0 === stream.writableLength) return resolve();
|
|
5930
|
+
stream.write('', ()=>resolve());
|
|
5931
|
+
})));
|
|
5932
|
+
process.exit(code);
|
|
5933
|
+
}
|
|
5934
|
+
var external_node_module_ = __webpack_require__("node:module");
|
|
5935
|
+
const external_node_url_namespaceObject = require("node:url");
|
|
5936
|
+
const extension_develop_runtime_require = (0, external_node_module_.createRequire)(__rslib_import_meta_url__);
|
|
5937
|
+
function parseJsonSafe(filePath) {
|
|
5938
|
+
return JSON.parse(external_node_fs_default().readFileSync(filePath, 'utf8'));
|
|
5939
|
+
}
|
|
5940
|
+
function resolveDevelopRootFromDir(dir) {
|
|
5941
|
+
try {
|
|
5942
|
+
const packageJsonPath = external_node_path_default().join(dir, 'package.json');
|
|
5943
|
+
if (!external_node_fs_default().existsSync(packageJsonPath)) return;
|
|
5944
|
+
const pkg = parseJsonSafe(packageJsonPath);
|
|
5945
|
+
return pkg?.name === 'extension-develop' ? dir : void 0;
|
|
5946
|
+
} catch {
|
|
5947
|
+
return;
|
|
5948
|
+
}
|
|
6047
5949
|
}
|
|
6048
|
-
function
|
|
5950
|
+
function resolveWorkspaceDevelopRoot(startDir) {
|
|
5951
|
+
let currentDir = external_node_path_default().resolve(startDir);
|
|
5952
|
+
if (currentDir.split(external_node_path_default().sep).includes('node_modules')) return;
|
|
5953
|
+
for(let depth = 0; depth < 8; depth += 1){
|
|
5954
|
+
const candidate = external_node_path_default().join(currentDir, 'programs', 'develop');
|
|
5955
|
+
const resolved = resolveDevelopRootFromDir(candidate);
|
|
5956
|
+
if (resolved) return resolved;
|
|
5957
|
+
const parent = external_node_path_default().dirname(currentDir);
|
|
5958
|
+
if (parent === currentDir) break;
|
|
5959
|
+
currentDir = parent;
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
function resolveInstalledDevelopRoot() {
|
|
5963
|
+
try {
|
|
5964
|
+
const packageJsonPath = extension_develop_runtime_require.resolve('extension-develop/package.json');
|
|
5965
|
+
return resolveDevelopRootFromDir(external_node_path_default().dirname(packageJsonPath));
|
|
5966
|
+
} catch {
|
|
5967
|
+
try {
|
|
5968
|
+
const entryPath = extension_develop_runtime_require.resolve('extension-develop');
|
|
5969
|
+
return resolveDevelopRootFromDir(external_node_path_default().dirname(external_node_path_default().dirname(entryPath)));
|
|
5970
|
+
} catch {
|
|
5971
|
+
return;
|
|
5972
|
+
}
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
function resolvePreferredDevelopRoot(startDir) {
|
|
5976
|
+
const workspaceRoot = resolveWorkspaceDevelopRoot(startDir);
|
|
5977
|
+
if (workspaceRoot) return {
|
|
5978
|
+
root: workspaceRoot,
|
|
5979
|
+
source: 'workspace'
|
|
5980
|
+
};
|
|
5981
|
+
const envRoot = process.env.EXTENSION_DEVELOP_ROOT ? resolveDevelopRootFromDir(external_node_path_default().resolve(process.env.EXTENSION_DEVELOP_ROOT)) : void 0;
|
|
5982
|
+
if (envRoot) return {
|
|
5983
|
+
root: envRoot,
|
|
5984
|
+
source: 'env'
|
|
5985
|
+
};
|
|
5986
|
+
const installedRoot = resolveInstalledDevelopRoot();
|
|
5987
|
+
if (installedRoot) return {
|
|
5988
|
+
root: installedRoot,
|
|
5989
|
+
source: 'installed'
|
|
5990
|
+
};
|
|
6049
5991
|
return {
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
5992
|
+
root: void 0,
|
|
5993
|
+
source: 'missing'
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
function resolveDevelopDistEntry(root, name = 'module') {
|
|
5997
|
+
const base = external_node_path_default().join(root, 'dist', name);
|
|
5998
|
+
const candidates = [
|
|
5999
|
+
`${base}.mjs`,
|
|
6000
|
+
`${base}.cjs`,
|
|
6001
|
+
`${base}.js`,
|
|
6002
|
+
base
|
|
6003
|
+
];
|
|
6004
|
+
for (const candidate of candidates)if (external_node_fs_default().existsSync(candidate)) return candidate;
|
|
6005
|
+
}
|
|
6006
|
+
function resolveExtensionDevelopRoot(startDir = __dirname) {
|
|
6007
|
+
const { root, source } = resolvePreferredDevelopRoot(startDir);
|
|
6008
|
+
if (!root) throw new Error('Unable to locate the extension-develop runtime.');
|
|
6009
|
+
process.env.EXTENSION_DEVELOP_ROOT = root;
|
|
6010
|
+
if ('workspace' === source) process.env.EXTENSION_CREATE_DEVELOP_ROOT = root;
|
|
6011
|
+
return root;
|
|
6012
|
+
}
|
|
6013
|
+
function resolveExtensionDevelopVersion(startDir = __dirname, fallbackVersion) {
|
|
6014
|
+
try {
|
|
6015
|
+
const root = resolveExtensionDevelopRoot(startDir);
|
|
6016
|
+
const packageJsonPath = external_node_path_default().join(root, 'package.json');
|
|
6017
|
+
const pkg = parseJsonSafe(packageJsonPath);
|
|
6018
|
+
return pkg?.version || fallbackVersion || '0.0.0';
|
|
6019
|
+
} catch {
|
|
6020
|
+
return fallbackVersion || '0.0.0';
|
|
6021
|
+
}
|
|
6022
|
+
}
|
|
6023
|
+
async function importModule(filePath) {
|
|
6024
|
+
const mod = await import((0, external_node_url_namespaceObject.pathToFileURL)(filePath).href);
|
|
6025
|
+
return mod?.default && 'object' == typeof mod.default ? {
|
|
6026
|
+
...mod.default,
|
|
6027
|
+
...mod
|
|
6028
|
+
} : mod;
|
|
6029
|
+
}
|
|
6030
|
+
async function loadExtensionDevelopModule(startDir = __dirname) {
|
|
6031
|
+
const root = resolveExtensionDevelopRoot(startDir);
|
|
6032
|
+
const { source } = resolvePreferredDevelopRoot(startDir);
|
|
6033
|
+
const distEntry = resolveDevelopDistEntry(root);
|
|
6034
|
+
if (distEntry) return importModule(distEntry);
|
|
6035
|
+
if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_node_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
|
|
6036
|
+
return await import("extension-develop");
|
|
6037
|
+
}
|
|
6038
|
+
async function loadExtensionDevelopPreviewModule(startDir = __dirname) {
|
|
6039
|
+
const root = resolveExtensionDevelopRoot(startDir);
|
|
6040
|
+
const { source } = resolvePreferredDevelopRoot(startDir);
|
|
6041
|
+
const previewEntry = resolveDevelopDistEntry(root, 'preview');
|
|
6042
|
+
if (previewEntry) return importModule(previewEntry);
|
|
6043
|
+
const fullEntry = resolveDevelopDistEntry(root);
|
|
6044
|
+
if (fullEntry) return importModule(fullEntry);
|
|
6045
|
+
if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_node_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
|
|
6046
|
+
return await import("extension-develop/preview");
|
|
6047
|
+
}
|
|
6048
|
+
async function loadExtensionDevelopBridgeModule(startDir = __dirname) {
|
|
6049
|
+
const root = resolveExtensionDevelopRoot(startDir);
|
|
6050
|
+
const { source } = resolvePreferredDevelopRoot(startDir);
|
|
6051
|
+
const bridgeEntry = resolveDevelopDistEntry(root, 'bridge');
|
|
6052
|
+
if (bridgeEntry) return importModule(bridgeEntry);
|
|
6053
|
+
if ('workspace' === source) throw new Error(`Local extension-develop runtime is not built at ${external_node_path_default().join(root, 'dist')}. Run \`pnpm --filter extension-develop compile\` before invoking the local CLI.`);
|
|
6054
|
+
const bridgeSpecifier = 'extension-develop/bridge';
|
|
6055
|
+
return await import(bridgeSpecifier);
|
|
6056
|
+
}
|
|
6057
|
+
var external_pintor_ = __webpack_require__("pintor");
|
|
6058
|
+
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
|
|
6059
|
+
var messaging = __webpack_require__("./helpers/messaging.ts");
|
|
6060
|
+
function getLoggingPrefix(type) {
|
|
6061
|
+
return (0, messaging.Pl)(type);
|
|
6062
|
+
}
|
|
6063
|
+
const messages_code = (text)=>external_pintor_default().blue(text);
|
|
6064
|
+
const messages_arg = (text)=>external_pintor_default().gray(text);
|
|
6065
|
+
function renderArgToken(spec) {
|
|
6066
|
+
const token = spec.values ? spec.values.join('|') : spec.label ?? spec.name;
|
|
6067
|
+
return spec.required ? `<${token}>` : `[${token}]`;
|
|
6068
|
+
}
|
|
6069
|
+
function commandArgSignature(positionals) {
|
|
6070
|
+
return positionals.map(renderArgToken).join(' ');
|
|
6071
|
+
}
|
|
6072
|
+
const COMMAND_TABLE = [
|
|
6073
|
+
{
|
|
6074
|
+
name: 'create',
|
|
6075
|
+
positionals: [
|
|
6057
6076
|
{
|
|
6058
|
-
name: '
|
|
6059
|
-
|
|
6077
|
+
name: 'project-name|project-path',
|
|
6078
|
+
required: true
|
|
6079
|
+
}
|
|
6080
|
+
],
|
|
6081
|
+
description: 'Create a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
|
|
6082
|
+
supportsSourceInspection: false
|
|
6083
|
+
},
|
|
6084
|
+
{
|
|
6085
|
+
name: 'dev',
|
|
6086
|
+
positionals: [
|
|
6087
|
+
{
|
|
6088
|
+
name: 'project-path|remote-url',
|
|
6089
|
+
required: false
|
|
6090
|
+
}
|
|
6091
|
+
],
|
|
6092
|
+
description: 'Start the development server with hot reloading',
|
|
6093
|
+
supportsSourceInspection: true
|
|
6094
|
+
},
|
|
6095
|
+
{
|
|
6096
|
+
name: 'start',
|
|
6097
|
+
positionals: [
|
|
6098
|
+
{
|
|
6099
|
+
name: 'project-path|remote-url',
|
|
6100
|
+
required: false
|
|
6101
|
+
}
|
|
6102
|
+
],
|
|
6103
|
+
description: 'Build and start the extension in production mode',
|
|
6104
|
+
supportsSourceInspection: false
|
|
6105
|
+
},
|
|
6106
|
+
{
|
|
6107
|
+
name: 'preview',
|
|
6108
|
+
positionals: [
|
|
6109
|
+
{
|
|
6110
|
+
name: 'project-name',
|
|
6111
|
+
required: false,
|
|
6112
|
+
label: 'project-path|remote-url'
|
|
6113
|
+
}
|
|
6114
|
+
],
|
|
6115
|
+
description: 'Preview the extension in production mode without building',
|
|
6116
|
+
supportsSourceInspection: false
|
|
6117
|
+
},
|
|
6118
|
+
{
|
|
6119
|
+
name: 'build',
|
|
6120
|
+
positionals: [
|
|
6121
|
+
{
|
|
6122
|
+
name: 'project-name',
|
|
6123
|
+
required: false,
|
|
6124
|
+
label: 'project-path|remote-url'
|
|
6125
|
+
}
|
|
6126
|
+
],
|
|
6127
|
+
description: 'Build the extension for packaging and distribution',
|
|
6128
|
+
supportsSourceInspection: false
|
|
6129
|
+
},
|
|
6130
|
+
{
|
|
6131
|
+
name: 'logs',
|
|
6132
|
+
positionals: [
|
|
6133
|
+
{
|
|
6134
|
+
name: 'project-path',
|
|
6135
|
+
required: false
|
|
6136
|
+
}
|
|
6137
|
+
],
|
|
6138
|
+
description: 'Print or stream logs from every context of a running dev session',
|
|
6139
|
+
supportsSourceInspection: false
|
|
6140
|
+
},
|
|
6141
|
+
{
|
|
6142
|
+
name: 'eval',
|
|
6143
|
+
positionals: [
|
|
6144
|
+
{
|
|
6145
|
+
name: 'expression',
|
|
6146
|
+
required: true
|
|
6147
|
+
},
|
|
6148
|
+
{
|
|
6149
|
+
name: 'project-path',
|
|
6150
|
+
required: false
|
|
6151
|
+
}
|
|
6152
|
+
],
|
|
6153
|
+
description: 'Evaluate an expression in a running extension context (requires --allow-eval)',
|
|
6154
|
+
supportsSourceInspection: false
|
|
6155
|
+
},
|
|
6156
|
+
{
|
|
6157
|
+
name: 'storage',
|
|
6158
|
+
positionals: [
|
|
6159
|
+
{
|
|
6160
|
+
name: 'action',
|
|
6161
|
+
required: true,
|
|
6162
|
+
values: [
|
|
6163
|
+
'get',
|
|
6164
|
+
'set'
|
|
6165
|
+
]
|
|
6166
|
+
},
|
|
6167
|
+
{
|
|
6168
|
+
name: 'project-path',
|
|
6169
|
+
required: false
|
|
6170
|
+
}
|
|
6171
|
+
],
|
|
6172
|
+
description: 'Read or write chrome.storage in a running extension (requires --allow-control)',
|
|
6173
|
+
supportsSourceInspection: false
|
|
6174
|
+
},
|
|
6175
|
+
{
|
|
6176
|
+
name: 'reload',
|
|
6177
|
+
positionals: [
|
|
6178
|
+
{
|
|
6179
|
+
name: 'project-path',
|
|
6180
|
+
required: false
|
|
6181
|
+
}
|
|
6182
|
+
],
|
|
6183
|
+
description: 'Reload a running extension or tab (requires --allow-control)',
|
|
6184
|
+
supportsSourceInspection: false
|
|
6185
|
+
},
|
|
6186
|
+
{
|
|
6187
|
+
name: 'open',
|
|
6188
|
+
positionals: [
|
|
6189
|
+
{
|
|
6190
|
+
name: 'surface',
|
|
6191
|
+
required: true,
|
|
6192
|
+
values: [
|
|
6193
|
+
'popup',
|
|
6194
|
+
'options',
|
|
6195
|
+
'sidebar',
|
|
6196
|
+
'action',
|
|
6197
|
+
'command'
|
|
6198
|
+
]
|
|
6060
6199
|
},
|
|
6061
6200
|
{
|
|
6062
|
-
name: '
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6201
|
+
name: 'project-path',
|
|
6202
|
+
required: false
|
|
6203
|
+
}
|
|
6204
|
+
],
|
|
6205
|
+
description: 'Open an extension surface: popup, options, sidebar, action, or command (requires --allow-control)',
|
|
6206
|
+
supportsSourceInspection: false
|
|
6207
|
+
},
|
|
6208
|
+
{
|
|
6209
|
+
name: 'inspect',
|
|
6210
|
+
positionals: [
|
|
6070
6211
|
{
|
|
6071
|
-
name: '
|
|
6072
|
-
|
|
6073
|
-
}
|
|
6212
|
+
name: 'project-path',
|
|
6213
|
+
required: false
|
|
6214
|
+
}
|
|
6215
|
+
],
|
|
6216
|
+
description: 'Inspect a page or content DOM through the agent bridge (CDP-free; requires --allow-control)',
|
|
6217
|
+
supportsSourceInspection: true
|
|
6218
|
+
},
|
|
6219
|
+
{
|
|
6220
|
+
name: 'publish',
|
|
6221
|
+
positionals: [
|
|
6074
6222
|
{
|
|
6075
|
-
name: '
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
default: 'chromium',
|
|
6086
|
-
description: 'Target browser/engine'
|
|
6087
|
-
},
|
|
6223
|
+
name: 'project-path',
|
|
6224
|
+
required: false
|
|
6225
|
+
}
|
|
6226
|
+
],
|
|
6227
|
+
description: 'Publish to extension.dev and print a shareable URL (requires EXTENSION_DEV_TOKEN)',
|
|
6228
|
+
supportsSourceInspection: false
|
|
6229
|
+
},
|
|
6230
|
+
{
|
|
6231
|
+
name: 'install',
|
|
6232
|
+
positionals: [
|
|
6088
6233
|
{
|
|
6089
|
-
name: '
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6234
|
+
name: 'browser-name',
|
|
6235
|
+
required: false
|
|
6236
|
+
}
|
|
6237
|
+
],
|
|
6238
|
+
description: 'Install a managed browser binary into the Extension.js cache',
|
|
6239
|
+
detail: 'Defaults to chromium when no browser is named.',
|
|
6240
|
+
supportsSourceInspection: false,
|
|
6241
|
+
notes: [
|
|
6093
6242
|
{
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
description: 'Dev server host address (use 0.0.0.0 for Docker/devcontainers)'
|
|
6243
|
+
usage: '--browser <chrome|chromium|edge|firefox|chromium-based|gecko-based|firefox-based|all>',
|
|
6244
|
+
description: 'Install multiple browsers, browser families, or all'
|
|
6097
6245
|
},
|
|
6098
6246
|
{
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6247
|
+
usage: '--where',
|
|
6248
|
+
description: 'Print the managed browser cache root (or browser install path(s) when a browser name or --browser is provided)'
|
|
6249
|
+
}
|
|
6250
|
+
]
|
|
6251
|
+
},
|
|
6252
|
+
{
|
|
6253
|
+
name: 'uninstall',
|
|
6254
|
+
positionals: [
|
|
6255
|
+
{
|
|
6256
|
+
name: 'browser-name',
|
|
6257
|
+
required: false
|
|
6102
6258
|
}
|
|
6103
6259
|
],
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
'info',
|
|
6111
|
-
'debug',
|
|
6112
|
-
'trace',
|
|
6113
|
-
'all'
|
|
6114
|
-
],
|
|
6115
|
-
formats: [
|
|
6116
|
-
'pretty',
|
|
6117
|
-
'json',
|
|
6118
|
-
'ndjson'
|
|
6119
|
-
],
|
|
6120
|
-
notes: [
|
|
6121
|
-
'centralized logger streams logs from multiple extension contexts',
|
|
6122
|
-
'--logs defaults to off unless explicitly enabled'
|
|
6123
|
-
]
|
|
6124
|
-
},
|
|
6125
|
-
managedDependencies: {
|
|
6126
|
-
enforcement: 'guarded',
|
|
6127
|
-
trigger: 'when managed packages are declared in package.json and imported as a module specifier in extension.config',
|
|
6128
|
-
action: 'print an error and abort'
|
|
6129
|
-
},
|
|
6130
|
-
readyContract: {
|
|
6131
|
-
readyPath: 'dist/extension-js/<browser>/ready.json',
|
|
6132
|
-
eventsPath: 'dist/extension-js/<browser>/events.ndjson',
|
|
6133
|
-
waitFlag: '--wait blocks until ready.json reports ready (or error) then exits; pair with --output json for machine output (--wait-format is a deprecated alias)',
|
|
6134
|
-
statuses: [
|
|
6135
|
-
'starting',
|
|
6136
|
-
'ready',
|
|
6137
|
-
'error'
|
|
6138
|
-
],
|
|
6139
|
-
readyFields: [
|
|
6140
|
-
'status',
|
|
6141
|
-
'command',
|
|
6142
|
-
'browser',
|
|
6143
|
-
'runId',
|
|
6144
|
-
'startedAt',
|
|
6145
|
-
'distPath',
|
|
6146
|
-
'manifestPath',
|
|
6147
|
-
'port',
|
|
6148
|
-
'pid',
|
|
6149
|
-
'ts',
|
|
6150
|
-
'compiledAt',
|
|
6151
|
-
'errors'
|
|
6152
|
-
],
|
|
6153
|
-
eventTypes: [
|
|
6154
|
-
'compile_start',
|
|
6155
|
-
'compile_success',
|
|
6156
|
-
'compile_error',
|
|
6157
|
-
'shutdown'
|
|
6158
|
-
],
|
|
6159
|
-
notes: [
|
|
6160
|
-
'ready.json is written atomically by the build (dev/start) on each compile',
|
|
6161
|
-
'events.ndjson is an append-only build timeline with durationMs and errorCount per entry',
|
|
6162
|
-
'--wait requires a local project path (remote URLs are not supported)',
|
|
6163
|
-
'consumers should verify pid liveness and recency before trusting a contract'
|
|
6164
|
-
]
|
|
6260
|
+
description: 'Remove managed browser binaries from the Extension.js cache',
|
|
6261
|
+
supportsSourceInspection: false,
|
|
6262
|
+
notes: [
|
|
6263
|
+
{
|
|
6264
|
+
usage: '--all',
|
|
6265
|
+
description: 'Remove every managed browser binary'
|
|
6165
6266
|
},
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
'/.dockerenv',
|
|
6170
|
-
'/run/.containerenv',
|
|
6171
|
-
'REMOTE_CONTAINERS=true',
|
|
6172
|
-
'CODESPACES=true',
|
|
6173
|
-
'container env var'
|
|
6174
|
-
],
|
|
6175
|
-
notes: [
|
|
6176
|
-
'Use --no-browser inside the container and load dist/<browser>/ in the host browser',
|
|
6177
|
-
'File watching uses polling (1s interval) for bind-mount compatibility',
|
|
6178
|
-
'--no-sandbox is added automatically when a container environment is detected'
|
|
6179
|
-
]
|
|
6267
|
+
{
|
|
6268
|
+
usage: '--where',
|
|
6269
|
+
description: 'Print the managed browser cache root (or browser install path(s) when --browser/--all is provided)'
|
|
6180
6270
|
}
|
|
6181
|
-
},
|
|
6182
|
-
examples: [
|
|
6183
|
-
'extension --ai-help',
|
|
6184
|
-
'extension --ai-help --output json',
|
|
6185
|
-
'extension dev ./my-ext --logs=info --log-format=json',
|
|
6186
|
-
'extension dev ./my-ext --host 0.0.0.0 --no-browser',
|
|
6187
|
-
'extension dev ./my-ext --wait --browser=chromium --output json',
|
|
6188
|
-
'extension start ./my-ext --wait --browser=chromium --output json',
|
|
6189
|
-
'extension dev ./my-ext --gecko-binary flatpak:org.mozilla.firefox',
|
|
6190
|
-
'extension install chromium',
|
|
6191
|
-
'extension install --where',
|
|
6192
|
-
'extension uninstall --where',
|
|
6193
|
-
'extension uninstall --all'
|
|
6194
6271
|
]
|
|
6195
|
-
}
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
return `${getLoggingPrefix('error')} ${messages_code('--no-browser')} is only supported for ${messages_code('dev')}, ${messages_code('start')}, and ${messages_code('preview')}.\nReceived command: ${messages_code(command || '(none)')}`;
|
|
6208
|
-
}
|
|
6209
|
-
function readRecentConsole(projectPath, browser, target, limit) {
|
|
6210
|
-
const file = external_node_path_default().resolve(projectPath, 'dist', 'extension-js', browser, 'logs.ndjson');
|
|
6211
|
-
let lines;
|
|
6212
|
-
try {
|
|
6213
|
-
lines = external_node_fs_default().readFileSync(file, 'utf-8').split('\n').filter(Boolean);
|
|
6214
|
-
} catch {
|
|
6215
|
-
return [];
|
|
6216
|
-
}
|
|
6217
|
-
const out = [];
|
|
6218
|
-
for (const line of lines){
|
|
6219
|
-
let e;
|
|
6220
|
-
try {
|
|
6221
|
-
e = JSON.parse(line);
|
|
6222
|
-
} catch {
|
|
6223
|
-
continue;
|
|
6224
|
-
}
|
|
6225
|
-
if (e && 'header' !== e.type) {
|
|
6226
|
-
if (!target.context || e.context === target.context) {
|
|
6227
|
-
if (null == target.tabId || e.tabId === target.tabId) out.push({
|
|
6228
|
-
seq: e.seq,
|
|
6229
|
-
level: e.level,
|
|
6230
|
-
context: e.context,
|
|
6231
|
-
messageParts: e.messageParts,
|
|
6232
|
-
eventType: e.eventType,
|
|
6233
|
-
code: e.code,
|
|
6234
|
-
tabId: e.tabId
|
|
6235
|
-
});
|
|
6272
|
+
},
|
|
6273
|
+
{
|
|
6274
|
+
name: 'telemetry',
|
|
6275
|
+
positionals: [
|
|
6276
|
+
{
|
|
6277
|
+
name: 'action',
|
|
6278
|
+
required: false,
|
|
6279
|
+
values: [
|
|
6280
|
+
'enable',
|
|
6281
|
+
'disable',
|
|
6282
|
+
'status'
|
|
6283
|
+
]
|
|
6236
6284
|
}
|
|
6237
|
-
|
|
6285
|
+
],
|
|
6286
|
+
description: 'Manage anonymous telemetry consent (enable, disable, or show status)',
|
|
6287
|
+
supportsSourceInspection: false
|
|
6288
|
+
},
|
|
6289
|
+
{
|
|
6290
|
+
name: 'doctor',
|
|
6291
|
+
positionals: [
|
|
6292
|
+
{
|
|
6293
|
+
name: 'project-path',
|
|
6294
|
+
required: false
|
|
6295
|
+
}
|
|
6296
|
+
],
|
|
6297
|
+
description: 'Diagnose a dev session: ready contract, control channel, token, executor, browser',
|
|
6298
|
+
supportsSourceInspection: false
|
|
6238
6299
|
}
|
|
6239
|
-
|
|
6300
|
+
];
|
|
6301
|
+
const COMMANDS = COMMAND_TABLE.map((entry)=>({
|
|
6302
|
+
...entry,
|
|
6303
|
+
args: commandArgSignature(entry.positionals)
|
|
6304
|
+
}));
|
|
6305
|
+
const commandDescriptions = Object.fromEntries(COMMANDS.map((spec)=>[
|
|
6306
|
+
spec.name,
|
|
6307
|
+
spec.description
|
|
6308
|
+
]));
|
|
6309
|
+
function commandHelpEntry(spec) {
|
|
6310
|
+
const signature = spec.args ? ` ${messages_arg(spec.args)}` : '';
|
|
6311
|
+
const lines = [
|
|
6312
|
+
`- ${messages_code(`extension ${spec.name}`)}${signature}`,
|
|
6313
|
+
` ${spec.description}`
|
|
6314
|
+
];
|
|
6315
|
+
if (spec.detail) lines.push(` ${spec.detail}`);
|
|
6316
|
+
for (const note of spec.notes ?? [])lines.push('', `- ${messages_code(`extension ${spec.name}`)} ${messages_arg(note.usage)}`, ` ${note.description}`);
|
|
6317
|
+
return lines.join('\n');
|
|
6240
6318
|
}
|
|
6241
|
-
function
|
|
6242
|
-
|
|
6243
|
-
if ('Unavailable' === name) return messaging.Lp.E_CONTROL_UNAVAILABLE;
|
|
6244
|
-
if ('Forbidden' === name) return /token missing/i.test(message) ? messaging.Lp.E_TOKEN_MISSING : messaging.Lp.E_EVAL_REFUSED;
|
|
6245
|
-
if ('BadRequest' === name) return messaging.Lp.E_ARGS;
|
|
6246
|
-
if ('Unsupported' === name) return /needs a --tab id|no injectable frame|is not open/i.test(message) ? messaging.Lp.E_TARGET_NOT_FOUND : messaging.Lp.E_NOT_IMPLEMENTED;
|
|
6247
|
-
if ('EvalError' === name) return messaging.Lp.E_EVAL;
|
|
6248
|
-
if ('InspectError' === name) return messaging.Lp.E_INSPECT;
|
|
6249
|
-
if ('StorageError' === name) return messaging.Lp.E_STORAGE;
|
|
6250
|
-
return messaging.Lp.E_INTERNAL;
|
|
6319
|
+
function availableCommandsBlock() {
|
|
6320
|
+
return COMMANDS.map(commandHelpEntry).join('\n\n');
|
|
6251
6321
|
}
|
|
6252
|
-
function
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
if (code === messaging.Lp.E_CONTROL_DENIED || code === messaging.Lp.E_EVAL_REFUSED || code === messaging.Lp.E_TOKEN_MISSING) return 'denied';
|
|
6256
|
-
if (code === messaging.Lp.E_ARGS) return 'usage';
|
|
6257
|
-
return 'failed';
|
|
6322
|
+
function unhandledError(err) {
|
|
6323
|
+
const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : messaging.Sc.truncate(err);
|
|
6324
|
+
return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
|
|
6258
6325
|
}
|
|
6259
|
-
function
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
};
|
|
6268
|
-
const raw = error || {};
|
|
6269
|
-
const name = 'string' == typeof raw.name ? raw.name : 'Error';
|
|
6270
|
-
const message = 'string' == typeof raw.message ? raw.message : 'command failed';
|
|
6271
|
-
const code = codeForBridgeError(name, message);
|
|
6326
|
+
function updateFailed(err) {
|
|
6327
|
+
return `${getLoggingPrefix('warn')} Couldn't check for updates.\n${external_pintor_default().yellow('The command continues without the update check.')}\n${external_pintor_default().yellow(String(err?.message || err))}`;
|
|
6328
|
+
}
|
|
6329
|
+
function checkUpdates(packageJson, update) {
|
|
6330
|
+
const latest = String(update.latest);
|
|
6331
|
+
const releaseNotesUrl = `https://github.com/extension-js/extension.js/releases/tag/v${latest}`;
|
|
6332
|
+
const suffix = external_pintor_default().gray(`(version ${latest} is available!)`);
|
|
6333
|
+
const message = `${getLoggingPrefix('info')} 🧩 An ${external_pintor_default().blue('Extension.js')} update is available.\n\nYou are on version ${external_pintor_default().red(String(packageJson.version))}.\nThe latest stable is ${external_pintor_default().green(latest)}.\nSee what's new: ${external_pintor_default().underline(releaseNotesUrl)}\nUpdate to the latest stable to get fixes and new features.`;
|
|
6272
6334
|
return {
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
...raw,
|
|
6276
|
-
code,
|
|
6277
|
-
message,
|
|
6278
|
-
name
|
|
6279
|
-
}, {
|
|
6280
|
-
truncated: wasTruncated
|
|
6281
|
-
})
|
|
6335
|
+
suffix,
|
|
6336
|
+
message
|
|
6282
6337
|
};
|
|
6283
6338
|
}
|
|
6284
|
-
function
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6339
|
+
function programUserHelp() {
|
|
6340
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
|
|
6341
|
+
|
|
6342
|
+
Usage: extension [command] [options]
|
|
6343
|
+
|
|
6344
|
+
Notes
|
|
6345
|
+
- All high-level commands offer their own \`--help\` with usage and flag lists.
|
|
6346
|
+
- Telemetry is anonymous and privacy-safe by default; see ${messages_code('docs/TELEMETRY.md')} for the full contract.
|
|
6347
|
+
|
|
6348
|
+
Example
|
|
6349
|
+
- ${messages_code('extension create --help')} outputs information about the "create" command.
|
|
6350
|
+
|
|
6351
|
+
Available Commands
|
|
6352
|
+
${availableCommandsBlock()}
|
|
6353
|
+
|
|
6354
|
+
Common Options
|
|
6355
|
+
- ${messages_code('--browser')} ${messages_arg('<chrome|edge|firefox|chromium|chromium-based|gecko-based|firefox-based>')} Target browser/engine (default: chromium)
|
|
6356
|
+
- ${messages_code('--profile')} ${messages_arg('<path|boolean>')} Browser profile configuration
|
|
6357
|
+
- ${messages_code('--polyfill')} ${messages_arg('[boolean]')} Enable/disable cross-browser polyfill
|
|
6358
|
+
- ${messages_code('--no-telemetry')} Disable anonymous telemetry for this run (persistent toggle: ${messages_code('extension telemetry disable')}, or ${messages_code('EXTENSION_TELEMETRY=0')})
|
|
6359
|
+
- ${messages_code('--ai-help')} Show AI-assistant oriented help and tips
|
|
6360
|
+
- ${messages_code('--output')} ${messages_arg('<pretty|json>')} Result format for ${messages_code('--ai-help')} and machine-readable command results (default: pretty)
|
|
6361
|
+
${messages_code('--format')} and ${messages_code('--wait-format')} still work as deprecated aliases of ${messages_code('--output')}
|
|
6362
|
+
- ${messages_code('--help')} Show help output
|
|
6363
|
+
- ${messages_code('--port')} ${messages_arg('<number>')} Development server port (default: 8080; use 0 for OS-assigned)
|
|
6364
|
+
- ${messages_code('--host')} ${messages_arg('<address>')} Dev server host (default: 127.0.0.1; use 0.0.0.0 for Docker/devcontainers)
|
|
6365
|
+
- ${messages_code('--public-host')} ${messages_arg('<address>')} Connectable host the browser dials for HMR + reload bridge when it differs from ${messages_code('--host')} (remote/devcontainer; default: the bind host, or 127.0.0.1 when bound to 0.0.0.0)
|
|
6366
|
+
- ${messages_code('--starting-url')} ${messages_arg('<url>')} Initial URL to load in browser
|
|
6367
|
+
- ${messages_code('--silent')} ${messages_arg('[boolean]')} Suppress console output during build
|
|
6368
|
+
|
|
6369
|
+
Browser-Specific Options
|
|
6370
|
+
- ${messages_code('--chromium-binary')} ${messages_arg('<path>')} Custom Chromium binary path
|
|
6371
|
+
- ${messages_code('--gecko-binary')}/${messages_code('--firefox-binary')} ${messages_arg('<path>')} Custom Firefox/Gecko binary path
|
|
6372
|
+
Use ${messages_code('flatpak:org.mozilla.firefox')} as the path to launch a Flatpak-installed Firefox
|
|
6373
|
+
|
|
6374
|
+
Build Options
|
|
6375
|
+
- ${messages_code('--zip')} ${messages_arg('[boolean]')} Create ZIP archive of built extension
|
|
6376
|
+
- ${messages_code('--zip-source')} ${messages_arg('[boolean]')} Include source files in ZIP
|
|
6377
|
+
- ${messages_code('--zip-filename')} ${messages_arg('<name>')} Custom ZIP filename
|
|
6378
|
+
|
|
6379
|
+
${external_pintor_default().underline('Centralized Logger (terminal output)')}
|
|
6380
|
+
- The manager extension embeds a centralized logger that streams events to the CLI.
|
|
6381
|
+
- Enable and filter logs directly via ${messages_code('extension dev')} flags:
|
|
6382
|
+
- ${messages_code('--logs')} ${messages_arg('<off|error|warn|info|debug|trace>')} Minimum level (default: off)
|
|
6383
|
+
- ${messages_code('--log-context')} ${messages_arg('<list|all>')} Contexts: background,content,page,sidebar,popup,options,devtools
|
|
6384
|
+
- ${messages_code('--log-format')} ${messages_arg('<pretty|json|ndjson>')} Output format (default: pretty)
|
|
6385
|
+
- ${messages_code('--no-log-timestamps')} Hide ISO timestamps in pretty output
|
|
6386
|
+
- ${messages_code('--no-log-color')} Disable color in pretty output
|
|
6387
|
+
- ${messages_code('--log-url')} ${messages_arg('<substring|/regex/>')} Filter by event.url
|
|
6388
|
+
- ${messages_code('--log-tab')} ${messages_arg('<id>')} Filter by tabId
|
|
6389
|
+
- Example: ${messages_code('extension dev ./my-ext --logs=debug --log-context=all --log-format=pretty')}
|
|
6390
|
+
|
|
6391
|
+
${messages_code('extension --help')}
|
|
6392
|
+
This command outputs a help file with key command options.
|
|
6393
|
+
|
|
6394
|
+
${external_pintor_default().underline('Path Resolution (important)')}
|
|
6395
|
+
- Leading ${messages_code('/')} in manifest/HTML means extension root (the directory containing ${messages_code('manifest.json')}).
|
|
6396
|
+
- Relative paths resolve from the ${messages_code('manifest.json')} directory.
|
|
6397
|
+
- Absolute OS paths are used as-is.
|
|
6398
|
+
|
|
6399
|
+
AI Assistants
|
|
6400
|
+
- For AI-oriented guidance and deeper tips, run ${messages_code('extension --ai-help')}
|
|
6401
|
+
- For machine-readable AI guidance, run ${messages_code('extension --ai-help --output json')}
|
|
6402
|
+
|
|
6403
|
+
Report issues
|
|
6404
|
+
- ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
|
|
6290
6405
|
}
|
|
6291
|
-
function
|
|
6292
|
-
|
|
6293
|
-
if (frame && 'json' === frame.output) writeFrame(messaging.Pr.fail(frame.command, statusForCode(frame.code), {
|
|
6294
|
-
code: frame.code,
|
|
6295
|
-
message,
|
|
6296
|
-
name: 'CliError'
|
|
6297
|
-
}));
|
|
6298
|
-
process.exit(1);
|
|
6406
|
+
function unsupportedBrowserFlag(value, supported) {
|
|
6407
|
+
return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}.\n${external_pintor_default().red('Choose one of:')} ${supported.join(', ')}${external_pintor_default().red('.')}`;
|
|
6299
6408
|
}
|
|
6300
|
-
function
|
|
6301
|
-
|
|
6302
|
-
if (result.ok) {
|
|
6303
|
-
const value = result.value;
|
|
6304
|
-
console.log('string' == typeof value ? value : JSON.stringify(value, null, 2));
|
|
6305
|
-
if (result.truncated) console.error('… result truncated (byte cap)');
|
|
6306
|
-
return;
|
|
6307
|
-
}
|
|
6308
|
-
const err = result.error || {
|
|
6309
|
-
name: 'Error',
|
|
6310
|
-
message: 'command failed'
|
|
6311
|
-
};
|
|
6312
|
-
console.error(`${err.name}: ${err.message}${err.engine ? ` (engine: ${err.engine})` : ''}`);
|
|
6409
|
+
function safariOnlyOption(flags) {
|
|
6410
|
+
return `${getLoggingPrefix('error')} ${flags.map(messages_code).join(', ')} only appl${1 === flags.length ? 'ies' : 'y'} to Safari targets.\nAdd ${messages_code('--browser safari')} (or ${messages_code('webkit-based')}).`;
|
|
6313
6411
|
}
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
const browser = input.opts.browser || 'chromium';
|
|
6317
|
-
const { BridgeController, readReadyContract, readControlToken } = await loadExtensionDevelopBridgeModule();
|
|
6318
|
-
const outputFrame = {
|
|
6319
|
-
command: input.command,
|
|
6320
|
-
output: input.opts.output
|
|
6321
|
-
};
|
|
6322
|
-
const ready = readReadyContract(projectPath, browser);
|
|
6323
|
-
if (!ready) fail(`No active control channel found for ${browser}. Run \`extension dev --browser=${browser} --allow-control\` first.`, {
|
|
6324
|
-
...outputFrame,
|
|
6325
|
-
code: messaging.Lp.E_SESSION_NOT_FOUND
|
|
6326
|
-
});
|
|
6327
|
-
const token = input.needsToken ? readControlToken(projectPath, browser) : void 0;
|
|
6328
|
-
const controller = new BridgeController({
|
|
6329
|
-
controlPort: ready.controlPort,
|
|
6330
|
-
instanceId: ready.instanceId,
|
|
6331
|
-
token: token ?? void 0
|
|
6332
|
-
});
|
|
6333
|
-
try {
|
|
6334
|
-
await controller.connect();
|
|
6335
|
-
} catch (err) {
|
|
6336
|
-
controller.close();
|
|
6337
|
-
const message = err?.message || 'could not connect to the control channel';
|
|
6338
|
-
fail(message, {
|
|
6339
|
-
...outputFrame,
|
|
6340
|
-
code: /code 40\d\d/.test(message) ? messaging.Lp.E_CONTROL_DENIED : messaging.Lp.E_CONTROL_UNAVAILABLE
|
|
6341
|
-
});
|
|
6342
|
-
}
|
|
6343
|
-
const timeoutMs = input.opts.timeout ? Number(input.opts.timeout) : 5000;
|
|
6344
|
-
let result;
|
|
6345
|
-
try {
|
|
6346
|
-
result = await controller.command({
|
|
6347
|
-
op: input.op,
|
|
6348
|
-
target: input.target,
|
|
6349
|
-
args: input.args,
|
|
6350
|
-
timeoutMs
|
|
6351
|
-
});
|
|
6352
|
-
} catch (err) {
|
|
6353
|
-
controller.close();
|
|
6354
|
-
const message = err?.message || 'command failed';
|
|
6355
|
-
fail(message, {
|
|
6356
|
-
...outputFrame,
|
|
6357
|
-
code: /timed out/i.test(message) ? messaging.Lp.E_TIMEOUT : messaging.Lp.E_CONTROL_UNAVAILABLE
|
|
6358
|
-
});
|
|
6359
|
-
} finally{
|
|
6360
|
-
controller.close();
|
|
6361
|
-
}
|
|
6362
|
-
if (result?.ok && input.augment) try {
|
|
6363
|
-
Object.assign(result, input.augment(projectPath, browser, result));
|
|
6364
|
-
} catch {}
|
|
6365
|
-
printResult(result, input.opts.output, input.command);
|
|
6366
|
-
await exitAfterDrain(result.ok ? 0 : 1);
|
|
6412
|
+
function safariInvalidBundleId(bundleId) {
|
|
6413
|
+
return `${getLoggingPrefix('error')} Invalid bundle identifier: ${messages_code(bundleId)}.\nUse reverse-DNS form: dot-separated segments of letters, digits and hyphens, each starting with a letter (e.g. ${messages_code('com.example.my-extension')}).`;
|
|
6367
6414
|
}
|
|
6368
|
-
function
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
}
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6415
|
+
function safariCommandNotSupported(command) {
|
|
6416
|
+
return `${getLoggingPrefix('error')} ${messages_code(command)} can't load an extension into Safari automatically.\nSafari extensions ship inside a signed app and are enabled by hand, so there's no live browser session to load into, unlike Chromium and Firefox.\nBuild the Safari app instead: ${messages_code('extension build --browser safari')}\nThen open the generated app and enable it in Safari → Settings → Extensions.`;
|
|
6417
|
+
}
|
|
6418
|
+
function programAIHelp() {
|
|
6419
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
|
|
6420
|
+
|
|
6421
|
+
Browser-Specific Configuration
|
|
6422
|
+
- Use browser prefixes in manifest.json for browser-specific fields:
|
|
6423
|
+
${messages_code('{"firefox:manifest": 2, "chrome:manifest": 3}')}
|
|
6424
|
+
This applies manifest v2 to Firefox only, v3 to Chrome/Edge.
|
|
6425
|
+
|
|
6426
|
+
Centralized Logger (for AI & CI)
|
|
6427
|
+
- Logs from all contexts are centralized by the manager extension and streamed to the CLI.
|
|
6428
|
+
- Prefer these flags to control terminal logs during ${messages_code('extension dev')}:
|
|
6429
|
+
- ${messages_code('--logs')} ${messages_arg('<off|error|warn|info|debug|trace>')} Minimum level
|
|
6430
|
+
- ${messages_code('--log-context')} ${messages_arg('<list|all>')} Contexts to include
|
|
6431
|
+
- ${messages_code('--log-format')} ${messages_arg('<pretty|json|ndjson>')} Pretty for humans; JSON for machines/NDJSON pipelines
|
|
6432
|
+
- ${messages_code('--no-log-timestamps')} ${messages_arg(' ')} Disable timestamps (pretty)
|
|
6433
|
+
- ${messages_code('--no-log-color')} ${messages_arg(' ')} Disable ANSI colors (pretty)
|
|
6434
|
+
- ${messages_code('--log-url')} ${messages_arg('<substring|/regex/>')} Filter by URL
|
|
6435
|
+
- ${messages_code('--log-tab')} ${messages_arg('<id>')} Filter by tabId
|
|
6436
|
+
- Good CI pattern: ${messages_code('EXTENSION_DEBUG=1 EXTENSION_AUTO_EXIT_MS=6000 extension dev ./ext --logs=info --log-format=json')}
|
|
6437
|
+
|
|
6438
|
+
Special Folders for Entrypoints
|
|
6439
|
+
- Use special folders to handle entrypoints and assets not declared in manifest.json:
|
|
6440
|
+
- ${external_pintor_default().underline(messages_code('public/'))} - Static assets automatically copied to build (resolves to output root)
|
|
6441
|
+
- ${external_pintor_default().underline(messages_code('pages/'))} - HTML files not declared in manifest (e.g., welcome pages)
|
|
6442
|
+
- ${external_pintor_default().underline(messages_code("scripts/"))} - JavaScript files not declared in manifest (e.g., executable scripts)
|
|
6443
|
+
|
|
6444
|
+
Predictable Output Paths
|
|
6445
|
+
- Core HTML destinations are standardized across browsers so you can reference them safely in code/tests:
|
|
6446
|
+
- ${messages_code('devtools_page')} → ${messages_code('devtools/index.html')}
|
|
6447
|
+
- ${messages_code('sidebar_action.default_panel')} (MV2) and ${messages_code('side_panel.default_path')} (MV3) → ${messages_code('sidebar/index.html')}
|
|
6448
|
+
- ${messages_code('options_ui.page')} and ${messages_code('options_page')} → ${messages_code('options/index.html')}
|
|
6449
|
+
- ${messages_code('background.page')} → ${messages_code('background/index.html')}
|
|
6450
|
+
- ${messages_code('action.default_popup')}, ${messages_code('browser_action.default_popup')}, ${messages_code('page_action.default_popup')} → ${messages_code('action/index.html')}
|
|
6451
|
+
- Other predictable outputs:
|
|
6452
|
+
- ${messages_code('chrome_url_overrides.*')} → ${messages_code('chrome_url_overrides/<key>.html')}
|
|
6453
|
+
- ${messages_code("content_scripts[n].js/css")} → ${messages_code("content_scripts/content-<n>.{js,css}")}
|
|
6454
|
+
- ${messages_code('sandbox.pages[]')} → ${messages_code('sandbox/page-<n>.html')}
|
|
6455
|
+
- ${messages_code("user_scripts.api_script")} → ${messages_code("user_scripts/api_script.js")}
|
|
6456
|
+
- ${messages_code('icons/*')} → ${messages_code('icons/')} (feature-specific icon folders preserved where applicable)
|
|
6457
|
+
|
|
6458
|
+
Public & Special Folders (Output Behavior)
|
|
6459
|
+
- ${external_pintor_default().underline(messages_code('public/'))} is the web root in output. Authors can use ${messages_code('/foo')}, ${messages_code('/public/foo')}, ${messages_code('public/foo')}, or ${messages_code('./public/foo')} and they all emit as ${messages_code('dist/<browser>/foo')}.
|
|
6460
|
+
- ${external_pintor_default().underline(messages_code('pages/'))} files emit as ${messages_code('pages/<name>.html')}. Relative assets referenced inside page HTML are emitted under ${messages_code('assets/')} preserving relative structure; public-root URLs are preserved.
|
|
6461
|
+
- ${external_pintor_default().underline(messages_code("scripts/"))} files emit as ${messages_code("scripts/<name>.js")} with extracted CSS when applicable.
|
|
6462
|
+
|
|
6463
|
+
Shadow DOM for Content Scripts
|
|
6464
|
+
- Add ${messages_code('use shadow-dom')} directive to content scripts for style isolation
|
|
6465
|
+
- Automatically creates ${messages_code('#extension-root')} element with shadow DOM
|
|
6466
|
+
- All CSS imports are automatically injected into shadow DOM
|
|
6467
|
+
- Prevents style conflicts with host page
|
|
6468
|
+
|
|
6469
|
+
Environment Variables
|
|
6470
|
+
- Use ${messages_code(messages_arg('EXTENSION_PUBLIC_*'))} prefix for variables accessible in extension code
|
|
6471
|
+
- Supported in both ${messages_code('process.env')} and ${messages_code('import.meta.env')}
|
|
6472
|
+
- Environment file priority: ${external_pintor_default().underline(messages_code(messages_arg('.env.{browser}.{mode}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env.{browser}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env.{mode}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env')))}
|
|
6473
|
+
- Example: ${messages_code(messages_arg('EXTENSION_PUBLIC_API_KEY=your_key'))}
|
|
6474
|
+
|
|
6475
|
+
Available Templates
|
|
6476
|
+
- ${external_pintor_default().green('Frameworks')}: ${messages_code(messages_arg('react'))}, ${messages_code(messages_arg('preact'))}, ${messages_code(messages_arg('vue'))}, ${messages_code(messages_arg('svelte'))}
|
|
6477
|
+
- ${external_pintor_default().green('Languages')}: ${messages_code(messages_arg("javascript"))}, ${messages_code(messages_arg("typescript"))}
|
|
6478
|
+
- ${external_pintor_default().green('Contexts')}: ${messages_code(messages_arg('content'))} (content scripts), ${messages_code(messages_arg('new'))} (new tab), ${messages_code(messages_arg('action'))} (popup)
|
|
6479
|
+
- ${external_pintor_default().green('Styling')}: ${messages_code(messages_arg('tailwind'))}, ${messages_code(messages_arg('sass'))}, ${messages_code(messages_arg('less'))}
|
|
6480
|
+
- ${external_pintor_default().green('Configs')}: ${messages_code(messages_arg('eslint'))}, ${messages_code(messages_arg('prettier'))}, ${messages_code(messages_arg('stylelint'))}
|
|
6481
|
+
|
|
6482
|
+
Webpack/Rspack Configuration
|
|
6483
|
+
- Create ${external_pintor_default().underline(messages_code(messages_arg('extension.config.js')))} for custom webpack configuration
|
|
6484
|
+
- Function receives base config, return modified config
|
|
6485
|
+
- Supports all webpack/rspack loaders and plugins
|
|
6486
|
+
- Example:
|
|
6487
|
+
${messages_code('export default {')}
|
|
6488
|
+
${messages_code(' config: (config) => {')}
|
|
6489
|
+
${messages_code(" config.module.rules.push({ test: /\\.svg$/, use: ['@svgr/webpack'] })")}
|
|
6490
|
+
${messages_code(' return config')}
|
|
6491
|
+
${messages_code(' }')}
|
|
6492
|
+
${messages_code('}')}
|
|
6493
|
+
|
|
6494
|
+
Managed Dependencies (Important)
|
|
6495
|
+
- ${external_pintor_default().green('Do not add')} packages that ${external_pintor_default().blue('Extension.js')} already ships in its own toolchain.
|
|
6496
|
+
- The guard only triggers when a managed package is declared in your ${messages_code('package.json')} ${external_pintor_default().gray('and')} is imported (as a module specifier) in your ${external_pintor_default().underline(messages_code('extension.config.js'))}.
|
|
6497
|
+
- In that case, the program will ${external_pintor_default().red('print an error and abort')} to avoid version conflicts.
|
|
6498
|
+
- Remove the duplicate from your project ${messages_code('package.json')} or avoid referencing it in ${external_pintor_default().underline(messages_code('extension.config.js'))} and rely on the built-in version instead.
|
|
6499
|
+
- If you truly need a different version, open an issue so we can evaluate a safe upgrade.
|
|
6500
|
+
|
|
6501
|
+
Framework-Specific Configuration
|
|
6502
|
+
- Create ${external_pintor_default().underline(messages_code(messages_arg('vue.loader.js')))} for Vue-specific loader configuration
|
|
6503
|
+
- Create ${external_pintor_default().underline(messages_code(messages_arg('svelte.loader.js')))} for Svelte-specific loader configuration
|
|
6504
|
+
- Automatically detected and used by Extension.js
|
|
6505
|
+
- Example svelte.loader.js:
|
|
6506
|
+
${messages_code('module.exports = {')}
|
|
6507
|
+
${messages_code(' preprocess: require("svelte-preprocess")({')}
|
|
6508
|
+
${messages_code(" typescript: true")}
|
|
6509
|
+
${messages_code(' })')}
|
|
6510
|
+
${messages_code('}')}
|
|
6511
|
+
|
|
6512
|
+
Hot Module Replacement (HMR)
|
|
6513
|
+
- Automatically enabled in development mode
|
|
6514
|
+
- CSS changes trigger automatic style updates
|
|
6515
|
+
- React components fast-refresh; Svelte components hot-update
|
|
6516
|
+
- Preact and Vue rebuild with a live reload (component state resets)
|
|
6517
|
+
- Content scripts automatically re-inject on changes
|
|
6518
|
+
- Service workers, _locales and manifest changes reload the extension
|
|
6519
|
+
|
|
6520
|
+
Non-Destructive Testing in CI
|
|
6521
|
+
- Prefer ${messages_code('EXTENSION_DEBUG=1')} to copy local templates and avoid network.
|
|
6522
|
+
- Reuse Playwright's Chromium via ${messages_code('--chromium-binary')} path when available.
|
|
6523
|
+
- Set ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS'))} and ${messages_code(messages_arg('EXTENSION_FORCE_KILL_MS'))} for non-interactive dev sessions.
|
|
6524
|
+
|
|
6525
|
+
File Watching & HMR Examples
|
|
6526
|
+
- Content script JS/TS changes trigger reinjection; CSS changes update styles live.
|
|
6527
|
+
- For watch-source HTML prints, update a visible string in ${messages_code("content/scripts.*")} and assert it appears in stdout.
|
|
6528
|
+
|
|
6529
|
+
Troubleshooting
|
|
6530
|
+
- Use ${messages_code('--silent true')} during builds to reduce noise; logs still surface errors.
|
|
6531
|
+
- When ports conflict, pass ${messages_code('--port 0')} to auto-select an available port.
|
|
6532
|
+
- In Docker/devcontainers, pass ${messages_code('--host 0.0.0.0')} so the dev server is reachable from the host.
|
|
6533
|
+
|
|
6534
|
+
Non-Interactive / Auto Mode (CI)
|
|
6535
|
+
- Set ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS'))} to enable self-termination after N milliseconds.
|
|
6536
|
+
Useful when ${messages_code('pnpm extension dev')} would otherwise hang under Rspack watch.
|
|
6537
|
+
Example: ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS=6000'))} pnpm extension dev ./templates/react --browser chrome --starting-url ${messages_arg('https://example.com')}
|
|
6538
|
+
- Optional: ${messages_code(messages_arg('EXTENSION_FORCE_KILL_MS'))} to hard-exit after N ms as a fallback (defaults to auto-exit + 4000).
|
|
6539
|
+
|
|
6540
|
+
Docker / Devcontainers / Codespaces
|
|
6541
|
+
- Use ${messages_code('--host 0.0.0.0')} to bind the dev server on all interfaces so HMR is reachable from the host.
|
|
6542
|
+
- Use ${messages_code('--no-browser')} inside the container and load the extension manually from ${messages_code('dist/<browser>/')} in your host browser.
|
|
6543
|
+
- Chromium sandbox flags (${messages_code('--no-sandbox')}) are added automatically when Docker, Podman, devcontainers, or Codespaces are detected.
|
|
6544
|
+
- File watching uses polling by default (1 s interval), which works across bind-mounted volumes.
|
|
6545
|
+
- Example: ${messages_code('extension dev ./my-ext --host 0.0.0.0 --no-browser --port 8080')}
|
|
6546
|
+
|
|
6547
|
+
Flatpak Firefox
|
|
6548
|
+
- Use ${messages_code('--gecko-binary flatpak:org.mozilla.firefox')} (or ${messages_code('--firefox-binary')}) to launch a Flatpak-installed Firefox.
|
|
6549
|
+
- Extension.js rewrites the binary path to ${messages_code('flatpak run')} with the correct filesystem grants automatically.
|
|
6550
|
+
|
|
6551
|
+
Cross-Browser Compatibility
|
|
6552
|
+
- Use ${messages_code('--polyfill')} flag to enable webextension-polyfill
|
|
6553
|
+
- Automatically handles browser API differences
|
|
6554
|
+
- Supports Chrome, Edge, Firefox with single codebase`;
|
|
6376
6555
|
}
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6556
|
+
function programAIHelpJSON(version) {
|
|
6557
|
+
return {
|
|
6558
|
+
version,
|
|
6559
|
+
commands: COMMANDS.map((spec)=>({
|
|
6560
|
+
name: spec.name,
|
|
6561
|
+
summary: spec.description,
|
|
6562
|
+
supportsSourceInspection: spec.supportsSourceInspection
|
|
6563
|
+
})),
|
|
6564
|
+
globalOptions: [
|
|
6565
|
+
{
|
|
6566
|
+
name: '--ai-help',
|
|
6567
|
+
description: 'Show AI-assistant oriented help and tips'
|
|
6387
6568
|
},
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
command: 'storage',
|
|
6397
|
-
op: 'storage.get',
|
|
6398
|
-
target: targetFrom(opts),
|
|
6399
|
-
args: opts.key ? {
|
|
6400
|
-
area,
|
|
6401
|
-
key: opts.key
|
|
6402
|
-
} : {
|
|
6403
|
-
area
|
|
6569
|
+
{
|
|
6570
|
+
name: '--output',
|
|
6571
|
+
values: [
|
|
6572
|
+
'pretty',
|
|
6573
|
+
'json'
|
|
6574
|
+
],
|
|
6575
|
+
default: 'pretty',
|
|
6576
|
+
description: 'Result format for --ai-help (--format is a deprecated alias)'
|
|
6404
6577
|
},
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6578
|
+
{
|
|
6579
|
+
name: '--no-telemetry',
|
|
6580
|
+
description: 'Disable anonymous telemetry for this run. Persistent toggle: `extension telemetry disable`. Hard override: `EXTENSION_TELEMETRY=0`.'
|
|
6581
|
+
},
|
|
6582
|
+
{
|
|
6583
|
+
name: '--browser',
|
|
6584
|
+
values: [
|
|
6585
|
+
'chrome',
|
|
6586
|
+
'edge',
|
|
6587
|
+
'firefox',
|
|
6588
|
+
'chromium',
|
|
6589
|
+
'chromium-based',
|
|
6590
|
+
'gecko-based',
|
|
6591
|
+
'firefox-based'
|
|
6592
|
+
],
|
|
6593
|
+
default: 'chromium',
|
|
6594
|
+
description: 'Target browser/engine'
|
|
6595
|
+
},
|
|
6596
|
+
{
|
|
6597
|
+
name: '--port',
|
|
6598
|
+
default: '8080',
|
|
6599
|
+
description: 'Development server port (use 0 for OS-assigned available port)'
|
|
6600
|
+
},
|
|
6601
|
+
{
|
|
6602
|
+
name: '--host',
|
|
6603
|
+
default: '127.0.0.1',
|
|
6604
|
+
description: 'Dev server host address (use 0.0.0.0 for Docker/devcontainers)'
|
|
6605
|
+
},
|
|
6606
|
+
{
|
|
6607
|
+
name: '--public-host',
|
|
6608
|
+
default: 'bind host (127.0.0.1 when bound to 0.0.0.0)',
|
|
6609
|
+
description: 'Connectable host the browser dials for HMR + the reload bridge when it differs from the bind host (remote/devcontainer)'
|
|
6418
6610
|
}
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
commonOptions(program.command('reload').arguments('[project-path]').description(commandDescriptions.reload).option('--context <background|content|page>', 'target context (default background)').option('--tab <id>', 'for content/page: a specific tab')).action(async (projectPathArg, opts)=>{
|
|
6441
|
-
await runCommand({
|
|
6442
|
-
projectPathArg,
|
|
6443
|
-
command: 'reload',
|
|
6444
|
-
op: 'reload',
|
|
6445
|
-
target: targetFrom(opts),
|
|
6446
|
-
opts
|
|
6447
|
-
});
|
|
6448
|
-
});
|
|
6449
|
-
commonOptions(program.command('inspect').arguments('[project-path]').description(commandDescriptions.inspect).option('--context <content|page|popup|options|sidebar|devtools|newtab|history|bookmarks>', 'what to inspect: content/page or an open surface, including url-override pages (default content)').option('--url <glob|substring>', 'for content/page: document to target (resolved to its tab)').option('--tab <id>', 'for content/page: a specific tab (default: the --url match, else the active tab)').option('--list-tabs', 'list open tabs as {tabId,url,title} and exit').option('--include <list>', 'comma-separated: html,summary (default summary)').option('--max-bytes <n>', 'cap on returned HTML bytes (default 262144)').option('--with-console [n]', 'also include the last n console lines for the target (default 20)')).action(async (projectPathArg, opts)=>{
|
|
6450
|
-
if (opts.listTabs) return void await runCommand({
|
|
6451
|
-
projectPathArg,
|
|
6452
|
-
command: 'inspect',
|
|
6453
|
-
op: 'tabs.query',
|
|
6454
|
-
target: {
|
|
6455
|
-
context: 'background'
|
|
6611
|
+
],
|
|
6612
|
+
capabilities: {
|
|
6613
|
+
logger: {
|
|
6614
|
+
levels: [
|
|
6615
|
+
'off',
|
|
6616
|
+
'error',
|
|
6617
|
+
'warn',
|
|
6618
|
+
'info',
|
|
6619
|
+
'debug',
|
|
6620
|
+
'trace',
|
|
6621
|
+
'all'
|
|
6622
|
+
],
|
|
6623
|
+
formats: [
|
|
6624
|
+
'pretty',
|
|
6625
|
+
'json',
|
|
6626
|
+
'ndjson'
|
|
6627
|
+
],
|
|
6628
|
+
notes: [
|
|
6629
|
+
'centralized logger streams logs from multiple extension contexts',
|
|
6630
|
+
'--logs defaults to off unless explicitly enabled'
|
|
6631
|
+
]
|
|
6456
6632
|
},
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
'summary'
|
|
6462
|
-
];
|
|
6463
|
-
const target = targetFrom(opts, 'content');
|
|
6464
|
-
await runCommand({
|
|
6465
|
-
projectPathArg,
|
|
6466
|
-
command: 'inspect',
|
|
6467
|
-
op: 'inspect',
|
|
6468
|
-
target,
|
|
6469
|
-
args: {
|
|
6470
|
-
include,
|
|
6471
|
-
maxBytes: opts.maxBytes ? Number(opts.maxBytes) : void 0
|
|
6633
|
+
managedDependencies: {
|
|
6634
|
+
enforcement: 'guarded',
|
|
6635
|
+
trigger: 'when managed packages are declared in package.json and imported as a module specifier in extension.config',
|
|
6636
|
+
action: 'print an error and abort'
|
|
6472
6637
|
},
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6638
|
+
readyContract: {
|
|
6639
|
+
readyPath: 'dist/extension-js/<browser>/ready.json',
|
|
6640
|
+
eventsPath: 'dist/extension-js/<browser>/events.ndjson',
|
|
6641
|
+
waitFlag: '--wait blocks until ready.json reports ready (or error) then exits; pair with --output json for machine output (--wait-format is a deprecated alias)',
|
|
6642
|
+
statuses: [
|
|
6643
|
+
'starting',
|
|
6644
|
+
'ready',
|
|
6645
|
+
'error'
|
|
6646
|
+
],
|
|
6647
|
+
readyFields: [
|
|
6648
|
+
'status',
|
|
6649
|
+
'command',
|
|
6650
|
+
'browser',
|
|
6651
|
+
'runId',
|
|
6652
|
+
'startedAt',
|
|
6653
|
+
'distPath',
|
|
6654
|
+
'manifestPath',
|
|
6655
|
+
'port',
|
|
6656
|
+
'pid',
|
|
6657
|
+
'ts',
|
|
6658
|
+
'compiledAt',
|
|
6659
|
+
'errors'
|
|
6660
|
+
],
|
|
6661
|
+
eventTypes: [
|
|
6662
|
+
'compile_start',
|
|
6663
|
+
'compile_success',
|
|
6664
|
+
'compile_error',
|
|
6665
|
+
'shutdown'
|
|
6666
|
+
],
|
|
6667
|
+
notes: [
|
|
6668
|
+
'ready.json is written atomically by the build (dev/start) on each compile',
|
|
6669
|
+
'events.ndjson is an append-only build timeline with durationMs and errorCount per entry',
|
|
6670
|
+
'--wait requires a local project path (remote URLs are not supported)',
|
|
6671
|
+
'consumers should verify pid liveness and recency before trusting a contract'
|
|
6672
|
+
]
|
|
6507
6673
|
},
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
return cleaned.length > 0 ? cleaned : 'Extension';
|
|
6524
|
-
}
|
|
6525
|
-
function bundleSegment(appName) {
|
|
6526
|
-
return String(appName || '').replace(/[^A-Za-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'extension';
|
|
6527
|
-
}
|
|
6528
|
-
function deriveBundleId(appName) {
|
|
6529
|
-
return `dev.extensionjs.${bundleSegment(appName)}`;
|
|
6530
|
-
}
|
|
6531
|
-
function isValidBundleId(value) {
|
|
6532
|
-
return /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/.test(value);
|
|
6533
|
-
}
|
|
6534
|
-
function readManifest(extensionDir) {
|
|
6535
|
-
try {
|
|
6536
|
-
const manifestPath = external_node_path_.join(extensionDir, 'manifest.json');
|
|
6537
|
-
if (external_node_fs_.existsSync(manifestPath)) return JSON.parse(external_node_fs_.readFileSync(manifestPath, 'utf8')) || {};
|
|
6538
|
-
} catch {}
|
|
6539
|
-
return {};
|
|
6540
|
-
}
|
|
6541
|
-
function resolveSafariBuildConfig(compilation, host) {
|
|
6542
|
-
const extensionDir = String(compilation?.options?.output?.path || '');
|
|
6543
|
-
const manifest = readManifest(extensionDir);
|
|
6544
|
-
const appName = sanitizeAppName(String(host.appName || manifest?.name || 'Extension'));
|
|
6545
|
-
const userBundleId = String(host.bundleId || '').trim();
|
|
6546
|
-
const bundleIdDerived = !userBundleId;
|
|
6547
|
-
const bundleIdentifier = bundleIdDerived ? deriveBundleId(appName) : userBundleId;
|
|
6548
|
-
const projectLocation = `${extensionDir.replace(/[\\/]+$/, '')}-xcode`;
|
|
6549
|
-
return {
|
|
6550
|
-
extensionDir,
|
|
6551
|
-
projectLocation,
|
|
6552
|
-
appName,
|
|
6553
|
-
bundleIdentifier,
|
|
6554
|
-
bundleIdDerived,
|
|
6555
|
-
macOsOnly: false !== host.macOsOnly,
|
|
6556
|
-
language: 'swift',
|
|
6557
|
-
open: !host.noOpen,
|
|
6558
|
-
safariBinary: host.safariBinary
|
|
6559
|
-
};
|
|
6560
|
-
}
|
|
6561
|
-
function composeConverterArgs(config) {
|
|
6562
|
-
const args = [
|
|
6563
|
-
'safari-web-extension-converter',
|
|
6564
|
-
config.extensionDir,
|
|
6565
|
-
'--project-location',
|
|
6566
|
-
config.projectLocation,
|
|
6567
|
-
'--app-name',
|
|
6568
|
-
config.appName,
|
|
6569
|
-
'--bundle-identifier',
|
|
6570
|
-
config.bundleIdentifier,
|
|
6571
|
-
'--no-prompt',
|
|
6572
|
-
'--no-open',
|
|
6573
|
-
'--force',
|
|
6574
|
-
'objc' === config.language ? '--objc' : '--swift'
|
|
6575
|
-
];
|
|
6576
|
-
if (config.macOsOnly) args.push('--macos-only');
|
|
6577
|
-
return args;
|
|
6578
|
-
}
|
|
6579
|
-
function macOsSchemeName(config) {
|
|
6580
|
-
return config.macOsOnly ? config.appName : `${config.appName} (macOS)`;
|
|
6581
|
-
}
|
|
6582
|
-
function xcodeProjectPath(config) {
|
|
6583
|
-
return external_node_path_.join(config.projectLocation, config.appName, `${config.appName}.xcodeproj`);
|
|
6584
|
-
}
|
|
6585
|
-
function derivedDataPath(config) {
|
|
6586
|
-
return external_node_path_.join(config.projectLocation, '.derived');
|
|
6587
|
-
}
|
|
6588
|
-
function builtAppPath(config) {
|
|
6589
|
-
return external_node_path_.join(derivedDataPath(config), 'Build', 'Products', 'Release', `${config.appName}.app`);
|
|
6590
|
-
}
|
|
6591
|
-
function composeXcodebuildArgs(config) {
|
|
6592
|
-
return [
|
|
6593
|
-
'-project',
|
|
6594
|
-
xcodeProjectPath(config),
|
|
6595
|
-
'-scheme',
|
|
6596
|
-
macOsSchemeName(config),
|
|
6597
|
-
'-configuration',
|
|
6598
|
-
'Release',
|
|
6599
|
-
'-derivedDataPath',
|
|
6600
|
-
derivedDataPath(config),
|
|
6601
|
-
'CODE_SIGN_IDENTITY=-',
|
|
6602
|
-
'CODE_SIGNING_REQUIRED=NO',
|
|
6603
|
-
'CODE_SIGNING_ALLOWED=YES',
|
|
6604
|
-
'build'
|
|
6605
|
-
];
|
|
6606
|
-
}
|
|
6607
|
-
function manifestFingerprintPath(config) {
|
|
6608
|
-
return external_node_path_.join(config.projectLocation, '.manifest-fingerprint');
|
|
6609
|
-
}
|
|
6610
|
-
function stableStringify(obj) {
|
|
6611
|
-
if (null == obj) return JSON.stringify(obj);
|
|
6612
|
-
if ('object' != typeof obj) return JSON.stringify(obj);
|
|
6613
|
-
if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(',')}]`;
|
|
6614
|
-
const keys = Object.keys(obj).sort();
|
|
6615
|
-
return `{${keys.map((k)=>`${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',')}}`;
|
|
6616
|
-
}
|
|
6617
|
-
function readManifestRaw(extensionDir) {
|
|
6618
|
-
try {
|
|
6619
|
-
return external_node_fs_.readFileSync(external_node_path_.join(extensionDir, 'manifest.json'), 'utf8');
|
|
6620
|
-
} catch {
|
|
6621
|
-
return '';
|
|
6622
|
-
}
|
|
6623
|
-
}
|
|
6624
|
-
function normalizeManifest(raw) {
|
|
6625
|
-
try {
|
|
6626
|
-
return stableStringify(JSON.parse(raw));
|
|
6627
|
-
} catch {
|
|
6628
|
-
return raw;
|
|
6629
|
-
}
|
|
6630
|
-
}
|
|
6631
|
-
function composeProjectFingerprint(config) {
|
|
6632
|
-
return JSON.stringify({
|
|
6633
|
-
v: 2,
|
|
6634
|
-
identity: {
|
|
6635
|
-
appName: config.appName,
|
|
6636
|
-
bundleId: config.bundleIdentifier,
|
|
6637
|
-
macOsOnly: config.macOsOnly
|
|
6674
|
+
dockerAndContainers: {
|
|
6675
|
+
hostFlag: '--host 0.0.0.0 binds the dev server to all interfaces',
|
|
6676
|
+
sandboxDetection: [
|
|
6677
|
+
'/.dockerenv',
|
|
6678
|
+
'/run/.containerenv',
|
|
6679
|
+
'REMOTE_CONTAINERS=true',
|
|
6680
|
+
'CODESPACES=true',
|
|
6681
|
+
'container env var'
|
|
6682
|
+
],
|
|
6683
|
+
notes: [
|
|
6684
|
+
'Use --no-browser inside the container and load dist/<browser>/ in the host browser',
|
|
6685
|
+
'File watching uses polling (1s interval) for bind-mount compatibility',
|
|
6686
|
+
'--no-sandbox is added automatically when a container environment is detected'
|
|
6687
|
+
]
|
|
6688
|
+
}
|
|
6638
6689
|
},
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6690
|
+
examples: [
|
|
6691
|
+
'extension --ai-help',
|
|
6692
|
+
'extension --ai-help --output json',
|
|
6693
|
+
'extension dev ./my-ext --logs=info --log-format=json',
|
|
6694
|
+
'extension dev ./my-ext --host 0.0.0.0 --no-browser',
|
|
6695
|
+
'extension dev ./my-ext --wait --browser=chromium --output json',
|
|
6696
|
+
'extension start ./my-ext --wait --browser=chromium --output json',
|
|
6697
|
+
'extension dev ./my-ext --gecko-binary flatpak:org.mozilla.firefox',
|
|
6698
|
+
'extension install chromium',
|
|
6699
|
+
'extension install --where',
|
|
6700
|
+
'extension uninstall --where',
|
|
6701
|
+
'extension uninstall --all'
|
|
6702
|
+
]
|
|
6703
|
+
};
|
|
6647
6704
|
}
|
|
6648
|
-
function
|
|
6649
|
-
|
|
6650
|
-
if (!external_node_fs_.existsSync(fpPath)) return true;
|
|
6651
|
-
const stored = external_node_fs_.readFileSync(fpPath, 'utf8');
|
|
6652
|
-
return stored !== composeProjectFingerprint(config);
|
|
6705
|
+
function invalidAIHelpFormat(value) {
|
|
6706
|
+
return `${getLoggingPrefix('error')} Invalid value for ${messages_code('--output')}: ${external_pintor_default().red(String(value))}.\n${external_pintor_default().red('Pass')} ${messages_arg('pretty')} ${external_pintor_default().red('or')} ${messages_arg('json')}${external_pintor_default().red(', for example')} ${messages_code('extension --ai-help --output json')}${external_pintor_default().red('.')}`;
|
|
6653
6707
|
}
|
|
6654
|
-
function
|
|
6655
|
-
return
|
|
6708
|
+
function removedNoRunnerFlag() {
|
|
6709
|
+
return `${getLoggingPrefix('error')} ${messages_code('--no-runner')} was removed.\nUse ${messages_code('--no-browser')} instead.`;
|
|
6656
6710
|
}
|
|
6657
|
-
|
|
6658
|
-
'
|
|
6659
|
-
'CODE_SIGN_STYLE',
|
|
6660
|
-
'PROVISIONING_PROFILE_SPECIFIER'
|
|
6661
|
-
];
|
|
6662
|
-
function pbxprojPath(config) {
|
|
6663
|
-
return external_node_path_.join(xcodeProjectPath(config), 'project.pbxproj');
|
|
6711
|
+
function deprecatedOutputAlias(flag) {
|
|
6712
|
+
return `${getLoggingPrefix('warn')} ${messages_code(flag)} is deprecated and maps to ${messages_code('--output')}.\nPass ${messages_code('--output')} ${messages_arg('<pretty|json>')} instead.`;
|
|
6664
6713
|
}
|
|
6665
|
-
function
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6714
|
+
function noBrowserNotSupportedForCommand(command) {
|
|
6715
|
+
return `${getLoggingPrefix('error')} ${messages_code('--no-browser')} is only supported for ${messages_code('dev')}, ${messages_code('start')}, and ${messages_code('preview')}.\nReceived command: ${messages_code(command || '(none)')}`;
|
|
6716
|
+
}
|
|
6717
|
+
function readRecentConsole(projectPath, browser, target, limit) {
|
|
6718
|
+
const file = external_node_path_default().resolve(projectPath, 'dist', 'extension-js', browser, 'logs.ndjson');
|
|
6719
|
+
let lines;
|
|
6720
|
+
try {
|
|
6721
|
+
lines = external_node_fs_default().readFileSync(file, 'utf-8').split('\n').filter(Boolean);
|
|
6722
|
+
} catch {
|
|
6723
|
+
return [];
|
|
6724
|
+
}
|
|
6725
|
+
const out = [];
|
|
6726
|
+
for (const line of lines){
|
|
6727
|
+
let e;
|
|
6728
|
+
try {
|
|
6729
|
+
e = JSON.parse(line);
|
|
6730
|
+
} catch {
|
|
6731
|
+
continue;
|
|
6732
|
+
}
|
|
6733
|
+
if (e && 'header' !== e.type) {
|
|
6734
|
+
if (!target.context || e.context === target.context) {
|
|
6735
|
+
if (null == target.tabId || e.tabId === target.tabId) out.push({
|
|
6736
|
+
seq: e.seq,
|
|
6737
|
+
level: e.level,
|
|
6738
|
+
context: e.context,
|
|
6739
|
+
messageParts: e.messageParts,
|
|
6740
|
+
eventType: e.eventType,
|
|
6741
|
+
code: e.code,
|
|
6742
|
+
tabId: e.tabId
|
|
6743
|
+
});
|
|
6744
|
+
}
|
|
6672
6745
|
}
|
|
6673
6746
|
}
|
|
6674
|
-
return
|
|
6747
|
+
return out.slice(Math.max(0, out.length - limit));
|
|
6675
6748
|
}
|
|
6676
|
-
function
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
return
|
|
6749
|
+
function codeForBridgeError(name, message) {
|
|
6750
|
+
if ('Timeout' === name) return messaging.Lp.E_TIMEOUT;
|
|
6751
|
+
if ('Unavailable' === name) return messaging.Lp.E_CONTROL_UNAVAILABLE;
|
|
6752
|
+
if ('Forbidden' === name) return /token missing/i.test(message) ? messaging.Lp.E_TOKEN_MISSING : messaging.Lp.E_EVAL_REFUSED;
|
|
6753
|
+
if ('BadRequest' === name) return messaging.Lp.E_ARGS;
|
|
6754
|
+
if ('Unsupported' === name) return /needs a --tab id|no injectable frame|is not open/i.test(message) ? messaging.Lp.E_TARGET_NOT_FOUND : messaging.Lp.E_NOT_IMPLEMENTED;
|
|
6755
|
+
if ('EvalError' === name) return messaging.Lp.E_EVAL;
|
|
6756
|
+
if ('InspectError' === name) return messaging.Lp.E_INSPECT;
|
|
6757
|
+
if ('StorageError' === name) return messaging.Lp.E_STORAGE;
|
|
6758
|
+
return messaging.Lp.E_INTERNAL;
|
|
6683
6759
|
}
|
|
6684
|
-
function
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
if (
|
|
6760
|
+
function statusForCode(code) {
|
|
6761
|
+
if (code === messaging.Lp.E_TIMEOUT) return 'timeout';
|
|
6762
|
+
if (code === messaging.Lp.E_SESSION_NOT_FOUND || code === messaging.Lp.E_TARGET_NOT_FOUND) return 'not-found';
|
|
6763
|
+
if (code === messaging.Lp.E_CONTROL_DENIED || code === messaging.Lp.E_EVAL_REFUSED || code === messaging.Lp.E_TOKEN_MISSING) return 'denied';
|
|
6764
|
+
if (code === messaging.Lp.E_ARGS) return 'usage';
|
|
6765
|
+
return 'failed';
|
|
6766
|
+
}
|
|
6767
|
+
function buildActEnvelope(command, result) {
|
|
6768
|
+
const { ok, value, truncated, error, ...extras } = result;
|
|
6769
|
+
const wasTruncated = true === truncated;
|
|
6770
|
+
if (ok) return {
|
|
6771
|
+
...extras,
|
|
6772
|
+
...messaging.Pr.ok(command, 'ok', value ?? null, {
|
|
6773
|
+
truncated: wasTruncated
|
|
6774
|
+
})
|
|
6775
|
+
};
|
|
6776
|
+
const raw = error || {};
|
|
6777
|
+
const name = 'string' == typeof raw.name ? raw.name : 'Error';
|
|
6778
|
+
const message = 'string' == typeof raw.message ? raw.message : 'command failed';
|
|
6779
|
+
const code = codeForBridgeError(name, message);
|
|
6688
6780
|
return {
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
}
|
|
6781
|
+
...extras,
|
|
6782
|
+
...messaging.Pr.fail(command, statusForCode(code), {
|
|
6783
|
+
...raw,
|
|
6784
|
+
code,
|
|
6785
|
+
message,
|
|
6786
|
+
name
|
|
6787
|
+
}, {
|
|
6788
|
+
truncated: wasTruncated
|
|
6789
|
+
})
|
|
6696
6790
|
};
|
|
6697
6791
|
}
|
|
6698
|
-
function
|
|
6699
|
-
return 'darwin' === process.platform;
|
|
6700
|
-
}
|
|
6701
|
-
function activeDeveloperDir() {
|
|
6792
|
+
function writeFrame(frame) {
|
|
6702
6793
|
try {
|
|
6703
|
-
|
|
6704
|
-
'-p'
|
|
6705
|
-
], {
|
|
6706
|
-
encoding: 'utf8',
|
|
6707
|
-
timeout: 15000
|
|
6708
|
-
});
|
|
6709
|
-
if (0 !== result.status) return null;
|
|
6710
|
-
const resolved = String(result.stdout || '').trim();
|
|
6711
|
-
return resolved.length > 0 ? resolved : null;
|
|
6794
|
+
external_node_fs_default().writeSync(1, `${JSON.stringify(frame)}\n`);
|
|
6712
6795
|
} catch {
|
|
6713
|
-
|
|
6796
|
+
console.log(JSON.stringify(frame));
|
|
6714
6797
|
}
|
|
6715
6798
|
}
|
|
6716
|
-
function
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
});
|
|
6725
|
-
if (0 !== result.status) return null;
|
|
6726
|
-
const resolved = String(result.stdout || '').trim();
|
|
6727
|
-
return resolved.length > 0 ? resolved : null;
|
|
6728
|
-
} catch {
|
|
6729
|
-
return null;
|
|
6730
|
-
}
|
|
6799
|
+
function fail(message, frame) {
|
|
6800
|
+
console.error(message);
|
|
6801
|
+
if (frame && 'json' === frame.output) writeFrame(messaging.Pr.fail(frame.command, statusForCode(frame.code), {
|
|
6802
|
+
code: frame.code,
|
|
6803
|
+
message,
|
|
6804
|
+
name: 'CliError'
|
|
6805
|
+
}));
|
|
6806
|
+
process.exit(1);
|
|
6731
6807
|
}
|
|
6732
|
-
function
|
|
6733
|
-
|
|
6734
|
-
if (
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
const needsFullXcode = !developerDir || /CommandLineTools/i.test(developerDir);
|
|
6744
|
-
const converter = findWithXcrun('safari-web-extension-converter');
|
|
6745
|
-
const xcodebuild = findWithXcrun('xcodebuild');
|
|
6746
|
-
return {
|
|
6747
|
-
platformOk,
|
|
6748
|
-
developerDir,
|
|
6749
|
-
needsFullXcode,
|
|
6750
|
-
converter,
|
|
6751
|
-
xcodebuild,
|
|
6752
|
-
ok: Boolean(converter && xcodebuild)
|
|
6808
|
+
function printResult(result, output, command) {
|
|
6809
|
+
if ('json' === output) return void console.log(JSON.stringify(buildActEnvelope(command, result)));
|
|
6810
|
+
if (result.ok) {
|
|
6811
|
+
const value = result.value;
|
|
6812
|
+
console.log('string' == typeof value ? value : JSON.stringify(value, null, 2));
|
|
6813
|
+
if (result.truncated) console.error('… result truncated (byte cap)');
|
|
6814
|
+
return;
|
|
6815
|
+
}
|
|
6816
|
+
const err = result.error || {
|
|
6817
|
+
name: 'Error',
|
|
6818
|
+
message: 'command failed'
|
|
6753
6819
|
};
|
|
6820
|
+
console.error(`${err.name}: ${err.message}${err.engine ? ` (engine: ${err.engine})` : ''}`);
|
|
6754
6821
|
}
|
|
6755
|
-
function
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6822
|
+
async function runCommand(input) {
|
|
6823
|
+
const projectPath = external_node_path_default().resolve(input.projectPathArg || process.cwd());
|
|
6824
|
+
const browser = input.opts.browser || 'chromium';
|
|
6825
|
+
const { BridgeController, readReadyContract, readControlToken } = await loadExtensionDevelopBridgeModule();
|
|
6826
|
+
const outputFrame = {
|
|
6827
|
+
command: input.command,
|
|
6828
|
+
output: input.opts.output
|
|
6761
6829
|
};
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
function delay(ms) {
|
|
6767
|
-
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
6768
|
-
}
|
|
6769
|
-
const TOOL_TAIL_LINES = 50;
|
|
6770
|
-
const TOOL_TAIL_BYTES = 8192;
|
|
6771
|
-
function toolOutputTail(output) {
|
|
6772
|
-
const lines = output.slice(4 * -TOOL_TAIL_BYTES).split(/\r?\n/).filter((line)=>line.trim().length > 0);
|
|
6773
|
-
const tail = lines.slice(-TOOL_TAIL_LINES).join('\n');
|
|
6774
|
-
return tail.length > TOOL_TAIL_BYTES ? tail.slice(-TOOL_TAIL_BYTES) : tail;
|
|
6775
|
-
}
|
|
6776
|
-
function runTool(bin, args, opts) {
|
|
6777
|
-
const streamOutput = (0, messaging._o)() && !opts?.quiet;
|
|
6778
|
-
return new Promise((resolve)=>{
|
|
6779
|
-
let output = '';
|
|
6780
|
-
const child = (0, external_node_child_process_.spawn)(bin, args, {
|
|
6781
|
-
stdio: [
|
|
6782
|
-
'ignore',
|
|
6783
|
-
'pipe',
|
|
6784
|
-
'pipe'
|
|
6785
|
-
]
|
|
6786
|
-
});
|
|
6787
|
-
const onChunk = (chunk)=>{
|
|
6788
|
-
const text = String(chunk);
|
|
6789
|
-
output += text;
|
|
6790
|
-
if (output.length > 8 * TOOL_TAIL_BYTES) output = output.slice(4 * -TOOL_TAIL_BYTES);
|
|
6791
|
-
if (streamOutput) process.stdout.write(text);
|
|
6792
|
-
};
|
|
6793
|
-
child.stdout?.on('data', onChunk);
|
|
6794
|
-
child.stderr?.on('data', onChunk);
|
|
6795
|
-
child.on('error', (error)=>resolve({
|
|
6796
|
-
ok: false,
|
|
6797
|
-
code: null,
|
|
6798
|
-
output: `${output}${String(error)}`
|
|
6799
|
-
}));
|
|
6800
|
-
child.on('close', (code)=>resolve({
|
|
6801
|
-
ok: 0 === code,
|
|
6802
|
-
code,
|
|
6803
|
-
output
|
|
6804
|
-
}));
|
|
6830
|
+
const ready = readReadyContract(projectPath, browser);
|
|
6831
|
+
if (!ready) fail(`No active control channel found for ${browser}. Run \`extension dev --browser=${browser} --allow-control\` first.`, {
|
|
6832
|
+
...outputFrame,
|
|
6833
|
+
code: messaging.Lp.E_SESSION_NOT_FOUND
|
|
6805
6834
|
});
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6835
|
+
const token = input.needsToken ? readControlToken(projectPath, browser) : void 0;
|
|
6836
|
+
const controller = new BridgeController({
|
|
6837
|
+
controlPort: ready.controlPort,
|
|
6838
|
+
instanceId: ready.instanceId,
|
|
6839
|
+
token: token ?? void 0
|
|
6840
|
+
});
|
|
6841
|
+
try {
|
|
6842
|
+
await controller.connect();
|
|
6843
|
+
} catch (err) {
|
|
6844
|
+
controller.close();
|
|
6845
|
+
const message = err?.message || 'could not connect to the control channel';
|
|
6846
|
+
fail(message, {
|
|
6847
|
+
...outputFrame,
|
|
6848
|
+
code: /code 40\d\d/.test(message) ? messaging.Lp.E_CONTROL_DENIED : messaging.Lp.E_CONTROL_UNAVAILABLE
|
|
6817
6849
|
});
|
|
6818
|
-
if (ok && output.includes(needle)) return true;
|
|
6819
|
-
await delay(800);
|
|
6820
6850
|
}
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6851
|
+
const timeoutMs = input.opts.timeout ? Number(input.opts.timeout) : 5000;
|
|
6852
|
+
let result;
|
|
6853
|
+
try {
|
|
6854
|
+
result = await controller.command({
|
|
6855
|
+
op: input.op,
|
|
6856
|
+
target: input.target,
|
|
6857
|
+
args: input.args,
|
|
6858
|
+
timeoutMs
|
|
6859
|
+
});
|
|
6860
|
+
} catch (err) {
|
|
6861
|
+
controller.close();
|
|
6862
|
+
const message = err?.message || 'command failed';
|
|
6863
|
+
fail(message, {
|
|
6864
|
+
...outputFrame,
|
|
6865
|
+
code: /timed out/i.test(message) ? messaging.Lp.E_TIMEOUT : messaging.Lp.E_CONTROL_UNAVAILABLE
|
|
6866
|
+
});
|
|
6867
|
+
} finally{
|
|
6868
|
+
controller.close();
|
|
6829
6869
|
}
|
|
6830
|
-
|
|
6870
|
+
if (result?.ok && input.augment) try {
|
|
6871
|
+
Object.assign(result, input.augment(projectPath, browser, result));
|
|
6872
|
+
} catch {}
|
|
6873
|
+
printResult(result, input.opts.output, input.command);
|
|
6874
|
+
await exitAfterDrain(result.ok ? 0 : 1);
|
|
6831
6875
|
}
|
|
6832
|
-
function
|
|
6833
|
-
const
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
message: messages.UW(process.platform)
|
|
6837
|
-
};
|
|
6838
|
-
if (!tc.ok) return {
|
|
6839
|
-
severity: 'fatal',
|
|
6840
|
-
message: tc.needsFullXcode ? messages.Xi(tc.developerDir) : messages.Cs(tc.converter ? 'xcodebuild' : 'safari-web-extension-converter')
|
|
6841
|
-
};
|
|
6842
|
-
return {
|
|
6843
|
-
severity: 'ok'
|
|
6876
|
+
function targetFrom(opts, fallback = 'background') {
|
|
6877
|
+
const context = opts.context || fallback;
|
|
6878
|
+
const target = {
|
|
6879
|
+
context
|
|
6844
6880
|
};
|
|
6881
|
+
if (opts.url) target.url = opts.url;
|
|
6882
|
+
if (null != opts.tab && '' !== opts.tab) target.tabId = Number(opts.tab);
|
|
6883
|
+
return target;
|
|
6845
6884
|
}
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
}
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
} else logger.info?.(messages.oM());
|
|
6888
|
-
if ('full' === mode) logger.info?.(messages.jR(macOsSchemeName(config)));
|
|
6889
|
-
const built = await runTool('xcodebuild', xcodebuildArgs);
|
|
6890
|
-
if (!built.ok) {
|
|
6891
|
-
const tail = toolOutputTail(built.output);
|
|
6892
|
-
logger.error?.(messages.A('xcodebuild', built.code, tail));
|
|
6893
|
-
throw new Error(`xcodebuild failed (exit ${built.code})\n${tail}`);
|
|
6894
|
-
}
|
|
6895
|
-
const appPath = builtAppPath(config);
|
|
6896
|
-
if ('resync' === mode) return void logger.info?.(messages.cF(config.appName));
|
|
6897
|
-
logger.info?.(messages.Rl(appPath));
|
|
6898
|
-
if (config.bundleIdDerived) logger.info?.(messages.$q(config.bundleIdentifier));
|
|
6899
|
-
if (!config.open) return void logger.info?.(messages.aO(appPath, config.appName));
|
|
6900
|
-
const target = external_node_fs_.existsSync(appPath) ? appPath : xcodeProjectPath(config);
|
|
6901
|
-
logger.info?.(messages.fw(target));
|
|
6902
|
-
await runTool('open', [
|
|
6903
|
-
target
|
|
6904
|
-
]);
|
|
6905
|
-
if (config.safariBinary) await runTool('open', [
|
|
6906
|
-
'-a',
|
|
6907
|
-
config.safariBinary
|
|
6908
|
-
]);
|
|
6909
|
-
logger.info?.(messages.fO(config.appName));
|
|
6910
|
-
if (await confirmRegisteredWithSafari(config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
|
|
6911
|
-
else logger.warn?.(messages.qY(config.appName));
|
|
6912
|
-
}
|
|
6913
|
-
async function packageSafariExtension(host, outputPath, logger, mode = 'full') {
|
|
6914
|
-
const compilation = {
|
|
6915
|
-
options: {
|
|
6916
|
-
output: {
|
|
6917
|
-
path: outputPath
|
|
6885
|
+
const commonOptions = (cmd)=>cmd.option('--browser <chrome | chromium | edge | firefox>', 'which session to target (default chromium)').option('--timeout <ms>', 'command timeout in milliseconds (default 5000)').option('--output <pretty|json>', 'output format (default pretty)');
|
|
6886
|
+
function registerActCommands(program) {
|
|
6887
|
+
commonOptions(program.command('eval').arguments('<expression> [project-path]').description(commandDescriptions.eval).option('--context <background|popup|options|sidebar|devtools|newtab|history|bookmarks|content|page>', 'target context (default background). Extension pages (popup/options/sidebar/devtools/newtab/history/bookmarks) answer via their own in-page relay and must be open').option('--url <glob|substring>', 'for content/page: document to target (resolved to its tab)').option('--tab <id>', 'for content/page: a specific tab (default: the --url match, else the active tab)')).action(async (expression, projectPathArg, opts)=>{
|
|
6888
|
+
await runCommand({
|
|
6889
|
+
projectPathArg,
|
|
6890
|
+
command: 'eval',
|
|
6891
|
+
op: 'eval',
|
|
6892
|
+
target: targetFrom(opts),
|
|
6893
|
+
args: {
|
|
6894
|
+
expression
|
|
6895
|
+
},
|
|
6896
|
+
needsToken: true,
|
|
6897
|
+
opts
|
|
6898
|
+
});
|
|
6899
|
+
});
|
|
6900
|
+
commonOptions(program.command('storage').arguments('<action> [project-path]').description(commandDescriptions.storage).option('--area <local|sync|session|managed>', 'storage area (default local)').option('--key <key>', 'key to get or set').option('--value <json>', 'JSON value to set (with set)').option('--context <background|popup|options|sidebar|content>', 'target context (default background)')).action(async (action, projectPathArg, opts)=>{
|
|
6901
|
+
const area = opts.area || 'local';
|
|
6902
|
+
if ('get' === action) return void await runCommand({
|
|
6903
|
+
projectPathArg,
|
|
6904
|
+
command: 'storage',
|
|
6905
|
+
op: 'storage.get',
|
|
6906
|
+
target: targetFrom(opts),
|
|
6907
|
+
args: opts.key ? {
|
|
6908
|
+
area,
|
|
6909
|
+
key: opts.key
|
|
6910
|
+
} : {
|
|
6911
|
+
area
|
|
6912
|
+
},
|
|
6913
|
+
opts
|
|
6914
|
+
});
|
|
6915
|
+
if ('set' === action) {
|
|
6916
|
+
if (!opts.key || null == opts.value) fail('storage set requires --key and --value', {
|
|
6917
|
+
command: 'storage',
|
|
6918
|
+
code: messaging.Lp.E_ARGS,
|
|
6919
|
+
output: opts.output
|
|
6920
|
+
});
|
|
6921
|
+
let parsed;
|
|
6922
|
+
try {
|
|
6923
|
+
parsed = JSON.parse(opts.value);
|
|
6924
|
+
} catch {
|
|
6925
|
+
parsed = opts.value;
|
|
6918
6926
|
}
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6927
|
+
await runCommand({
|
|
6928
|
+
projectPathArg,
|
|
6929
|
+
command: 'storage',
|
|
6930
|
+
op: 'storage.set',
|
|
6931
|
+
target: targetFrom(opts),
|
|
6932
|
+
args: {
|
|
6933
|
+
area,
|
|
6934
|
+
items: {
|
|
6935
|
+
[opts.key]: parsed
|
|
6936
|
+
}
|
|
6937
|
+
},
|
|
6938
|
+
opts
|
|
6939
|
+
});
|
|
6940
|
+
return;
|
|
6922
6941
|
}
|
|
6923
|
-
|
|
6924
|
-
|
|
6942
|
+
fail(`unknown storage action: ${action} (use get or set)`, {
|
|
6943
|
+
command: 'storage',
|
|
6944
|
+
code: messaging.Lp.E_ARGS,
|
|
6945
|
+
output: opts.output
|
|
6946
|
+
});
|
|
6947
|
+
});
|
|
6948
|
+
commonOptions(program.command('reload').arguments('[project-path]').description(commandDescriptions.reload).option('--context <background|content|page>', 'target context (default background)').option('--tab <id>', 'for content/page: a specific tab')).action(async (projectPathArg, opts)=>{
|
|
6949
|
+
await runCommand({
|
|
6950
|
+
projectPathArg,
|
|
6951
|
+
command: 'reload',
|
|
6952
|
+
op: 'reload',
|
|
6953
|
+
target: targetFrom(opts),
|
|
6954
|
+
opts
|
|
6955
|
+
});
|
|
6956
|
+
});
|
|
6957
|
+
commonOptions(program.command('inspect').arguments('[project-path]').description(commandDescriptions.inspect).option('--context <content|page|popup|options|sidebar|devtools|newtab|history|bookmarks>', 'what to inspect: content/page or an open surface, including url-override pages (default content)').option('--url <glob|substring>', 'for content/page: document to target (resolved to its tab)').option('--tab <id>', 'for content/page: a specific tab (default: the --url match, else the active tab)').option('--list-tabs', 'list open tabs as {tabId,url,title} and exit').option('--include <list>', 'comma-separated: html,summary (default summary)').option('--max-bytes <n>', 'cap on returned HTML bytes (default 262144)').option('--with-console [n]', 'also include the last n console lines for the target (default 20)')).action(async (projectPathArg, opts)=>{
|
|
6958
|
+
if (opts.listTabs) return void await runCommand({
|
|
6959
|
+
projectPathArg,
|
|
6960
|
+
command: 'inspect',
|
|
6961
|
+
op: 'tabs.query',
|
|
6962
|
+
target: {
|
|
6963
|
+
context: 'background'
|
|
6964
|
+
},
|
|
6965
|
+
args: {},
|
|
6966
|
+
opts
|
|
6967
|
+
});
|
|
6968
|
+
const include = opts.include ? opts.include.split(',').map((s)=>s.trim()).filter(Boolean) : [
|
|
6969
|
+
'summary'
|
|
6970
|
+
];
|
|
6971
|
+
const target = targetFrom(opts, 'content');
|
|
6972
|
+
await runCommand({
|
|
6973
|
+
projectPathArg,
|
|
6974
|
+
command: 'inspect',
|
|
6975
|
+
op: 'inspect',
|
|
6976
|
+
target,
|
|
6977
|
+
args: {
|
|
6978
|
+
include,
|
|
6979
|
+
maxBytes: opts.maxBytes ? Number(opts.maxBytes) : void 0
|
|
6980
|
+
},
|
|
6981
|
+
opts,
|
|
6982
|
+
augment: opts.withConsole ? (projectPath, browser)=>{
|
|
6983
|
+
const n = 'string' == typeof opts.withConsole && '' !== opts.withConsole ? Number(opts.withConsole) : 20;
|
|
6984
|
+
return {
|
|
6985
|
+
console: readRecentConsole(projectPath, browser, target, Number.isFinite(n) && n > 0 ? n : 20)
|
|
6986
|
+
};
|
|
6987
|
+
} : void 0
|
|
6988
|
+
});
|
|
6989
|
+
});
|
|
6990
|
+
commonOptions(program.command('open').arguments('<surface> [project-path]').description('Open an extension surface: popup, options, sidebar, action, or command (requires --allow-control)').option('--name <command>', 'with `open command`: the chrome.commands name to trigger')).action(async (surface, projectPathArg, opts)=>{
|
|
6991
|
+
const allowed = [
|
|
6992
|
+
'popup',
|
|
6993
|
+
'options',
|
|
6994
|
+
'sidebar',
|
|
6995
|
+
'action',
|
|
6996
|
+
'command'
|
|
6997
|
+
];
|
|
6998
|
+
if (!allowed.includes(surface)) fail(`unknown surface: ${surface} (use popup, options, sidebar, action, or command)`, {
|
|
6999
|
+
command: 'open',
|
|
7000
|
+
code: messaging.Lp.E_ARGS,
|
|
7001
|
+
output: opts.output
|
|
7002
|
+
});
|
|
7003
|
+
const inBackground = 'action' === surface || 'command' === surface;
|
|
7004
|
+
const context = inBackground ? 'background' : surface;
|
|
7005
|
+
const args = {
|
|
7006
|
+
surface
|
|
7007
|
+
};
|
|
7008
|
+
if ('command' === surface && opts.name) args.name = opts.name;
|
|
7009
|
+
await runCommand({
|
|
7010
|
+
projectPathArg,
|
|
7011
|
+
command: 'open',
|
|
7012
|
+
op: 'open',
|
|
7013
|
+
target: {
|
|
7014
|
+
context
|
|
7015
|
+
},
|
|
7016
|
+
args,
|
|
7017
|
+
opts
|
|
7018
|
+
});
|
|
7019
|
+
});
|
|
6925
7020
|
}
|
|
7021
|
+
var safari_launch = __webpack_require__("./browsers/run-safari/safari-launch/index.ts");
|
|
7022
|
+
var safari_config = __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
|
|
7023
|
+
var safari_packager = __webpack_require__("./browsers/run-safari/safari-packager.ts");
|
|
6926
7024
|
function parseLogContexts(raw) {
|
|
6927
7025
|
if (!raw || 0 === String(raw).trim().length) return;
|
|
6928
7026
|
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
@@ -6995,7 +7093,7 @@ Cross-Browser Compatibility
|
|
|
6995
7093
|
return true;
|
|
6996
7094
|
}
|
|
6997
7095
|
function registerBuildCommand(program) {
|
|
6998
|
-
program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | safari | webkit-based>', 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', parseOptionalBoolean).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser = 'chromium', ...buildOptions })=>{
|
|
7096
|
+
program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | safari | webkit-based>', 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', parseOptionalBoolean).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser = 'chromium', ...buildOptions })=>{
|
|
6999
7097
|
if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
|
|
7000
7098
|
process.env.EXTENSION_DEBUG = '1';
|
|
7001
7099
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
@@ -7032,18 +7130,19 @@ Cross-Browser Compatibility
|
|
|
7032
7130
|
'--force-regenerate',
|
|
7033
7131
|
buildOptions.forceRegenerate
|
|
7034
7132
|
]
|
|
7035
|
-
].filter(([, value])=>void 0 !== value && false !== value);
|
|
7133
|
+
].filter(([, value])=>void 0 !== value && false !== value).map(([flag])=>flag);
|
|
7134
|
+
if (void 0 !== buildOptions.macosOnly) safariOnlyFlags.push('--macos-only');
|
|
7036
7135
|
if (safariOnlyFlags.length > 0 && !list.some(isSafariVendor)) {
|
|
7037
|
-
console.error(safariOnlyOption(safariOnlyFlags
|
|
7136
|
+
console.error(safariOnlyOption(safariOnlyFlags));
|
|
7038
7137
|
process.exit(1);
|
|
7039
7138
|
}
|
|
7040
|
-
if (buildOptions.bundleId && !
|
|
7139
|
+
if (buildOptions.bundleId && !(0, safari_config.OA)(buildOptions.bundleId)) {
|
|
7041
7140
|
console.error(safariInvalidBundleId(buildOptions.bundleId));
|
|
7042
7141
|
process.exit(1);
|
|
7043
7142
|
}
|
|
7044
7143
|
let safariPackagingEnabled = true;
|
|
7045
7144
|
if (list.some(isSafariVendor)) {
|
|
7046
|
-
const preflight =
|
|
7145
|
+
const preflight = (0, safari_launch.QW)();
|
|
7047
7146
|
if ('fatal' === preflight.severity) {
|
|
7048
7147
|
console.error(preflight.message);
|
|
7049
7148
|
process.exit(1);
|
|
@@ -7057,8 +7156,9 @@ Cross-Browser Compatibility
|
|
|
7057
7156
|
const asJson = 'json' === buildOptions.output;
|
|
7058
7157
|
if (asJson) process.env.EXTENSION_OUTPUT = 'json';
|
|
7059
7158
|
const built = [];
|
|
7159
|
+
const summaries = [];
|
|
7060
7160
|
for (const vendor of list)try {
|
|
7061
|
-
await extensionBuild(pathOrRemoteUrl, {
|
|
7161
|
+
const summary = await extensionBuild(pathOrRemoteUrl, {
|
|
7062
7162
|
browser: vendor,
|
|
7063
7163
|
exitOnError: !asJson,
|
|
7064
7164
|
polyfill: buildOptions.polyfill,
|
|
@@ -7071,20 +7171,15 @@ Cross-Browser Compatibility
|
|
|
7071
7171
|
mode,
|
|
7072
7172
|
appName: buildOptions.appName,
|
|
7073
7173
|
bundleId: buildOptions.bundleId,
|
|
7174
|
+
macOsOnly: buildOptions.macosOnly,
|
|
7074
7175
|
forceRegenerate: buildOptions.forceRegenerate,
|
|
7075
|
-
safariPackager: safariPackagingEnabled ?
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
],
|
|
7080
|
-
browser: vendor,
|
|
7081
|
-
noOpen: true !== buildOptions.open,
|
|
7082
|
-
dryRun: false,
|
|
7083
|
-
...overrides
|
|
7084
|
-
}, distPath, void 0, packagerMode);
|
|
7085
|
-
} : void 0
|
|
7176
|
+
safariPackager: safariPackagingEnabled ? (0, safari_packager.P)({
|
|
7177
|
+
browser: vendor,
|
|
7178
|
+
noOpen: true !== buildOptions.open
|
|
7179
|
+
}) : void 0
|
|
7086
7180
|
});
|
|
7087
7181
|
built.push(vendor);
|
|
7182
|
+
if (summary) summaries.push(summary);
|
|
7088
7183
|
} catch (error) {
|
|
7089
7184
|
if (!asJson) throw error;
|
|
7090
7185
|
console.log(JSON.stringify(messaging.Pr.fail('build', 'build-failed', {
|
|
@@ -7098,7 +7193,8 @@ Cross-Browser Compatibility
|
|
|
7098
7193
|
if (asJson) console.log(JSON.stringify(messaging.Pr.ok('build', 'built', {
|
|
7099
7194
|
projectPath: pathOrRemoteUrl,
|
|
7100
7195
|
browsers: built,
|
|
7101
|
-
mode
|
|
7196
|
+
mode,
|
|
7197
|
+
summaries
|
|
7102
7198
|
})));
|
|
7103
7199
|
});
|
|
7104
7200
|
}
|
|
@@ -7413,7 +7509,7 @@ Cross-Browser Compatibility
|
|
|
7413
7509
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
|
|
7414
7510
|
}
|
|
7415
7511
|
function registerDevCommand(program) {
|
|
7416
|
-
program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --no-reload emit a dev-mode dist without the content-script reload runtime; tabs need manual reload to see changes\n --wait wait for ready contract and exit; pair with --output json for machine output\n").option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('-b, --browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | safari | webkit-based>', 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only; no live reload)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', 'do not open the browser automatically (default: open)').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (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, { browser = 'chromium', ...devOptions })=>{
|
|
7512
|
+
program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser do not launch the browser (dev server still starts)\n --no-reload emit a dev-mode dist without the content-script reload runtime; tabs need manual reload to see changes\n --wait wait for ready contract and exit; pair with --output json for machine output\n").option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('-b, --browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based | safari | webkit-based>', 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only; no live reload)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', parseOptionalBoolean).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`', parseOptionalBoolean).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', 'do not open the browser automatically (default: open)').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', parseOptionalBoolean).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (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, { browser = 'chromium', ...devOptions })=>{
|
|
7417
7513
|
if (devOptions.debug || devOptions.author || devOptions.authorMode) {
|
|
7418
7514
|
process.env.EXTENSION_DEBUG = '1';
|
|
7419
7515
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
@@ -7460,16 +7556,16 @@ Cross-Browser Compatibility
|
|
|
7460
7556
|
'--force-regenerate',
|
|
7461
7557
|
opts.forceRegenerate
|
|
7462
7558
|
]
|
|
7463
|
-
].filter(([, value])=>void 0 !== value && false !== value);
|
|
7559
|
+
].filter(([, value])=>void 0 !== value && false !== value).map(([flag])=>flag);
|
|
7560
|
+
if (void 0 !== opts.macosOnly) safariOnlyFlags.push('--macos-only');
|
|
7464
7561
|
if (safariOnlyFlags.length > 0 && !list.some(isSafariVendor)) {
|
|
7465
|
-
|
|
7466
|
-
console.error(safariOnlyOption(flags));
|
|
7562
|
+
console.error(safariOnlyOption(safariOnlyFlags));
|
|
7467
7563
|
failAndExit(asJson, 'usage', {
|
|
7468
7564
|
code: messaging.Lp.E_INVALID_OPTION,
|
|
7469
|
-
message: `${
|
|
7565
|
+
message: `${safariOnlyFlags.join(', ')} apply to safari targets only.`
|
|
7470
7566
|
});
|
|
7471
7567
|
}
|
|
7472
|
-
if (opts.bundleId && !
|
|
7568
|
+
if (opts.bundleId && !(0, safari_config.OA)(opts.bundleId)) {
|
|
7473
7569
|
console.error(safariInvalidBundleId(opts.bundleId));
|
|
7474
7570
|
failAndExit(asJson, 'usage', {
|
|
7475
7571
|
code: messaging.Lp.E_INVALID_OPTION,
|
|
@@ -7477,7 +7573,7 @@ Cross-Browser Compatibility
|
|
|
7477
7573
|
});
|
|
7478
7574
|
}
|
|
7479
7575
|
if (list.some(isSafariVendor)) {
|
|
7480
|
-
const issue =
|
|
7576
|
+
const issue = (0, safari_launch.iF)();
|
|
7481
7577
|
if (issue) {
|
|
7482
7578
|
console.error(issue);
|
|
7483
7579
|
failAndExit(asJson, 'failed', {
|
|
@@ -7541,6 +7637,7 @@ Cross-Browser Compatibility
|
|
|
7541
7637
|
geckoBinary: devOptions.geckoBinary,
|
|
7542
7638
|
polyfill: devOptions.polyfill?.toString() !== 'false',
|
|
7543
7639
|
noOpen: false === devOptions.open,
|
|
7640
|
+
macOsOnly: opts.macosOnly,
|
|
7544
7641
|
startingUrl: devOptions.startingUrl,
|
|
7545
7642
|
install: devOptions.install,
|
|
7546
7643
|
noBrowser,
|
|
@@ -7553,17 +7650,10 @@ Cross-Browser Compatibility
|
|
|
7553
7650
|
logUrl: devOptions.logUrl,
|
|
7554
7651
|
logTab: devOptions.logTab,
|
|
7555
7652
|
launcher: noBrowser ? void 0 : browsers.launchBrowser,
|
|
7556
|
-
safariPackager:
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
],
|
|
7561
|
-
browser: vendor,
|
|
7562
|
-
noOpen: false === devOptions.open,
|
|
7563
|
-
dryRun: false,
|
|
7564
|
-
...overrides
|
|
7565
|
-
}, distPath, void 0, mode);
|
|
7566
|
-
}
|
|
7653
|
+
safariPackager: (0, safari_packager.P)({
|
|
7654
|
+
browser: vendor,
|
|
7655
|
+
noOpen: false === devOptions.open
|
|
7656
|
+
})
|
|
7567
7657
|
};
|
|
7568
7658
|
try {
|
|
7569
7659
|
await extensionDev(pathOrRemoteUrl, devArgs);
|