extension 2.1.3 → 3.0.0-next.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -10
- package/dist/cli-lib/manifest-summary.d.ts +13 -0
- package/dist/cli-lib/messages.d.ts +11 -0
- package/dist/cli-lib/telemetry-cli.d.ts +2 -0
- package/dist/cli-lib/telemetry.d.ts +22 -0
- package/dist/cli.js +767 -137
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/create.d.ts +2 -0
- package/dist/commands/dev.d.ts +2 -0
- package/dist/commands/preview.d.ts +2 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/utils.d.ts +5 -0
- package/package.json +30 -22
- package/types/index.d.ts +2 -1
- package/types/polyfill.d.ts +6 -0
- package/dist/cli.d.ts +0 -2
package/dist/cli.js
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var
|
|
4
|
-
"extension-develop": function(module) {
|
|
5
|
-
module.exports = import("extension-develop").then(function(module) {
|
|
6
|
-
return module;
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
var __webpack_module_cache__ = {};
|
|
11
|
-
function __webpack_require__(moduleId) {
|
|
12
|
-
var cachedModule = __webpack_module_cache__[moduleId];
|
|
13
|
-
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
14
|
-
var module = __webpack_module_cache__[moduleId] = {
|
|
15
|
-
exports: {}
|
|
16
|
-
};
|
|
17
|
-
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
18
|
-
return module.exports;
|
|
19
|
-
}
|
|
3
|
+
var __webpack_require__ = {};
|
|
20
4
|
(()=>{
|
|
21
5
|
__webpack_require__.n = (module)=>{
|
|
22
6
|
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
@@ -38,27 +22,29 @@ function __webpack_require__(moduleId) {
|
|
|
38
22
|
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
39
23
|
})();
|
|
40
24
|
var __webpack_exports__ = {};
|
|
41
|
-
(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
25
|
+
const external_commander_namespaceObject = require("commander");
|
|
26
|
+
var package_namespaceObject = JSON.parse('{"license":"MIT","repository":{"type":"git","url":"git+https://github.com/extension-js/extension.js.git","directory":"programs/cli"},"engines":{"node":">=18"},"exports":{".":{"types":"./dist/cli.d.ts","import":"./dist/cli.js","require":"./dist/cli.js"}},"main":"./dist/cli.js","types":"./dist/cli.d.ts","typesVersions":{"*":{"types":["./types/index.d.ts"],"types/*":["./types/*"]}},"files":["dist","types"],"bin":{"extension":"./dist/cli.js"},"name":"extension","version":"3.0.0-next.28","description":"Create cross-browser extensions with no build configuration.","homepage":"https://extension.js.org/","author":{"name":"Cezar Augusto","email":"boss@cezaraugusto.net","url":"https://cezaraugusto.com"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"scripts":{"prepare":"rslib build >/dev/null 2>&1 || true","postinstall":"rslib build >/dev/null 2>&1 || true","compile":"rslib build","watch":"rslib build --watch","test":"vitest run"},"keywords":["zero-config","build","develop","browser","extension","chrome extension","edge extension","firefox extension","safari extension","web","react","typescript","webextension","browser-extension","chrome-extension","firefox-addon","edge-extension","safari-web-extension","manifest-v3","mv3","cross-browser","content-script","background-script","devtools","create-extension","scaffold","starter-template","boilerplate","cli"],"dependencies":{"commander":"^12.1.0","extension-create":"^2.2.0","pintor":"0.3.0","semver":"^7.6.3","update-check":"^1.5.4"},"devDependencies":{"@rslib/core":"^0.6.9","@types/chrome":"^0.0.287","@types/node":"^22.10.1","@types/react":"^19.0.1","@types/react-dom":"^19.0.1","@types/webextension-polyfill":"0.12.3","@types/mock-fs":"^4.13.4","@types/semver":"^7.5.8","mock-fs":"^5.4.1","webextension-polyfill":"^0.12.0","tsconfig":"*","typescript":"5.7.2","vitest":"^3.2.4"}}');
|
|
27
|
+
const external_update_check_namespaceObject = require("update-check");
|
|
28
|
+
var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
|
|
29
|
+
const external_pintor_namespaceObject = require("pintor");
|
|
30
|
+
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
|
|
31
|
+
function getLoggingPrefix(type) {
|
|
32
|
+
if ('true' === process.env.EXTENSION_AUTHOR_MODE) return external_pintor_default().brightMagenta('error' === type ? 'ERROR' : "\u25BA\u25BA\u25BA");
|
|
33
|
+
if ('error' === type) return external_pintor_default().red('ERROR');
|
|
34
|
+
if ('warn' === type) return external_pintor_default().brightYellow("\u25BA\u25BA\u25BA");
|
|
35
|
+
if ('info' === type) return external_pintor_default().gray("\u25BA\u25BA\u25BA");
|
|
36
|
+
return external_pintor_default().green("\u25BA\u25BA\u25BA");
|
|
37
|
+
}
|
|
38
|
+
const code = (text)=>external_pintor_default().blue(text);
|
|
39
|
+
const arg = (text)=>external_pintor_default().gray(text);
|
|
40
|
+
function updateFailed(err) {
|
|
41
|
+
return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String((null == err ? void 0 : err.message) || err))}`;
|
|
42
|
+
}
|
|
43
|
+
function checkUpdates(packageJson, update) {
|
|
44
|
+
return `${getLoggingPrefix('info')} \u{1F9E9} ${external_pintor_default().blue('Extension.js')} update available.\n\nYou are currently using version ${external_pintor_default().red(String(packageJson.version))}. Latest stable is ${external_pintor_default().green(String(update.latest))}.\nPlease update to enjoy new features and improvements.`;
|
|
45
|
+
}
|
|
46
|
+
function programUserHelp() {
|
|
47
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
|
|
62
48
|
|
|
63
49
|
Usage: extension [command] [options]
|
|
64
50
|
|
|
@@ -88,52 +74,103 @@ Available Commands
|
|
|
88
74
|
Cleans up orphaned instances and frees unused ports
|
|
89
75
|
|
|
90
76
|
Common Options
|
|
91
|
-
- ${code('--browser')} ${arg('<chrome|edge|firefox>')} Target browser (default: chrome)
|
|
77
|
+
- ${code('--browser')} ${arg('<chrome|edge|firefox|chromium|chromium-based|gecko-based|firefox-based>')} Target browser/engine (default: chrome)
|
|
92
78
|
- ${code('--profile')} ${arg('<path|boolean>')} Browser profile configuration
|
|
93
79
|
- ${code('--polyfill')} ${arg('[boolean]')} Enable/disable cross-browser polyfill
|
|
80
|
+
- ${code('--no-telemetry')} Disable anonymous telemetry for this run
|
|
94
81
|
- ${code('--port')} ${arg('<number>')} Development server port (default: 8080)
|
|
95
82
|
- ${code('--starting-url')} ${arg('<url>')} Initial URL to load in browser
|
|
96
83
|
- ${code('--silent')} ${arg('[boolean]')} Suppress console output during build
|
|
97
84
|
|
|
98
85
|
Source Inspection
|
|
99
|
-
- ${code('--source')} ${arg('<url>')}
|
|
100
|
-
- ${
|
|
86
|
+
- ${code('--source')} ${arg('<url|boolean>')} Open URL and print HTML after content scripts inject
|
|
87
|
+
- When provided without a URL, falls back to ${arg('--starting-url')} or ${arg('https://example.com')}
|
|
88
|
+
- Watch mode is enabled by default when ${code('--source')} is present
|
|
101
89
|
|
|
102
90
|
Browser-Specific Options
|
|
103
91
|
- ${code('--chromium-binary')} ${arg('<path>')} Custom Chromium binary path
|
|
104
|
-
- ${code('--gecko-binary')} ${arg('<path>')} Custom Firefox/Gecko binary path
|
|
92
|
+
- ${code('--gecko-binary')}/${code('--firefox-binary')} ${arg('<path>')} Custom Firefox/Gecko binary path
|
|
105
93
|
|
|
106
94
|
Build Options
|
|
107
95
|
- ${code('--zip')} ${arg('[boolean]')} Create ZIP archive of built extension
|
|
108
96
|
- ${code('--zip-source')} ${arg('[boolean]')} Include source files in ZIP
|
|
109
97
|
- ${code('--zip-filename')} ${arg('<name>')} Custom ZIP filename
|
|
110
98
|
|
|
99
|
+
${external_pintor_default().underline('Centralized Logger (terminal output)')}
|
|
100
|
+
- The manager extension embeds a centralized logger that streams events to the CLI.
|
|
101
|
+
- Enable and filter logs directly via ${code('extension dev')} flags:
|
|
102
|
+
- ${code('--logs')} ${arg('<off|error|warn|info|debug|trace>')} Minimum level (default: info)
|
|
103
|
+
- ${code('--log-context')} ${arg('<list|all>')} Contexts: background,content,page,sidebar,popup,options,devtools
|
|
104
|
+
- ${code('--log-format')} ${arg('<pretty|json>')} Output format (default: pretty)
|
|
105
|
+
- ${code('--no-log-timestamps')} Hide ISO timestamps in pretty output
|
|
106
|
+
- ${code('--no-log-color')} Disable color in pretty output
|
|
107
|
+
- ${code('--log-url')} ${arg('<substring|/regex/>')} Filter by event.url
|
|
108
|
+
- ${code('--log-tab')} ${arg('<id>')} Filter by tabId
|
|
109
|
+
- Example: ${code('extension dev ./my-ext --logs=debug --log-context=all --log-format=pretty')}
|
|
110
|
+
|
|
111
111
|
${code('extension --help')}
|
|
112
112
|
This command outputs a help file with key command options.
|
|
113
113
|
|
|
114
|
+
${external_pintor_default().underline('Path Resolution (important)')}
|
|
115
|
+
- Leading ${code('/')} in manifest/HTML means extension root (the directory containing ${code('manifest.json')}).
|
|
116
|
+
- Relative paths resolve from the ${code('manifest.json')} directory.
|
|
117
|
+
- Absolute OS paths are used as-is.
|
|
118
|
+
|
|
119
|
+
|
|
114
120
|
AI Assistants
|
|
115
121
|
- For AI-oriented guidance and deep-dive tips, run ${code('extension --ai-help')}
|
|
116
122
|
|
|
117
123
|
Report issues
|
|
118
124
|
- ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
}
|
|
126
|
+
function unsupportedBrowserFlag(value, supported) {
|
|
127
|
+
return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}. Supported: ${supported.join(', ')}.`;
|
|
128
|
+
}
|
|
129
|
+
function programAIHelp() {
|
|
130
|
+
return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
|
|
125
131
|
|
|
126
132
|
Browser-Specific Configuration
|
|
127
133
|
- Use browser prefixes in manifest.json for browser-specific fields:
|
|
128
134
|
${code('{"firefox:manifest": 2, "chrome:manifest": 3}')}
|
|
129
135
|
This applies manifest v2 to Firefox only, v3 to Chrome/Edge.
|
|
130
136
|
|
|
137
|
+
Centralized Logger (for AI & CI)
|
|
138
|
+
- Logs from all contexts are centralized by the manager extension and streamed to the CLI.
|
|
139
|
+
- Prefer these flags to control terminal logs during ${code('extension dev')}:
|
|
140
|
+
- ${code('--logs')} ${arg('<off|error|warn|info|debug|trace>')} Minimum level
|
|
141
|
+
- ${code('--log-context')} ${arg('<list|all>')} Contexts to include
|
|
142
|
+
- ${code('--log-format')} ${arg('<pretty|json>')} Pretty for humans; JSON for machines/NDJSON pipelines
|
|
143
|
+
- ${code('--no-log-timestamps')} ${arg(' ')} Disable timestamps (pretty)
|
|
144
|
+
- ${code('--no-log-color')} ${arg(' ')} Disable ANSI colors (pretty)
|
|
145
|
+
- ${code('--log-url')} ${arg('<substring|/regex/>')} Filter by URL
|
|
146
|
+
- ${code('--log-tab')} ${arg('<id>')} Filter by tabId
|
|
147
|
+
- Good CI pattern: ${code('EXTENSION_AUTHOR_MODE=development EXTENSION_AUTO_EXIT_MS=6000 extension dev ./ext --logs=info --log-format=json')}
|
|
148
|
+
|
|
131
149
|
Special Folders for Entrypoints
|
|
132
150
|
- Use special folders to handle entrypoints and assets not declared in manifest.json:
|
|
133
151
|
- ${external_pintor_default().underline(code('public/'))} - Static assets automatically copied to build (resolves to output root)
|
|
134
152
|
- ${external_pintor_default().underline(code('pages/'))} - HTML files not declared in manifest (e.g., welcome pages)
|
|
135
153
|
- ${external_pintor_default().underline(code("scripts/"))} - JavaScript files not declared in manifest (e.g., executable scripts)
|
|
136
154
|
|
|
155
|
+
Predictable Output Paths
|
|
156
|
+
- Core HTML destinations are standardized across browsers so you can reference them safely in code/tests:
|
|
157
|
+
- ${code('devtools_page')} \u{2192} ${code('devtools/index.html')}
|
|
158
|
+
- ${code('sidebar_action.default_panel')} (MV2) and ${code('side_panel.default_path')} (MV3) \u{2192} ${code('sidebar/index.html')}
|
|
159
|
+
- ${code('options_ui.page')} and ${code('options_page')} \u{2192} ${code('options/index.html')}
|
|
160
|
+
- ${code('background.page')} \u{2192} ${code('background/index.html')}
|
|
161
|
+
- ${code('action.default_popup')}, ${code('browser_action.default_popup')}, ${code('page_action.default_popup')} \u{2192} ${code('action/index.html')}
|
|
162
|
+
- Other predictable outputs:
|
|
163
|
+
- ${code('chrome_url_overrides.*')} \u{2192} ${code('chrome_url_overrides/<key>.html')}
|
|
164
|
+
- ${code("content_scripts[n].js/css")} \u{2192} ${code("content_scripts/content-<n>.{js,css}")}
|
|
165
|
+
- ${code('sandbox.pages[]')} \u{2192} ${code('sandbox/page-<n>.html')}
|
|
166
|
+
- ${code("user_scripts.api_script")} \u{2192} ${code("user_scripts/api_script.js")}
|
|
167
|
+
- ${code('icons/*')} \u{2192} ${code('icons/')} (feature-specific icon folders preserved where applicable)
|
|
168
|
+
|
|
169
|
+
Public & Special Folders (Output Behavior)
|
|
170
|
+
- ${external_pintor_default().underline(code('public/'))} is the web root in output. Authors can use ${code('/foo')}, ${code('/public/foo')}, ${code('public/foo')}, or ${code('./public/foo')} and they all emit as ${code('dist/<browser>/foo')}.
|
|
171
|
+
- ${external_pintor_default().underline(code('pages/'))} files emit as ${code('pages/<name>.html')}. Relative assets referenced inside page HTML are emitted under ${code('assets/')} preserving relative structure; public-root URLs are preserved.
|
|
172
|
+
- ${external_pintor_default().underline(code("scripts/"))} files emit as ${code("scripts/<name>.js")} with extracted CSS when applicable.
|
|
173
|
+
|
|
137
174
|
Shadow DOM for Content Scripts
|
|
138
175
|
- Add ${code('use shadow-dom')} directive to content scripts for style isolation
|
|
139
176
|
- Automatically creates ${code('#extension-root')} element with shadow DOM
|
|
@@ -191,15 +228,16 @@ Hot Module Replacement (HMR)
|
|
|
191
228
|
- Service workers, _locales and manifest changes reload the extension
|
|
192
229
|
|
|
193
230
|
Source Inspection & Real-Time Monitoring
|
|
194
|
-
- Use ${code('--source')} ${arg('<url>')} to inspect page HTML after content script injection
|
|
195
|
-
-
|
|
231
|
+
- Use ${code('--source')} ${arg('<url|boolean>')} to inspect page HTML after content script injection
|
|
232
|
+
- When no URL is provided, falls back to ${arg('--starting-url')} or ${arg('https://example.com')}
|
|
233
|
+
- Watch mode is enabled by default when ${code('--source')} is present
|
|
196
234
|
- Automatically enables Chrome remote debugging (port 9222) when source inspection is active
|
|
197
|
-
- Extracts Shadow DOM content from ${code('#extension-root')} elements
|
|
235
|
+
- Extracts Shadow DOM content from ${code('#extension-root')} or ${code('[data-extension-root=\"true\"]')} elements
|
|
198
236
|
- Perfect for debugging content script behavior and style injection
|
|
199
|
-
- Example: ${code('extension dev --source=' + arg('https://example.com')
|
|
237
|
+
- Example: ${code('extension dev --source=' + arg('https://example.com'))}
|
|
200
238
|
|
|
201
239
|
Non-Destructive Testing in CI
|
|
202
|
-
- Prefer ${code('
|
|
240
|
+
- Prefer ${code('EXTENSION_AUTHOR_MODE=development')} to copy local templates and avoid network.
|
|
203
241
|
- Reuse Playwright's Chromium via ${code('--chromium-binary')} path when available.
|
|
204
242
|
- Set ${code(arg('EXTENSION_AUTO_EXIT_MS'))} and ${code(arg('EXTENSION_FORCE_KILL_MS'))} for non-interactive dev sessions.
|
|
205
243
|
|
|
@@ -222,123 +260,715 @@ Cross-Browser Compatibility
|
|
|
222
260
|
- Use ${code('--polyfill')} flag to enable webextension-polyfill
|
|
223
261
|
- Automatically handles browser API differences
|
|
224
262
|
- Supports Chrome, Edge, Firefox with single codebase`;
|
|
263
|
+
}
|
|
264
|
+
const external_semver_namespaceObject = require("semver");
|
|
265
|
+
function isStableVersion(version) {
|
|
266
|
+
const v = external_semver_namespaceObject.parse(version);
|
|
267
|
+
return Boolean(v && 0 === v.prerelease.length);
|
|
268
|
+
}
|
|
269
|
+
async function check_updates_checkUpdates(packageJson) {
|
|
270
|
+
let update = null;
|
|
271
|
+
try {
|
|
272
|
+
update = await external_update_check_default()(packageJson);
|
|
273
|
+
} catch (err) {
|
|
274
|
+
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(updateFailed(err));
|
|
225
275
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
276
|
+
if (update && isStableVersion(update.latest)) console.log(checkUpdates(packageJson, update));
|
|
277
|
+
}
|
|
278
|
+
const external_fs_namespaceObject = require("fs");
|
|
279
|
+
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
280
|
+
const external_path_namespaceObject = require("path");
|
|
281
|
+
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
282
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
283
|
+
var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
|
|
284
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
285
|
+
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
286
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
287
|
+
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
288
|
+
const external_node_crypto_namespaceObject = require("node:crypto");
|
|
289
|
+
var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
|
|
290
|
+
function _define_property(obj, key, value) {
|
|
291
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
292
|
+
value: value,
|
|
293
|
+
enumerable: true,
|
|
294
|
+
configurable: true,
|
|
295
|
+
writable: true
|
|
296
|
+
});
|
|
297
|
+
else obj[key] = value;
|
|
298
|
+
return obj;
|
|
299
|
+
}
|
|
300
|
+
function isCI() {
|
|
301
|
+
const v = process.env;
|
|
302
|
+
return Boolean(v.CI || v.GITHUB_ACTIONS || v.GITLAB_CI || v.BUILDKITE || v.CIRCLECI || v.TRAVIS);
|
|
303
|
+
}
|
|
304
|
+
function configDir() {
|
|
305
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
306
|
+
if (xdg) return external_node_path_default().join(xdg, 'extensionjs');
|
|
307
|
+
if ('win32' === process.platform && process.env.APPDATA) return external_node_path_default().join(process.env.APPDATA, 'extensionjs');
|
|
308
|
+
return external_node_path_default().join(external_node_os_default().homedir(), '.config', 'extensionjs');
|
|
309
|
+
}
|
|
310
|
+
function ensureDir(p) {
|
|
311
|
+
if (external_node_fs_default().existsSync(p)) return;
|
|
312
|
+
external_node_fs_default().mkdirSync(p, {
|
|
313
|
+
recursive: true
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function loadOrCreateId(file) {
|
|
317
|
+
if (external_node_fs_default().existsSync(file)) return external_node_fs_default().readFileSync(file, 'utf8').trim();
|
|
318
|
+
const id = external_node_crypto_default().randomUUID();
|
|
319
|
+
ensureDir(external_node_path_default().dirname(file));
|
|
320
|
+
external_node_fs_default().writeFileSync(file, id, 'utf8');
|
|
321
|
+
return id;
|
|
322
|
+
}
|
|
323
|
+
function auditFilePath() {
|
|
324
|
+
const dir = external_node_path_default().join(configDir(), 'telemetry');
|
|
325
|
+
ensureDir(dir);
|
|
326
|
+
return external_node_path_default().join(dir, 'events.jsonl');
|
|
327
|
+
}
|
|
328
|
+
const DEFAULT_FLUSH_AT = Number(process.env.EXTENSION_TELEMETRY_FLUSH_AT || 10);
|
|
329
|
+
const DEFAULT_FLUSH_INTERVAL = Number(process.env.EXTENSION_TELEMETRY_FLUSH_INTERVAL || 2000);
|
|
330
|
+
const DEFAULT_TIMEOUT_MS = Number(process.env.EXTENSION_TELEMETRY_TIMEOUT_MS || 200);
|
|
331
|
+
class Telemetry {
|
|
332
|
+
track(event, props = {}) {
|
|
333
|
+
if (this.disabled) return;
|
|
334
|
+
const payload = {
|
|
335
|
+
event,
|
|
336
|
+
properties: {
|
|
337
|
+
...this.common,
|
|
338
|
+
...props,
|
|
339
|
+
$ip: null
|
|
340
|
+
},
|
|
341
|
+
distinct_id: this.anonId
|
|
342
|
+
};
|
|
343
|
+
external_node_fs_default().appendFileSync(auditFilePath(), JSON.stringify(payload) + '\n');
|
|
344
|
+
if (this.debug) console.error('[telemetry]', JSON.stringify(payload));
|
|
345
|
+
if (!this.apiKey || !this.host) return;
|
|
346
|
+
this.buffer.push(payload);
|
|
347
|
+
if (this.buffer.length >= DEFAULT_FLUSH_AT) return void this.flush();
|
|
348
|
+
if (!this.timer) this.timer = setTimeout(()=>{
|
|
349
|
+
this.timer = null;
|
|
350
|
+
this.flush();
|
|
351
|
+
}, DEFAULT_FLUSH_INTERVAL);
|
|
230
352
|
}
|
|
231
|
-
async
|
|
232
|
-
|
|
353
|
+
async flush() {
|
|
354
|
+
if (this.disabled || !this.apiKey || !this.host) return;
|
|
355
|
+
if (0 === this.buffer.length) return;
|
|
356
|
+
const batch = this.buffer.splice(0, this.buffer.length);
|
|
233
357
|
try {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
358
|
+
const ac = new AbortController();
|
|
359
|
+
const t = setTimeout(()=>ac.abort(), DEFAULT_TIMEOUT_MS);
|
|
360
|
+
const url = new URL('/capture/', this.host);
|
|
361
|
+
await fetch(url.toString(), {
|
|
362
|
+
method: 'POST',
|
|
363
|
+
headers: {
|
|
364
|
+
'content-type': 'application/json'
|
|
365
|
+
},
|
|
366
|
+
body: JSON.stringify({
|
|
367
|
+
api_key: this.apiKey,
|
|
368
|
+
batch: batch.map((e)=>({
|
|
369
|
+
event: e.event,
|
|
370
|
+
properties: e.properties,
|
|
371
|
+
distinct_id: e.distinct_id
|
|
372
|
+
}))
|
|
373
|
+
}),
|
|
374
|
+
signal: ac.signal,
|
|
375
|
+
keepalive: true
|
|
376
|
+
}).catch(()=>{});
|
|
377
|
+
clearTimeout(t);
|
|
378
|
+
} catch {}
|
|
379
|
+
}
|
|
380
|
+
shutdown() {}
|
|
381
|
+
constructor(init){
|
|
382
|
+
_define_property(this, "anonId", void 0);
|
|
383
|
+
_define_property(this, "common", void 0);
|
|
384
|
+
_define_property(this, "debug", void 0);
|
|
385
|
+
_define_property(this, "disabled", void 0);
|
|
386
|
+
_define_property(this, "apiKey", void 0);
|
|
387
|
+
_define_property(this, "host", void 0);
|
|
388
|
+
_define_property(this, "buffer", []);
|
|
389
|
+
_define_property(this, "timer", null);
|
|
390
|
+
this.debug = '1' === process.env.EXTENSION_TELEMETRY_DEBUG;
|
|
391
|
+
this.disabled = Boolean(init.disabled);
|
|
392
|
+
this.anonId = 'disabled';
|
|
393
|
+
if (!this.disabled) {
|
|
394
|
+
const idFile = external_node_path_default().join(configDir(), 'telemetry', 'anonymous-id');
|
|
395
|
+
this.anonId = loadOrCreateId(idFile);
|
|
396
|
+
}
|
|
397
|
+
this.common = {
|
|
398
|
+
app: init.app,
|
|
399
|
+
version: init.version,
|
|
400
|
+
os: process.platform,
|
|
401
|
+
arch: process.arch,
|
|
402
|
+
node: process.versions.node,
|
|
403
|
+
is_ci: isCI(),
|
|
404
|
+
schema_version: 1
|
|
405
|
+
};
|
|
406
|
+
this.apiKey = init.apiKey || process.env.EXTENSION_PUBLIC_POSTHOG_KEY;
|
|
407
|
+
this.host = init.host || process.env.EXTENSION_PUBLIC_POSTHOG_HOST;
|
|
408
|
+
if (!this.disabled) {
|
|
409
|
+
const consentPath = external_node_path_default().join(configDir(), 'telemetry', 'consent');
|
|
410
|
+
if (!external_node_fs_default().existsSync(consentPath)) {
|
|
411
|
+
external_node_fs_default().writeFileSync(consentPath, 'ok', 'utf8');
|
|
412
|
+
this.track('cli_telemetry_consent', {
|
|
413
|
+
value: 'implicit_opt_in'
|
|
414
|
+
});
|
|
415
|
+
console.log('[extension] anonymous telemetry helps us improve. Pass --no-telemetry to opt out. Read more in TELEMETRY.md.');
|
|
416
|
+
}
|
|
237
417
|
}
|
|
238
|
-
if (update && isStableVersion(update.latest)) console.log(checkUpdates(packageJson, update));
|
|
239
418
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
419
|
+
}
|
|
420
|
+
function summarizeManifest(manifest) {
|
|
421
|
+
var _manifest_action;
|
|
422
|
+
const mv = (null == manifest ? void 0 : manifest.manifest_version) === 2 ? 2 : 3;
|
|
423
|
+
const permissions = Array.isArray(null == manifest ? void 0 : manifest.permissions) ? manifest.permissions : [];
|
|
424
|
+
const optionalPermissions = Array.isArray(null == manifest ? void 0 : manifest.optional_permissions) ? manifest.optional_permissions : [];
|
|
425
|
+
const hostPermissions = Array.isArray(null == manifest ? void 0 : manifest.host_permissions) ? manifest.host_permissions : [];
|
|
426
|
+
const usesAllUrls = [
|
|
427
|
+
...permissions,
|
|
428
|
+
...hostPermissions
|
|
429
|
+
].includes('<all_urls>');
|
|
430
|
+
const usesDeclarativeNetRequest = permissions.includes('declarativeNetRequest') || permissions.includes('declarativeNetRequestWithHostAccess');
|
|
431
|
+
const background = null == manifest ? void 0 : manifest.background;
|
|
432
|
+
let backgroundType = 'none';
|
|
433
|
+
if (3 === mv && (null == background ? void 0 : background.service_worker)) backgroundType = 'service_worker';
|
|
434
|
+
else if (2 === mv && (Array.isArray(null == background ? void 0 : background.scripts) && background.scripts.length > 0 || (null == background ? void 0 : background.page))) backgroundType = 'event_page';
|
|
435
|
+
const contentScriptsCount = Array.isArray(null == manifest ? void 0 : manifest.content_scripts) ? manifest.content_scripts.length : 0;
|
|
436
|
+
const hasDevtoolsPage = Boolean(null == manifest ? void 0 : manifest.devtools_page);
|
|
437
|
+
const hasActionPopup = Boolean(null == manifest ? void 0 : null == (_manifest_action = manifest.action) ? void 0 : _manifest_action.default_popup);
|
|
438
|
+
return {
|
|
439
|
+
mv,
|
|
440
|
+
permissions_count: permissions.length,
|
|
441
|
+
optional_permissions_count: optionalPermissions.length,
|
|
442
|
+
host_permissions_count: hostPermissions.length,
|
|
443
|
+
uses_all_urls: usesAllUrls,
|
|
444
|
+
uses_declarative_net_request: usesDeclarativeNetRequest,
|
|
445
|
+
background_type: backgroundType,
|
|
446
|
+
content_scripts_count: contentScriptsCount,
|
|
447
|
+
has_devtools_page: hasDevtoolsPage,
|
|
448
|
+
has_action_popup: hasActionPopup
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function isTelemetryDisabledFromArgs(argv) {
|
|
452
|
+
return argv.includes('--no-telemetry');
|
|
453
|
+
}
|
|
454
|
+
const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
|
|
455
|
+
const telemetry_cli_telemetry = new Telemetry({
|
|
456
|
+
app: 'extension',
|
|
457
|
+
version: package_namespaceObject.version,
|
|
458
|
+
disabled: telemetryDisabled
|
|
459
|
+
});
|
|
460
|
+
if (!telemetryDisabled) {
|
|
461
|
+
const startedAt = Date.now();
|
|
462
|
+
const known = new Set([
|
|
463
|
+
'create',
|
|
464
|
+
'dev',
|
|
465
|
+
'start',
|
|
466
|
+
'preview',
|
|
467
|
+
'build',
|
|
468
|
+
'cleanup'
|
|
469
|
+
]);
|
|
470
|
+
const invoked = process.argv.slice(2).find((a)=>known.has(a)) || 'unknown';
|
|
471
|
+
telemetry_cli_telemetry.track('cli_boot', {
|
|
472
|
+
command_guess: invoked
|
|
473
|
+
});
|
|
474
|
+
const cwd = process.cwd();
|
|
475
|
+
const manifestPath = external_path_default().join(cwd, 'manifest.json');
|
|
476
|
+
if (external_fs_default().existsSync(manifestPath)) {
|
|
477
|
+
const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
|
|
478
|
+
const json = JSON.parse(raw);
|
|
479
|
+
const summary = summarizeManifest(json);
|
|
480
|
+
telemetry_cli_telemetry.track('manifest_summary', summary);
|
|
250
481
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
482
|
+
process.on('beforeExit', async function() {
|
|
483
|
+
telemetry_cli_telemetry.track('cli_shutdown', {
|
|
484
|
+
command_guess: invoked,
|
|
485
|
+
duration_ms: Date.now() - startedAt,
|
|
486
|
+
exit_code: process.exitCode ?? 0
|
|
487
|
+
});
|
|
488
|
+
await telemetry_cli_telemetry.flush();
|
|
489
|
+
});
|
|
490
|
+
process.on('uncaughtException', function(err) {
|
|
491
|
+
telemetry_cli_telemetry.track('cli_error', {
|
|
492
|
+
command_guess: invoked,
|
|
493
|
+
error_name: String((null == err ? void 0 : err.name) || 'Error').slice(0, 64)
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
process.on('unhandledRejection', function(reason) {
|
|
497
|
+
telemetry_cli_telemetry.track('cli_error', {
|
|
498
|
+
command_guess: invoked,
|
|
499
|
+
error_name: String((null == reason ? void 0 : reason.name) || 'PromiseRejection').slice(0, 64)
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
const external_extension_create_namespaceObject = require("extension-create");
|
|
504
|
+
const external_node_child_process_namespaceObject = require("node:child_process");
|
|
505
|
+
const external_node_url_namespaceObject = require("node:url");
|
|
506
|
+
function parseOptionalBoolean(value) {
|
|
507
|
+
if (void 0 === value) return true;
|
|
508
|
+
const normalized = String(value).trim().toLowerCase();
|
|
509
|
+
return ![
|
|
510
|
+
'false',
|
|
511
|
+
'0',
|
|
512
|
+
'no',
|
|
513
|
+
'off'
|
|
514
|
+
].includes(normalized);
|
|
515
|
+
}
|
|
516
|
+
async function requireOrDlx(moduleName, versionHint) {
|
|
517
|
+
try {
|
|
518
|
+
return await import(moduleName);
|
|
519
|
+
} catch {}
|
|
520
|
+
const spec = versionHint ? `${moduleName}@${versionHint}` : moduleName;
|
|
521
|
+
const cacheDir = external_node_path_default().join(external_node_os_default().tmpdir(), 'extensionjs-cache', spec);
|
|
522
|
+
const modulePath = external_node_path_default().join(cacheDir, 'node_modules', moduleName);
|
|
523
|
+
let prefer = String(process.env.EXTENSION_DLX || '').trim().toLowerCase();
|
|
524
|
+
const isWin = 'win32' === process.platform;
|
|
525
|
+
const npmCmd = isWin ? 'npm.cmd' : 'npm';
|
|
526
|
+
const pnpmCmd = isWin ? 'pnpm.cmd' : 'pnpm';
|
|
527
|
+
const bunCmd = isWin ? 'bun.exe' : 'bun';
|
|
528
|
+
if (!prefer) try {
|
|
529
|
+
const pnpmCheck = (0, external_node_child_process_namespaceObject.spawnSync)(pnpmCmd, [
|
|
530
|
+
'--version'
|
|
531
|
+
], {
|
|
532
|
+
stdio: 'ignore'
|
|
533
|
+
});
|
|
534
|
+
if (0 === (pnpmCheck.status || 0)) prefer = 'pnpm';
|
|
535
|
+
} catch {}
|
|
536
|
+
try {
|
|
537
|
+
external_node_fs_default().mkdirSync(cacheDir, {
|
|
538
|
+
recursive: true
|
|
539
|
+
});
|
|
540
|
+
} catch {}
|
|
541
|
+
try {
|
|
542
|
+
var _pkgJson_exports_, _pkgJson_exports, _pkgJson_exports_1, _pkgJson_exports1;
|
|
543
|
+
const pkgJson = JSON.parse(external_node_fs_default().readFileSync(external_node_path_default().join(modulePath, 'package.json'), 'utf8'));
|
|
544
|
+
const main = pkgJson.main || (null == (_pkgJson_exports = pkgJson.exports) ? void 0 : null == (_pkgJson_exports_ = _pkgJson_exports['.']) ? void 0 : _pkgJson_exports_.import) || (null == (_pkgJson_exports1 = pkgJson.exports) ? void 0 : null == (_pkgJson_exports_1 = _pkgJson_exports1['.']) ? void 0 : _pkgJson_exports_1.require);
|
|
545
|
+
if (main) {
|
|
546
|
+
const resolved = (0, external_node_url_namespaceObject.pathToFileURL)(external_node_path_default().join(modulePath, main)).href;
|
|
547
|
+
return await import(resolved);
|
|
548
|
+
}
|
|
549
|
+
} catch {}
|
|
550
|
+
if ('pnpm' === prefer) try {
|
|
551
|
+
external_node_fs_default().writeFileSync(external_node_path_default().join(cacheDir, 'package.json'), JSON.stringify({
|
|
552
|
+
name: 'extensionjs-cache',
|
|
553
|
+
private: true
|
|
554
|
+
}, null, 2));
|
|
555
|
+
} catch {}
|
|
556
|
+
let status = 0;
|
|
557
|
+
if ('pnpm' === prefer) {
|
|
558
|
+
const args = [
|
|
559
|
+
'add',
|
|
560
|
+
spec,
|
|
561
|
+
'--reporter',
|
|
562
|
+
'silent',
|
|
563
|
+
'--no-frozen-lockfile'
|
|
259
564
|
];
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
565
|
+
status = (0, external_node_child_process_namespaceObject.spawnSync)(pnpmCmd, args, {
|
|
566
|
+
cwd: cacheDir,
|
|
567
|
+
stdio: 'ignore'
|
|
568
|
+
}).status || 0;
|
|
569
|
+
} else if ('bun' === prefer) {
|
|
570
|
+
const args = [
|
|
571
|
+
'add',
|
|
572
|
+
spec
|
|
573
|
+
];
|
|
574
|
+
status = (0, external_node_child_process_namespaceObject.spawnSync)(bunCmd, args, {
|
|
575
|
+
cwd: cacheDir,
|
|
576
|
+
stdio: 'ignore'
|
|
577
|
+
}).status || 0;
|
|
578
|
+
} else {
|
|
579
|
+
const args = [
|
|
580
|
+
'i',
|
|
581
|
+
spec,
|
|
582
|
+
'--no-fund',
|
|
583
|
+
'--no-audit',
|
|
584
|
+
'--prefer-online',
|
|
585
|
+
'--omit=dev',
|
|
586
|
+
'--omit=optional',
|
|
587
|
+
'--no-package-lock'
|
|
588
|
+
];
|
|
589
|
+
status = (0, external_node_child_process_namespaceObject.spawnSync)(npmCmd, args, {
|
|
590
|
+
cwd: cacheDir,
|
|
591
|
+
stdio: 'ignore'
|
|
592
|
+
}).status || 0;
|
|
593
|
+
}
|
|
594
|
+
if (0 !== status) throw new Error(`Failed to install ${spec}`);
|
|
595
|
+
try {
|
|
596
|
+
var _pkgJson_exports_2, _pkgJson_exports2, _pkgJson_exports_3, _pkgJson_exports3;
|
|
597
|
+
const pkgJson = JSON.parse(external_node_fs_default().readFileSync(external_node_path_default().join(modulePath, 'package.json'), 'utf8'));
|
|
598
|
+
const main = pkgJson.main || (null == (_pkgJson_exports2 = pkgJson.exports) ? void 0 : null == (_pkgJson_exports_2 = _pkgJson_exports2['.']) ? void 0 : _pkgJson_exports_2.import) || (null == (_pkgJson_exports3 = pkgJson.exports) ? void 0 : null == (_pkgJson_exports_3 = _pkgJson_exports3['.']) ? void 0 : _pkgJson_exports_3.require);
|
|
599
|
+
if (main) {
|
|
600
|
+
const resolved = (0, external_node_url_namespaceObject.pathToFileURL)(external_node_path_default().join(modulePath, main)).href;
|
|
601
|
+
return await import(resolved);
|
|
263
602
|
}
|
|
603
|
+
} catch {}
|
|
604
|
+
return await import((0, external_node_url_namespaceObject.pathToFileURL)(external_node_path_default().join(modulePath, 'dist', 'module.js')).href);
|
|
605
|
+
}
|
|
606
|
+
const vendors = (browser)=>{
|
|
607
|
+
const value = browser ?? 'chromium';
|
|
608
|
+
return 'all' === value ? [
|
|
609
|
+
'chrome',
|
|
610
|
+
'edge',
|
|
611
|
+
'firefox'
|
|
612
|
+
] : String(value).split(',');
|
|
613
|
+
};
|
|
614
|
+
function validateVendorsOrExit(vendorsList, onInvalid) {
|
|
615
|
+
const supported = [
|
|
616
|
+
'chrome',
|
|
617
|
+
'edge',
|
|
618
|
+
'firefox',
|
|
619
|
+
'chromium',
|
|
620
|
+
'chromium-based',
|
|
621
|
+
'gecko-based',
|
|
622
|
+
'firefox-based'
|
|
623
|
+
];
|
|
624
|
+
for (const v of vendorsList)if (!supported.includes(v)) {
|
|
625
|
+
onInvalid(v, supported);
|
|
626
|
+
process.exit(1);
|
|
264
627
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
628
|
+
}
|
|
629
|
+
function registerCreateCommand(program, telemetry) {
|
|
630
|
+
program.command('create').arguments('<project-name|project-path>').usage('create <project-name|project-path> [options]').description('Creates a new extension.').option('-t, --template <template-name>', 'specify a template for the created project').option('--install [boolean]', 'whether or not to install the dependencies after creating the project (disabled by default)', parseOptionalBoolean, false).action(async function(pathOrRemoteUrl, { template, install }) {
|
|
631
|
+
const startedAt = Date.now();
|
|
632
|
+
telemetry.track('cli_command_start', {
|
|
633
|
+
command: 'create',
|
|
634
|
+
template: template || 'default',
|
|
635
|
+
install: Boolean(install)
|
|
271
636
|
});
|
|
637
|
+
try {
|
|
638
|
+
await (0, external_extension_create_namespaceObject.extensionCreate)(pathOrRemoteUrl, {
|
|
639
|
+
template,
|
|
640
|
+
install,
|
|
641
|
+
cliVersion: package_namespaceObject.version
|
|
642
|
+
});
|
|
643
|
+
telemetry.track('cli_command_finish', {
|
|
644
|
+
command: 'create',
|
|
645
|
+
duration_ms: Date.now() - startedAt,
|
|
646
|
+
success: true,
|
|
647
|
+
exit_code: 0
|
|
648
|
+
});
|
|
649
|
+
} catch (err) {
|
|
650
|
+
telemetry.track('cli_command_finish', {
|
|
651
|
+
command: 'create',
|
|
652
|
+
duration_ms: Date.now() - startedAt,
|
|
653
|
+
success: false,
|
|
654
|
+
exit_code: 1
|
|
655
|
+
});
|
|
656
|
+
throw err;
|
|
657
|
+
}
|
|
272
658
|
});
|
|
273
|
-
|
|
659
|
+
}
|
|
660
|
+
function registerDevCommand(program, telemetry) {
|
|
661
|
+
program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description('Starts the development server (development mode)').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').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('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').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('--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>', '[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('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
|
|
662
|
+
var _devOptions_polyfill;
|
|
663
|
+
if (devOptions.author || devOptions['authorMode']) {
|
|
664
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
665
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
666
|
+
}
|
|
667
|
+
const cmdStart = Date.now();
|
|
668
|
+
telemetry.track('cli_command_start', {
|
|
669
|
+
command: 'dev',
|
|
670
|
+
vendors: vendors(browser),
|
|
671
|
+
polyfill_used: (null == (_devOptions_polyfill = devOptions.polyfill) ? void 0 : _devOptions_polyfill.toString()) !== 'false',
|
|
672
|
+
log_level: devOptions.logLevel || 'off',
|
|
673
|
+
log_format: devOptions.logFormat || 'pretty',
|
|
674
|
+
custom_binary_used: Boolean(devOptions.chromiumBinary || devOptions.geckoBinary)
|
|
675
|
+
});
|
|
274
676
|
const list = vendors(browser);
|
|
275
|
-
validateVendorsOrExit(list)
|
|
276
|
-
|
|
677
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
678
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
679
|
+
});
|
|
680
|
+
if (devOptions.source) {
|
|
681
|
+
const hasExplicitSourceString = 'string' == typeof devOptions.source && 'true' !== String(devOptions.source).trim().toLowerCase();
|
|
682
|
+
const hasStartingUrl = 'string' == typeof devOptions.startingUrl && String(devOptions.startingUrl).trim().length > 0;
|
|
683
|
+
if (!hasExplicitSourceString) devOptions.source = hasStartingUrl ? String(devOptions.startingUrl) : 'https://example.com';
|
|
684
|
+
devOptions.watchSource = true;
|
|
685
|
+
}
|
|
686
|
+
const versionExact = String(package_namespaceObject.version);
|
|
687
|
+
const major = String(package_namespaceObject.version).split('.')[0] || '2';
|
|
688
|
+
let extensionDev;
|
|
689
|
+
try {
|
|
690
|
+
({ extensionDev } = await requireOrDlx('extension-develop', versionExact));
|
|
691
|
+
} catch {
|
|
692
|
+
({ extensionDev } = await requireOrDlx('extension-develop', major));
|
|
693
|
+
}
|
|
277
694
|
for (const vendor of list){
|
|
278
|
-
var
|
|
279
|
-
|
|
695
|
+
var _devOptions_polyfill1;
|
|
696
|
+
const vendorStart = Date.now();
|
|
697
|
+
telemetry.track('cli_vendor_start', {
|
|
698
|
+
command: 'dev',
|
|
699
|
+
vendor
|
|
700
|
+
});
|
|
701
|
+
const logsOption = devOptions.logs;
|
|
702
|
+
const logContextOption = devOptions.logContext;
|
|
703
|
+
const devArgs = {
|
|
280
704
|
...devOptions,
|
|
281
705
|
profile: devOptions.profile,
|
|
282
706
|
browser: vendor,
|
|
283
707
|
chromiumBinary: devOptions.chromiumBinary,
|
|
284
708
|
geckoBinary: devOptions.geckoBinary,
|
|
285
|
-
polyfill: (null == (
|
|
709
|
+
polyfill: (null == (_devOptions_polyfill1 = devOptions.polyfill) ? void 0 : _devOptions_polyfill1.toString()) !== 'false',
|
|
286
710
|
open: devOptions.open,
|
|
287
711
|
startingUrl: devOptions.startingUrl,
|
|
288
712
|
source: devOptions.source,
|
|
289
|
-
watchSource: devOptions.watchSource
|
|
713
|
+
watchSource: devOptions.watchSource,
|
|
714
|
+
logLevel: logsOption || devOptions.logLevel || 'off',
|
|
715
|
+
logContexts: (()=>{
|
|
716
|
+
const raw = logContextOption || devOptions.logContexts;
|
|
717
|
+
if (!raw || 0 === String(raw).trim().length) return;
|
|
718
|
+
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
719
|
+
const allowed = [
|
|
720
|
+
'background',
|
|
721
|
+
'content',
|
|
722
|
+
'page',
|
|
723
|
+
'sidebar',
|
|
724
|
+
'popup',
|
|
725
|
+
'options',
|
|
726
|
+
'devtools'
|
|
727
|
+
];
|
|
728
|
+
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
729
|
+
return values.length ? values : void 0;
|
|
730
|
+
})(),
|
|
731
|
+
logFormat: devOptions.logFormat || 'pretty',
|
|
732
|
+
logTimestamps: false !== devOptions.logTimestamps,
|
|
733
|
+
logColor: false !== devOptions.logColor,
|
|
734
|
+
logUrl: devOptions.logUrl,
|
|
735
|
+
logTab: devOptions.logTab
|
|
736
|
+
};
|
|
737
|
+
await extensionDev(pathOrRemoteUrl, devArgs);
|
|
738
|
+
telemetry.track('cli_vendor_finish', {
|
|
739
|
+
command: 'dev',
|
|
740
|
+
vendor,
|
|
741
|
+
duration_ms: Date.now() - vendorStart
|
|
290
742
|
});
|
|
291
743
|
}
|
|
744
|
+
telemetry.track('cli_command_finish', {
|
|
745
|
+
command: 'dev',
|
|
746
|
+
duration_ms: Date.now() - cmdStart,
|
|
747
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
748
|
+
exit_code: process.exitCode ?? 0
|
|
749
|
+
});
|
|
292
750
|
});
|
|
293
|
-
|
|
751
|
+
}
|
|
752
|
+
function registerStartCommand(program, telemetry) {
|
|
753
|
+
program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description('Starts the development server (production mode)').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`').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('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json>', '[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('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
|
|
754
|
+
var _startOptions_polyfill;
|
|
755
|
+
if (startOptions.author || startOptions['authorMode']) {
|
|
756
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
757
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
758
|
+
}
|
|
759
|
+
const cmdStart = Date.now();
|
|
760
|
+
telemetry.track('cli_command_start', {
|
|
761
|
+
command: 'start',
|
|
762
|
+
vendors: vendors(browser),
|
|
763
|
+
polyfill_used: (null == (_startOptions_polyfill = startOptions.polyfill) ? void 0 : _startOptions_polyfill.toString()) !== 'false'
|
|
764
|
+
});
|
|
294
765
|
const list = vendors(browser);
|
|
295
|
-
validateVendorsOrExit(list)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
766
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
767
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
768
|
+
});
|
|
769
|
+
const major = String(package_namespaceObject.version).split('.')[0] || '2';
|
|
770
|
+
const { extensionStart } = await requireOrDlx('extension-develop', major);
|
|
771
|
+
for (const vendor of list){
|
|
772
|
+
const vendorStart = Date.now();
|
|
773
|
+
telemetry.track('cli_vendor_start', {
|
|
774
|
+
command: 'start',
|
|
775
|
+
vendor
|
|
776
|
+
});
|
|
777
|
+
const logsOption = startOptions.logs;
|
|
778
|
+
const logContextOption = startOptions.logContext;
|
|
779
|
+
const logContexts = (()=>{
|
|
780
|
+
const raw = logContextOption || startOptions.logContexts;
|
|
781
|
+
if (!raw || 0 === String(raw).trim().length) return;
|
|
782
|
+
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
783
|
+
const allowed = [
|
|
784
|
+
'background',
|
|
785
|
+
'content',
|
|
786
|
+
'page',
|
|
787
|
+
'sidebar',
|
|
788
|
+
'popup',
|
|
789
|
+
'options',
|
|
790
|
+
'devtools'
|
|
791
|
+
];
|
|
792
|
+
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
793
|
+
return values.length ? values : void 0;
|
|
794
|
+
})();
|
|
795
|
+
await extensionStart(pathOrRemoteUrl, {
|
|
796
|
+
mode: 'production',
|
|
797
|
+
profile: startOptions.profile,
|
|
798
|
+
browser: vendor,
|
|
799
|
+
chromiumBinary: startOptions.chromiumBinary,
|
|
800
|
+
geckoBinary: startOptions.geckoBinary,
|
|
801
|
+
startingUrl: startOptions.startingUrl,
|
|
802
|
+
port: startOptions.port,
|
|
803
|
+
source: 'string' == typeof startOptions.source ? startOptions.source : startOptions.source,
|
|
804
|
+
watchSource: startOptions.watchSource,
|
|
805
|
+
logLevel: logsOption || startOptions.logLevel || 'off',
|
|
806
|
+
logContexts,
|
|
807
|
+
logFormat: startOptions.logFormat || 'pretty',
|
|
808
|
+
logTimestamps: false !== startOptions.logTimestamps,
|
|
809
|
+
logColor: false !== startOptions.logColor,
|
|
810
|
+
logUrl: startOptions.logUrl,
|
|
811
|
+
logTab: startOptions.logTab
|
|
812
|
+
});
|
|
813
|
+
telemetry.track('cli_vendor_finish', {
|
|
814
|
+
command: 'start',
|
|
815
|
+
vendor,
|
|
816
|
+
duration_ms: Date.now() - vendorStart
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
telemetry.track('cli_command_finish', {
|
|
820
|
+
command: 'start',
|
|
821
|
+
duration_ms: Date.now() - cmdStart,
|
|
822
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
823
|
+
exit_code: process.exitCode ?? 0
|
|
304
824
|
});
|
|
305
825
|
});
|
|
306
|
-
|
|
826
|
+
}
|
|
827
|
+
function registerPreviewCommand(program, telemetry) {
|
|
828
|
+
program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description('Preview the extension in production mode').option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').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('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json>', '[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('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
|
|
829
|
+
if (previewOptions.author || previewOptions['authorMode']) {
|
|
830
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
831
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
832
|
+
}
|
|
833
|
+
const cmdStart = Date.now();
|
|
834
|
+
telemetry.track('cli_command_start', {
|
|
835
|
+
command: 'preview',
|
|
836
|
+
vendors: vendors(browser)
|
|
837
|
+
});
|
|
307
838
|
const list = vendors(browser);
|
|
308
|
-
validateVendorsOrExit(list)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
839
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
840
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
841
|
+
});
|
|
842
|
+
if (!process.env.EXTJS_LIGHT) {
|
|
843
|
+
const isRemote = 'string' == typeof pathOrRemoteUrl && /^https?:/i.test(pathOrRemoteUrl);
|
|
844
|
+
if (isRemote) process.env.EXTJS_LIGHT = '1';
|
|
845
|
+
}
|
|
846
|
+
const major = String(package_namespaceObject.version).split('.')[0] || '2';
|
|
847
|
+
const { extensionPreview } = await requireOrDlx('extension-develop', major);
|
|
848
|
+
for (const vendor of list){
|
|
849
|
+
const vendorStart = Date.now();
|
|
850
|
+
telemetry.track('cli_vendor_start', {
|
|
851
|
+
command: 'preview',
|
|
852
|
+
vendor
|
|
853
|
+
});
|
|
854
|
+
const logsOption = previewOptions.logs;
|
|
855
|
+
const logContextOption = previewOptions.logContext;
|
|
856
|
+
const logContexts = (()=>{
|
|
857
|
+
const raw = logContextOption || previewOptions.logContexts;
|
|
858
|
+
if (!raw || 0 === String(raw).trim().length) return;
|
|
859
|
+
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
860
|
+
const allowed = [
|
|
861
|
+
'background',
|
|
862
|
+
'content',
|
|
863
|
+
'page',
|
|
864
|
+
'sidebar',
|
|
865
|
+
'popup',
|
|
866
|
+
'options',
|
|
867
|
+
'devtools'
|
|
868
|
+
];
|
|
869
|
+
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
870
|
+
return values.length ? values : void 0;
|
|
871
|
+
})();
|
|
872
|
+
await extensionPreview(pathOrRemoteUrl, {
|
|
873
|
+
mode: 'production',
|
|
874
|
+
profile: previewOptions.profile,
|
|
875
|
+
browser: vendor,
|
|
876
|
+
chromiumBinary: previewOptions.chromiumBinary,
|
|
877
|
+
geckoBinary: previewOptions.geckoBinary,
|
|
878
|
+
startingUrl: previewOptions.startingUrl,
|
|
879
|
+
port: previewOptions.port,
|
|
880
|
+
source: 'string' == typeof previewOptions.source ? previewOptions.source : previewOptions.source,
|
|
881
|
+
watchSource: previewOptions.watchSource,
|
|
882
|
+
logLevel: logsOption || previewOptions.logLevel || 'off',
|
|
883
|
+
logContexts,
|
|
884
|
+
logFormat: previewOptions.logFormat || 'pretty',
|
|
885
|
+
logTimestamps: false !== previewOptions.logTimestamps,
|
|
886
|
+
logColor: false !== previewOptions.logColor,
|
|
887
|
+
logUrl: previewOptions.logUrl,
|
|
888
|
+
logTab: previewOptions.logTab
|
|
889
|
+
});
|
|
890
|
+
telemetry.track('cli_vendor_finish', {
|
|
891
|
+
command: 'preview',
|
|
892
|
+
vendor,
|
|
893
|
+
duration_ms: Date.now() - vendorStart
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
telemetry.track('cli_command_finish', {
|
|
897
|
+
command: 'preview',
|
|
898
|
+
duration_ms: Date.now() - cmdStart,
|
|
899
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
900
|
+
exit_code: process.exitCode ?? 0
|
|
317
901
|
});
|
|
318
902
|
});
|
|
319
|
-
|
|
903
|
+
}
|
|
904
|
+
function registerBuildCommand(program, telemetry) {
|
|
905
|
+
program.command('build').arguments('[project-name]').usage('build [path-to-remote-extension] [options]').description('Builds the extension for production').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`').option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`').option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'whether or not to open the browser automatically. Defaults to `false`').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
|
|
906
|
+
if (buildOptions.author || buildOptions['authorMode']) {
|
|
907
|
+
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
908
|
+
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
909
|
+
}
|
|
910
|
+
const cmdStart = Date.now();
|
|
911
|
+
telemetry.track('cli_command_start', {
|
|
912
|
+
command: 'build',
|
|
913
|
+
vendors: vendors(browser),
|
|
914
|
+
polyfill_used: buildOptions.polyfill || false,
|
|
915
|
+
zip: buildOptions.zip || false,
|
|
916
|
+
zip_source: buildOptions.zipSource || false
|
|
917
|
+
});
|
|
320
918
|
const list = vendors(browser);
|
|
321
|
-
validateVendorsOrExit(list)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
919
|
+
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
920
|
+
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
921
|
+
});
|
|
922
|
+
const major = String(package_namespaceObject.version).split('.')[0] || '2';
|
|
923
|
+
const { extensionBuild } = await requireOrDlx('extension-develop', major);
|
|
924
|
+
for (const vendor of list){
|
|
925
|
+
const vendorStart = Date.now();
|
|
926
|
+
telemetry.track('cli_vendor_start', {
|
|
927
|
+
command: 'build',
|
|
928
|
+
vendor
|
|
929
|
+
});
|
|
930
|
+
const buildSummary = await extensionBuild(pathOrRemoteUrl, {
|
|
931
|
+
browser: vendor,
|
|
932
|
+
polyfill: buildOptions.polyfill,
|
|
933
|
+
zip: buildOptions.zip,
|
|
934
|
+
zipSource: buildOptions.zipSource,
|
|
935
|
+
zipFilename: buildOptions.zipFilename,
|
|
936
|
+
silent: buildOptions.silent
|
|
937
|
+
});
|
|
938
|
+
telemetry.track('cli_build_summary', {
|
|
939
|
+
...buildSummary
|
|
940
|
+
});
|
|
941
|
+
telemetry.track('cli_vendor_finish', {
|
|
942
|
+
command: 'build',
|
|
943
|
+
vendor,
|
|
944
|
+
duration_ms: Date.now() - vendorStart
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
telemetry.track('cli_command_finish', {
|
|
948
|
+
command: 'build',
|
|
949
|
+
duration_ms: Date.now() - cmdStart,
|
|
950
|
+
success: 0 === process.exitCode || null == process.exitCode,
|
|
951
|
+
exit_code: process.exitCode ?? 0
|
|
330
952
|
});
|
|
331
953
|
});
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
954
|
+
}
|
|
955
|
+
check_updates_checkUpdates(package_namespaceObject);
|
|
956
|
+
const extensionJs = external_commander_namespaceObject.program;
|
|
957
|
+
extensionJs.name(package_namespaceObject.name).description(package_namespaceObject.description).version(package_namespaceObject.version).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true);
|
|
958
|
+
registerCreateCommand(extensionJs, telemetry_cli_telemetry);
|
|
959
|
+
registerDevCommand(extensionJs, telemetry_cli_telemetry);
|
|
960
|
+
registerStartCommand(extensionJs, telemetry_cli_telemetry);
|
|
961
|
+
registerPreviewCommand(extensionJs, telemetry_cli_telemetry);
|
|
962
|
+
registerBuildCommand(extensionJs, telemetry_cli_telemetry);
|
|
963
|
+
extensionJs.on('option:ai-help', function() {
|
|
964
|
+
console.log(programAIHelp());
|
|
965
|
+
process.exit(0);
|
|
966
|
+
});
|
|
967
|
+
if (process.argv.length <= 2) {
|
|
968
|
+
extensionJs.outputHelp();
|
|
969
|
+
process.exit(0);
|
|
970
|
+
}
|
|
971
|
+
extensionJs.parse();
|
|
342
972
|
for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
343
973
|
Object.defineProperty(exports, '__esModule', {
|
|
344
974
|
value: true
|