browser-extension-manager 1.2.13 → 1.2.14

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.
@@ -90,7 +90,7 @@
90
90
  // IDs
91
91
  browser_specific_settings: {
92
92
  gecko: {
93
- id: 'my-addon@example.com',
93
+ // id: 'my-addon@example.com',
94
94
  strict_min_version: '91.0',
95
95
  // Required for new Firefox extensions as of Nov 2025
96
96
  // https://blog.mozilla.org/addons/2025/10/23/data-collection-consent-changes-for-new-firefox-extensions/
@@ -128,8 +128,8 @@ async function auditFn(complete) {
128
128
  auditResults.localeWarnings = [];
129
129
 
130
130
  try {
131
- // Find all files in packaged directory (JS, HTML, etc.)
132
- const packagedDir = path.join(rootPathProject, 'packaged', 'raw');
131
+ // Audit chromium build (code is same for both targets, only manifest differs)
132
+ const packagedDir = path.join(rootPathProject, 'packaged', 'chromium', 'raw');
133
133
 
134
134
  if (!jetpack.exists(packagedDir)) {
135
135
  logger.log(chalk.yellow('⚠️ Packaged directory not found. Run package task first.'));
@@ -152,8 +152,11 @@ function getPackageVersion(packageName) {
152
152
  }
153
153
  }
154
154
 
155
+ // Build targets
156
+ const TARGETS = ['chromium', 'firefox'];
157
+
155
158
  // Special Compilation Task for manifest.json with default settings
156
- async function compileManifest(outputDir) {
159
+ async function compileManifest(outputDir, target) {
157
160
  try {
158
161
  const manifestPath = path.join('dist', 'manifest.json');
159
162
  const outputPath = path.join(outputDir, 'manifest.json');
@@ -189,10 +192,27 @@ async function compileManifest(outputDir) {
189
192
  // Add package version to manifest
190
193
  manifest.version = project.version;
191
194
 
195
+ // Apply target-specific manifest adjustments
196
+ if (manifest.background) {
197
+ if (target === 'chromium') {
198
+ // Chrome/Edge uses service_worker only
199
+ delete manifest.background.scripts;
200
+ } else if (target === 'firefox') {
201
+ // Firefox uses scripts array only
202
+ if (manifest.background.service_worker) {
203
+ // Ensure scripts array exists (derive from service_worker if needed)
204
+ if (!manifest.background.scripts) {
205
+ manifest.background.scripts = [manifest.background.service_worker];
206
+ }
207
+ delete manifest.background.service_worker;
208
+ }
209
+ }
210
+ }
211
+
192
212
  // Save as regular JSON
193
213
  jetpack.write(outputPath, JSON.stringify(manifest, null, 2));
194
214
 
195
- logger.log(`Manifest compiled with defaults`);
215
+ logger.log(`[${target}] Manifest compiled with defaults`);
196
216
  } catch (e) {
197
217
  logger.error(`Error compiling manifest`, e);
198
218
  }
@@ -225,76 +245,92 @@ async function compileLocales(outputDir) {
225
245
  }
226
246
  }
227
247
 
228
- // Package Task for raw
248
+ // Package Task for raw - creates both chromium and firefox builds
229
249
  async function packageRaw() {
230
250
  // Log
231
251
  logger.log(`Starting raw packaging...`);
232
252
 
233
253
  try {
234
- const outputDir = 'packaged/raw';
254
+ // Build for each target
255
+ for (const target of TARGETS) {
256
+ await packageRawForTarget(target);
257
+ }
235
258
 
236
- // Ensure the directory exists
237
- jetpack.dir(outputDir);
259
+ // Log completion
260
+ logger.log(`Finished raw packaging for all targets`);
261
+ } catch (e) {
262
+ logger.error(`Error during raw packaging`, e);
263
+ }
264
+ }
265
+
266
+ // Package raw for a specific target (chromium or firefox)
267
+ async function packageRawForTarget(target) {
268
+ logger.log(`[${target}] Starting raw packaging...`);
269
+
270
+ const outputDir = `packaged/${target}/raw`;
238
271
 
239
- // Copy files to raw package directory
240
- await execute(`cp -r dist/* ${outputDir}`);
272
+ // Ensure the directory exists (this also cleans it)
273
+ jetpack.dir(outputDir, { empty: true });
241
274
 
242
- // Loop thru outputDir/dist/assets/js all JS files
243
- const jsFiles = jetpack.find(path.join(outputDir, 'assets', 'js'), { matching: '*.js' });
244
- const redactions = getRedactions();
275
+ // Copy files to raw package directory
276
+ await execute(`cp -r dist/* ${outputDir}`);
245
277
 
246
- jsFiles.forEach(filePath => {
247
- // Load the content
248
- let content = jetpack.read(filePath);
278
+ // Loop thru outputDir/assets/js all JS files for redactions
279
+ const jsFiles = jetpack.find(path.join(outputDir, 'assets', 'js'), { matching: '*.js' });
280
+ const redactions = getRedactions();
249
281
 
250
- // Replace keys with their corresponding values
251
- Object.keys(redactions).forEach(key => {
252
- const value = redactions[key];
253
- const regex = new RegExp(key, 'g'); // Create a global regex for the key
254
- content = content.replace(regex, value);
282
+ jsFiles.forEach(filePath => {
283
+ // Load the content
284
+ let content = jetpack.read(filePath);
255
285
 
256
- // Log replacement
257
- logger.log(`Redacted ${key} in ${filePath}`);
258
- });
286
+ // Replace keys with their corresponding values
287
+ Object.keys(redactions).forEach(key => {
288
+ const value = redactions[key];
289
+ const regex = new RegExp(key, 'g'); // Create a global regex for the key
290
+ content = content.replace(regex, value);
259
291
 
260
- // Write the new content to the file
261
- jetpack.write(filePath, content);
292
+ // Log replacement
293
+ logger.log(`[${target}] Redacted ${key} in ${filePath}`);
262
294
  });
263
295
 
264
- // Generate build.js and build.json
265
- await generateBuildJs(outputDir);
296
+ // Write the new content to the file
297
+ jetpack.write(filePath, content);
298
+ });
266
299
 
267
- // Compile manifest and locales
268
- await compileManifest(outputDir);
269
- await compileLocales(outputDir);
300
+ // Generate build.js and build.json
301
+ await generateBuildJs(outputDir);
270
302
 
271
- // Log completion
272
- logger.log(`Finished raw packaging`);
273
- } catch (e) {
274
- logger.error(`Error during raw packaging`, e);
275
- }
303
+ // Compile manifest (target-specific) and locales
304
+ await compileManifest(outputDir, target);
305
+ await compileLocales(outputDir);
306
+
307
+ logger.log(`[${target}] Finished raw packaging`);
276
308
  }
277
309
 
278
- // Create zipped version of raw package
310
+ // Create zipped version of raw packages for each target
279
311
  async function packageZip() {
280
312
  // Log
281
- logger.log(`Zipping raw package...`);
313
+ logger.log(`Zipping raw packages...`);
314
+
315
+ // Skip if not in build mode
316
+ if (!Manager.isBuildMode()) {
317
+ logger.log(`Skipping zip (not in build mode)`);
318
+ return;
319
+ }
282
320
 
283
321
  try {
284
- const inputDir = 'packaged/raw';
285
- const zipPath = 'packaged/extension.zip';
322
+ // Create zip for each target
323
+ for (const target of TARGETS) {
324
+ const inputDir = `packaged/${target}/raw`;
325
+ const zipPath = `packaged/${target}/extension.zip`;
286
326
 
287
- // Create packed extension (.zip)
288
- if (Manager.isBuildMode()) {
289
327
  // Remove existing zip if it exists
290
328
  jetpack.remove(zipPath);
291
329
 
292
330
  // Zip contents of raw directory (not the directory itself)
293
331
  // This ensures manifest.json is at the root of the zip
294
- await execute(`cd ${inputDir} && zip -r ../../${zipPath} .`);
295
- logger.log(`Zipped package created at ${zipPath}`);
296
- } else {
297
- logger.log(`Skipping zip (not in build mode)`);
332
+ await execute(`cd ${inputDir} && zip -r ../extension.zip .`);
333
+ logger.log(`[${target}] Zipped package created at ${zipPath}`);
298
334
  }
299
335
  } catch (e) {
300
336
  logger.error(`Error zipping package`, e);
@@ -9,8 +9,17 @@ const { execute } = require('node-powertools');
9
9
  // Load package
10
10
  const project = Manager.getPackage('project');
11
11
 
12
- // Paths
13
- const zipPath = path.join(process.cwd(), 'packaged', 'extension.zip');
12
+ // Paths for each target
13
+ const PATHS = {
14
+ chromium: {
15
+ zip: path.join(process.cwd(), 'packaged', 'chromium', 'extension.zip'),
16
+ raw: path.join(process.cwd(), 'packaged', 'chromium', 'raw'),
17
+ },
18
+ firefox: {
19
+ zip: path.join(process.cwd(), 'packaged', 'firefox', 'extension.zip'),
20
+ raw: path.join(process.cwd(), 'packaged', 'firefox', 'raw'),
21
+ },
22
+ };
14
23
 
15
24
  // Helper to check if a credential is valid (not empty or placeholder)
16
25
  function isValidCredential(value) {
@@ -56,9 +65,13 @@ async function publish(complete) {
56
65
  // Log
57
66
  logger.log('Starting publish...');
58
67
 
59
- // Check if zip exists
60
- if (!jetpack.exists(zipPath)) {
61
- logger.error(`Extension zip not found at ${zipPath}. Run build first.`);
68
+ // Check if zips exist for each target
69
+ const missingZips = Object.entries(PATHS)
70
+ .filter(([, paths]) => !jetpack.exists(paths.zip))
71
+ .map(([target]) => target);
72
+
73
+ if (missingZips.length > 0) {
74
+ logger.error(`Extension zips not found for: ${missingZips.join(', ')}. Run build first.`);
62
75
  return complete();
63
76
  }
64
77
 
@@ -158,10 +171,10 @@ async function publishToChrome() {
158
171
 
159
172
  logger.log('[chrome] Uploading to Chrome Web Store...');
160
173
 
161
- // Use chrome-webstore-upload-cli
174
+ // Use chrome-webstore-upload-cli with chromium build
162
175
  const command = [
163
176
  'npx chrome-webstore-upload-cli',
164
- `--source "${zipPath}"`,
177
+ `--source "${PATHS.chromium.zip}"`,
165
178
  `--extension-id "${extensionId}"`,
166
179
  `--client-id "${clientId}"`,
167
180
  `--client-secret "${clientSecret}"`,
@@ -188,11 +201,10 @@ async function publishToFirefox() {
188
201
 
189
202
  logger.log('[firefox] Uploading to Firefox Add-ons...');
190
203
 
191
- // Use web-ext sign
192
- const rawDir = path.join(process.cwd(), 'packaged', 'raw');
204
+ // Use web-ext sign with firefox build
193
205
  const command = [
194
206
  'npx web-ext sign',
195
- `--source-dir "${rawDir}"`,
207
+ `--source-dir "${PATHS.firefox.raw}"`,
196
208
  `--api-key "${apiKey}"`,
197
209
  `--api-secret "${apiSecret}"`,
198
210
  `--channel "${channel}"`,
@@ -218,8 +230,8 @@ async function publishToEdge() {
218
230
 
219
231
  logger.log('[edge] Uploading to Microsoft Edge Add-ons...');
220
232
 
221
- // Read zip file
222
- const zipBuffer = jetpack.read(zipPath, 'buffer');
233
+ // Read chromium zip file (Edge uses same build as Chrome)
234
+ const zipBuffer = jetpack.read(PATHS.chromium.zip, 'buffer');
223
235
 
224
236
  // Edge API v1.1 endpoint
225
237
  const uploadUrl = `https://api.addons.microsoftedge.microsoft.com/v1/products/${productId}/submissions/draft/package`;
@@ -25,8 +25,9 @@ npm install
25
25
  ```sh
26
26
  npm run build
27
27
  ```
28
- 5. The built extension will be in `packaged/raw/` directory
29
- 6. The packaged zip will be at `packaged/extension.zip`
28
+ 5. The built extensions will be in `packaged/` directory:
29
+ - **Firefox:** `packaged/firefox/raw/` (unpacked) and `packaged/firefox/extension.zip`
30
+ - **Chrome/Edge:** `packaged/chromium/raw/` (unpacked) and `packaged/chromium/extension.zip`
30
31
 
31
32
  ## Loading the Extension
32
33
 
@@ -34,13 +35,19 @@ npm run build
34
35
  1. Go to `about:debugging`
35
36
  2. Click "This Firefox"
36
37
  3. Click "Load Temporary Add-on"
37
- 4. Select `packaged/raw/manifest.json`
38
+ 4. Select `packaged/firefox/raw/manifest.json`
38
39
 
39
40
  ### Chrome
40
41
  1. Go to `chrome://extensions`
41
42
  2. Enable "Developer mode"
42
43
  3. Click "Load unpacked"
43
- 4. Select the `packaged/raw/` directory
44
+ 4. Select the `packaged/chromium/raw/` directory
45
+
46
+ ### Edge
47
+ 1. Go to `edge://extensions`
48
+ 2. Enable "Developer mode"
49
+ 3. Click "Load unpacked"
50
+ 4. Select the `packaged/chromium/raw/` directory
44
51
 
45
52
  ## Questions
46
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-extension-manager",
3
- "version": "1.2.13",
3
+ "version": "1.2.14",
4
4
  "description": "Browser Extension Manager dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {