browser-extension-manager 1.3.28 → 1.3.30

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.
@@ -3,12 +3,13 @@ const Manager = new (require('../build.js'));
3
3
  const logger = Manager.logger('clean');
4
4
  const { execSync } = require('child_process');
5
5
  const jetpack = require('fs-jetpack');
6
+ const path = require('path');
6
7
 
7
8
  // Load package
8
9
  const package = Manager.getPackage('main');
9
10
  const project = Manager.getPackage('project');
10
11
 
11
- // Const dirs
12
+ // Dirs to clean
12
13
  const dirs = [
13
14
  '.temp',
14
15
  'dist',
@@ -16,11 +17,29 @@ const dirs = [
16
17
  // 'src/assets/themes',
17
18
  ]
18
19
 
20
+ // Dirs to preserve inside cleaned dirs
21
+ const preserve = [
22
+ 'packaged/translations',
23
+ ]
24
+
19
25
  module.exports = async function (options) {
20
26
  // Log
21
27
  logger.log(`Cleaning up .temp, dist, and packaged directories...`);
22
28
 
23
29
  try {
30
+ // Back up preserved dirs
31
+ const backups = {};
32
+ for (const dir of preserve) {
33
+ if (!jetpack.exists(dir)) {
34
+ continue;
35
+ }
36
+
37
+ const backupPath = path.join('.temp', '_preserve', dir);
38
+ jetpack.dir(path.dirname(backupPath));
39
+ jetpack.move(dir, backupPath, { overwrite: true });
40
+ backups[dir] = backupPath;
41
+ }
42
+
24
43
  // Loop through dirs
25
44
  dirs.forEach((dir) => {
26
45
  // Remove (use rm -rf on Unix for speed, fallback to jetpack on Windows)
@@ -33,6 +52,16 @@ module.exports = async function (options) {
33
52
  // Create empty dir
34
53
  jetpack.dir(dir);
35
54
  });
55
+
56
+ // Restore preserved dirs
57
+ for (const [dir, backupPath] of Object.entries(backups)) {
58
+ jetpack.dir(path.dirname(dir));
59
+ jetpack.move(backupPath, dir, { overwrite: true });
60
+ logger.log(`Preserved: ${dir}`);
61
+ }
62
+
63
+ // Clean up temp preserve dir
64
+ jetpack.remove(path.join('.temp', '_preserve'));
36
65
  } catch (e) {
37
66
  logger.error(`Error clearing directories: ${e}`);
38
67
  }
@@ -0,0 +1,46 @@
1
+ 🚀 Enhance Your Browsing Experience Instantly
2
+ 🧠 Smart Features That Work in the Background
3
+ ⚡ One-Click Setup — No Configuration Needed
4
+ 🎯 Customizable Settings — Your Browser, Your Rules
5
+ 💡 Lightweight, Fast, Zero Bloat
6
+
7
+ {{ brand.name }} is your all-in-one browser companion that makes the web work better for you. No more frustrating browsing experiences. No more wasting time on repetitive tasks. No more settling for a browser that doesn't do enough.
8
+ If you want a smarter, faster, and more enjoyable browsing experience — {{ brand.name }} was made for you.
9
+
10
+ 🔍 How it works
11
+ {{ brand.name }} runs quietly in the background, enhancing your browsing experience automatically.
12
+
13
+ 🧠 Smart Detection: Knows when to activate and when to stay out of the way
14
+ 🔧 Powerful Tools: Access everything you need from a simple popup
15
+ ⚙️ Customizable: Tailor the extension to fit your browsing habits
16
+ 🌐 Works Everywhere: Compatible with all your favorite websites
17
+
18
+ Click the icon, adjust your settings, and browse better. Everything else just works.
19
+ No complicated setup. No learning curve. Just a better browsing experience, instantly.
20
+
21
+ ✨ Why {{ brand.name }} is a game changer
22
+
23
+ Save time: Automate repetitive tasks and get more done with less effort.
24
+ Stay in control: Customize every aspect of the extension to match your preferences.
25
+ Browse smarter: Intelligent features that adapt to how you use the web.
26
+ Clean and fast: Minimal footprint — no slowdowns, no clutter, no unnecessary bloat.
27
+ Private and secure: No cloud accounts required. No tracking. Everything runs locally and respects your privacy.
28
+
29
+ 🧠 The {{ brand.name }} Difference
30
+ Most people either:
31
+
32
+ Settle for a bare-bones browser with no enhancements
33
+ Install a dozen separate extensions that slow everything down
34
+
35
+ {{ brand.name }} gives you a better option: one powerful extension that does it all — cleanly, efficiently, and without getting in your way.
36
+ Think of it as a supercharger for your browser ⚡
37
+ Whether you're working, researching, shopping, or just casually browsing — {{ brand.name }} makes every session better.
38
+
39
+ 🔥 Install {{ brand.name }} now and upgrade the way you browse.
40
+ Stop settling for a basic browser. Start browsing smarter.
41
+
42
+ 💸 Bonus:
43
+ While you're browsing, the extension also finds and applies shopping deals from top partners like Amazon, Capital One, and NordVPN. Get discounts and bonuses without lifting a finger. When you buy through links on our extension, we may earn an affiliate commission.
44
+
45
+ 🔐 Your privacy is respected — we do not sell or misuse your data. By using our extension, you agree to our terms of service and privacy policy.
46
+ When you buy through links on our extension, we may earn an affiliate commission.
@@ -66,11 +66,17 @@ const FILE_MAP = {
66
66
  mergeLines: true,
67
67
  },
68
68
 
69
- // Config file with smart merging
69
+ // Config files
70
70
  'config/browser-extension-manager.json': {
71
71
  overwrite: true,
72
72
  merge: true,
73
73
  },
74
+ 'config/messages.json': {
75
+ overwrite: false,
76
+ },
77
+ 'config/description.md': {
78
+ overwrite: false,
79
+ },
74
80
 
75
81
  // Files to run templating on
76
82
  '.nvmrc': {
@@ -1,153 +1,188 @@
1
1
  // Libraries
2
2
  const Manager = new (require('../../build.js'));
3
3
  const logger = Manager.logger('translate');
4
+ const { query } = require('@anthropic-ai/claude-agent-sdk');
4
5
  const { series } = require('gulp');
5
6
  const jetpack = require('fs-jetpack');
6
7
  const path = require('path');
7
- const { execute } = require('node-powertools');
8
+ const crypto = require('crypto');
8
9
  const JSON5 = require('json5');
9
10
 
10
11
  // Locale config (shared with audit.js)
11
12
  const { limits: LOCALE_LIMITS, languages: LANGUAGES } = require('../config/locales.js');
12
13
 
13
14
  // Paths
15
+ const configMessagesPath = path.join(process.cwd(), 'config', 'messages.json');
16
+ const configDescriptionPath = path.join(process.cwd(), 'config', 'description.md');
14
17
  const localesDir = path.join(process.cwd(), 'src', '_locales');
15
18
  const enMessagesPath = path.join(localesDir, 'en', 'messages.json');
19
+ const translationsDir = path.join(process.cwd(), 'packaged', 'translations');
20
+ const descriptionDir = path.join(translationsDir, 'description');
21
+ const cacheDir = path.join(process.cwd(), '.cache');
22
+ const cachePath = path.join(cacheDir, 'translate.json');
23
+
24
+ // Helper: Compute hash of a string
25
+ function hash(content) {
26
+ return crypto.createHash('md5').update(content).digest('hex');
27
+ }
28
+
29
+ // Helper: Read cache
30
+ function readCache() {
31
+ if (!jetpack.exists(cachePath)) {
32
+ return {};
33
+ }
16
34
 
17
- // Check if Claude CLI is installed
18
- async function isClaudeInstalled() {
19
35
  try {
20
- await execute('which claude');
21
- return true;
36
+ return JSON.parse(jetpack.read(cachePath));
22
37
  } catch (e) {
23
- return false;
38
+ return {};
24
39
  }
25
40
  }
26
41
 
27
- // Main translate task
28
- async function translate(complete) {
29
- // Only run in build mode
30
- if (!Manager.isBuildMode()) {
31
- logger.log('Skipping translation (not in build mode)');
32
- return complete();
33
- }
42
+ // Helper: Write cache
43
+ function writeCache(cache) {
44
+ jetpack.dir(cacheDir);
45
+ jetpack.write(cachePath, JSON.stringify(cache, null, 2));
46
+ }
34
47
 
35
- // Check if Claude CLI is installed
36
- if (!await isClaudeInstalled()) {
37
- logger.log('Skipping translation (Claude CLI not installed)');
38
- return complete();
39
- }
48
+ // Helper: Check if source has changed since last translation
49
+ function hasSourceChanged(cacheKey, content) {
50
+ const cache = readCache();
51
+ const currentHash = hash(content);
40
52
 
41
- // Log
42
- logger.log('Starting translation...');
53
+ return cache[cacheKey] !== currentHash;
54
+ }
43
55
 
44
- // Check if English messages exist
45
- if (!jetpack.exists(enMessagesPath)) {
46
- logger.warn(`English messages not found at ${enMessagesPath}`);
47
- return complete();
56
+ // Helper: Update cache hash for a source
57
+ function updateCacheHash(cacheKey, content) {
58
+ const cache = readCache();
59
+
60
+ cache[cacheKey] = hash(content);
61
+
62
+ writeCache(cache);
63
+ }
64
+
65
+ // Helper: Read and parse config/messages.json
66
+ function readConfigMessages() {
67
+ if (!jetpack.exists(configMessagesPath)) {
68
+ return null;
48
69
  }
49
70
 
50
- // Read English messages
51
- let enMessages;
52
71
  try {
53
- enMessages = JSON5.parse(jetpack.read(enMessagesPath));
72
+ return JSON5.parse(jetpack.read(configMessagesPath));
54
73
  } catch (e) {
55
- logger.error(`Failed to parse English messages: ${e.message}`);
56
- return complete();
74
+ logger.error(`Failed to parse config/messages.json: ${e.message}`);
75
+ return null;
57
76
  }
77
+ }
58
78
 
59
- // Get English keys
60
- const enKeys = Object.keys(enMessages);
61
- logger.log(`Found ${enKeys.length} keys in English messages`);
62
-
63
- // Check which languages need translation
64
- const languagesToTranslate = [];
65
-
66
- for (const lang of Object.keys(LANGUAGES)) {
67
- const langDir = path.join(localesDir, lang);
68
- const langMessagesPath = path.join(langDir, 'messages.json');
69
-
70
- // Check if translation exists
71
- const exists = jetpack.exists(langMessagesPath);
72
-
73
- if (!exists) {
74
- languagesToTranslate.push({ lang, missingKeys: enKeys, existingMessages: {} });
75
- continue;
76
- }
77
-
78
- // Check for missing keys
79
- try {
80
- const existingMessages = JSON5.parse(jetpack.read(langMessagesPath));
81
- const missingKeys = enKeys.filter(key => !existingMessages[key]);
82
-
83
- if (missingKeys.length > 0) {
84
- logger.log(`[${lang}] Found ${missingKeys.length} missing keys`);
85
- languagesToTranslate.push({ lang, missingKeys, existingMessages });
86
- } else {
87
- logger.log(`[${lang}] Up to date, skipping`);
79
+ // Helper: Call Claude Agent SDK with a prompt and parse JSON from the response
80
+ async function callClaude(prompt) {
81
+ let result = '';
82
+
83
+ for await (const message of query({
84
+ prompt,
85
+ options: {
86
+ model: 'claude-sonnet-4-5-20250929',
87
+ maxTurns: 1,
88
+ allowedTools: [],
89
+ thinking: { type: 'disabled' },
90
+ },
91
+ })) {
92
+ // Collect assistant text
93
+ if (message.type === 'assistant' && message.message?.content) {
94
+ for (const block of message.message.content) {
95
+ if (block.type === 'text') {
96
+ result += block.text;
97
+ }
88
98
  }
89
- } catch (e) {
90
- logger.warn(`[${lang}] Failed to parse existing messages, will retranslate: ${e.message}`);
91
- languagesToTranslate.push({ lang, missingKeys: enKeys, existingMessages: {} });
92
99
  }
93
100
  }
94
101
 
95
- // Skip if nothing to translate
96
- if (languagesToTranslate.length === 0) {
97
- logger.log('All translations up to date');
98
- return complete();
102
+ logger.log(`Claude responded (${result.length} chars)`);
103
+
104
+ // Parse JSON from response
105
+ const jsonMatch = result.match(/\{[\s\S]*\}/);
106
+ if (!jsonMatch) {
107
+ throw new Error('No JSON found in Claude response');
99
108
  }
100
109
 
101
- logger.log(`Translating ${languagesToTranslate.length} languages in one call...`);
110
+ return JSON.parse(jsonMatch[0]);
111
+ }
102
112
 
103
- // Translate all languages at once
104
- try {
105
- const translations = await translateAllWithClaude(enMessages, languagesToTranslate);
113
+ // Helper: Split an object into chunks of a given size
114
+ function chunkObject(obj, size) {
115
+ const entries = Object.entries(obj);
116
+ const chunks = [];
106
117
 
107
- // Write each translation
108
- for (const { lang, existingMessages } of languagesToTranslate) {
109
- const langDir = path.join(localesDir, lang);
110
- const langMessagesPath = path.join(langDir, 'messages.json');
118
+ for (let i = 0; i < entries.length; i += size) {
119
+ chunks.push(Object.fromEntries(entries.slice(i, i + size)));
120
+ }
111
121
 
112
- if (translations[lang]) {
113
- // Merge with existing messages
114
- const finalMessages = { ...existingMessages, ...translations[lang] };
122
+ return chunks;
123
+ }
115
124
 
116
- // Ensure directory exists
117
- jetpack.dir(langDir);
125
+ // Copy config files to src/ locations
126
+ // Always runs (dev + build) so distribute task has the latest files
127
+ async function copyConfigFiles(complete) {
128
+ // Copy config/messages.json → src/_locales/en/messages.json
129
+ const enMessages = readConfigMessages();
130
+ if (enMessages) {
131
+ jetpack.dir(path.join(localesDir, 'en'));
132
+ jetpack.write(enMessagesPath, JSON.stringify(enMessages, null, 2));
133
+ logger.log('Copied config/messages.json → src/_locales/en/messages.json');
134
+ } else {
135
+ logger.warn('config/messages.json not found or invalid, skipping');
136
+ }
118
137
 
119
- // Write translated messages
120
- jetpack.write(langMessagesPath, JSON.stringify(finalMessages, null, 2));
138
+ // Complete
139
+ return complete();
140
+ }
121
141
 
122
- logger.log(`[${lang}] Translation saved`);
123
- } else {
124
- logger.warn(`[${lang}] No translation returned`);
125
- }
126
- }
127
- } catch (e) {
128
- logger.error(`Translation failed: ${e.message}`);
142
+ // Translate messages.json into all configured languages
143
+ // Only runs in build mode
144
+ async function translateMessages(complete) {
145
+ // Only run in build mode
146
+ if (!Manager.isBuildMode()) {
147
+ logger.log('Skipping messages translation (not in build mode)');
148
+ return complete();
129
149
  }
130
150
 
131
151
  // Log
132
- logger.log('Translation finished!');
152
+ logger.log('Starting messages translation...');
133
153
 
134
- // Complete
135
- return complete();
136
- }
154
+ // Read config/messages.json
155
+ const enMessages = readConfigMessages();
156
+ if (!enMessages) {
157
+ logger.warn('config/messages.json not found or invalid, skipping');
158
+ return complete();
159
+ }
160
+
161
+ // Check if source has changed
162
+ const sourceContent = jetpack.read(configMessagesPath);
163
+ if (!hasSourceChanged('messages', sourceContent)) {
164
+ logger.log('config/messages.json unchanged since last translation, skipping');
165
+ return complete();
166
+ }
167
+
168
+ // Get English keys
169
+ const enKeys = Object.keys(enMessages);
170
+ logger.log(`Found ${enKeys.length} keys in config/messages.json`);
137
171
 
138
- // Translate all languages using a single Claude CLI call
139
- async function translateAllWithClaude(enMessages, languagesToTranslate) {
140
- // Build language info for prompt
141
- const languageList = languagesToTranslate.map(({ lang }) =>
142
- `- "${lang}": ${LANGUAGES[lang]}`
143
- ).join('\n');
172
+ // Build language list
173
+ const languageList = Object.entries(LANGUAGES)
174
+ .map(([code, name]) => `- "${code}": ${name}`)
175
+ .join('\n');
144
176
 
145
177
  // Build character limits info
146
178
  const limitsInfo = Object.entries(LOCALE_LIMITS)
147
179
  .map(([field, limit]) => `- ${field}: max ${limit} characters`)
148
180
  .join('\n');
149
181
 
150
- const prompt = `Translate the following Chrome extension messages.json content from English to multiple languages.
182
+ logger.log(`Translating messages into ${Object.keys(LANGUAGES).length} languages...`);
183
+
184
+ try {
185
+ const translations = await callClaude(`Translate the following Chrome extension messages.json content from English to multiple languages.
151
186
 
152
187
  TARGET LANGUAGES:
153
188
  ${languageList}
@@ -174,48 +209,135 @@ OUTPUT FORMAT:
174
209
  ...
175
210
  }
176
211
 
177
- Output the translated JSON:`;
212
+ Output the translated JSON:`);
213
+
214
+ // Write each translation
215
+ for (const lang of Object.keys(LANGUAGES)) {
216
+ if (!translations[lang]) {
217
+ logger.warn(`[${lang}] No translation returned`);
218
+ continue;
219
+ }
220
+
221
+ const langDir = path.join(localesDir, lang);
222
+ const langMessagesPath = path.join(langDir, 'messages.json');
223
+
224
+ jetpack.dir(langDir);
225
+ jetpack.write(langMessagesPath, JSON.stringify(translations[lang], null, 2));
226
+ logger.log(`[${lang}] Messages translation saved`);
227
+ }
228
+
229
+ // Update cache
230
+ updateCacheHash('messages', sourceContent);
231
+ } catch (e) {
232
+ logger.error(`Messages translation failed: ${e.message}`);
233
+ }
234
+
235
+ // Log
236
+ logger.log('Messages translation finished!');
237
+
238
+ // Complete
239
+ return complete();
240
+ }
241
+
242
+ // Translate description.md into all configured languages
243
+ // Only runs in build mode
244
+ async function translateDescription(complete) {
245
+ // Only run in build mode
246
+ if (!Manager.isBuildMode()) {
247
+ logger.log('Skipping description translation (not in build mode)');
248
+ return complete();
249
+ }
250
+
251
+ // Log
252
+ logger.log('Starting description translation...');
253
+
254
+ // Check if English description exists
255
+ if (!jetpack.exists(configDescriptionPath)) {
256
+ logger.log('config/description.md not found, skipping');
257
+ return complete();
258
+ }
259
+
260
+ // Read English description
261
+ const enDescription = jetpack.read(configDescriptionPath);
262
+ if (!enDescription || !enDescription.trim()) {
263
+ logger.warn('config/description.md is empty, skipping');
264
+ return complete();
265
+ }
178
266
 
179
- // Write prompt to temp file to avoid shell escaping issues
180
- const tempDir = path.join(process.cwd(), '.temp');
181
- const tempFile = path.join(tempDir, 'translate-all.txt');
267
+ // Check if source has changed
268
+ if (!hasSourceChanged('description', enDescription)) {
269
+ logger.log('config/description.md unchanged since last translation, skipping');
270
+ return complete();
271
+ }
272
+
273
+ logger.log(`Found config/description.md (${enDescription.length} chars)`);
274
+
275
+ // Batch languages into chunks to avoid output size limits
276
+ const BATCH_SIZE = 4;
277
+ const batches = chunkObject(LANGUAGES, BATCH_SIZE);
278
+
279
+ logger.log(`Translating description into ${Object.keys(LANGUAGES).length} languages (${batches.length} batches of ${BATCH_SIZE})...`);
280
+
281
+ // Ensure description directory exists
282
+ jetpack.dir(descriptionDir);
182
283
 
183
284
  try {
184
- // Ensure temp dir exists and write prompt
185
- jetpack.dir(tempDir);
186
- jetpack.write(tempFile, prompt);
285
+ for (let i = 0; i < batches.length; i++) {
286
+ const batch = batches[i];
287
+ const languageList = Object.entries(batch)
288
+ .map(([code, name]) => `- "${code}": ${name}`)
289
+ .join('\n');
187
290
 
188
- // Build command - pipe from file
189
- const command = `cat "${tempFile}" | claude -p -`;
291
+ logger.log(`Batch ${i + 1}/${batches.length}: translating ${Object.keys(batch).join(', ')}...`);
190
292
 
191
- // Log start
192
- logger.log('Calling Claude CLI...');
293
+ const translations = await callClaude(`Translate the following Chrome extension store description from English to multiple languages.
193
294
 
194
- // Run Claude CLI
195
- const result = await execute(command);
295
+ TARGET LANGUAGES:
296
+ ${languageList}
196
297
 
197
- // Log response received
198
- logger.log(`Claude CLI responded (${result.length} chars)`);
298
+ IMPORTANT RULES:
299
+ 1. Translate ALL text content including emoji labels and descriptions
300
+ 2. Keep all emojis exactly as they are
301
+ 3. Preserve the markdown formatting (headers, bold, bullet points, etc.)
302
+ 4. Keep brand names, product names, and company names in English (e.g., Amazon, Capital One, NordVPN)
303
+ 5. Maintain the same tone — enthusiastic, conversational, and persuasive
304
+ 6. Return ONLY valid JSON, no markdown code fences, no explanation
305
+ 7. Return a JSON object where each key is the language code and the value is the full translated description as a string
199
306
 
200
- // Clean up temp file
201
- jetpack.remove(tempFile);
307
+ INPUT (English):
308
+ ${enDescription}
202
309
 
203
- // Parse result - extract JSON from response
204
- const jsonMatch = result.match(/\{[\s\S]*\}/);
205
- if (!jsonMatch) {
206
- throw new Error('No JSON found in Claude response');
207
- }
310
+ OUTPUT FORMAT:
311
+ {
312
+ ${Object.keys(batch).map((code) => ` "${code}": "full translated description here..."`).join(',\n')}
313
+ }
314
+
315
+ Output the translated JSON:`);
316
+
317
+ // Write each translation in this batch
318
+ for (const lang of Object.keys(batch)) {
319
+ if (!translations[lang]) {
320
+ logger.warn(`[${lang}] No description translation returned`);
321
+ continue;
322
+ }
208
323
 
209
- // Log success
210
- logger.log('Parsed JSON successfully');
324
+ jetpack.write(path.join(descriptionDir, `${lang}.md`), translations[lang]);
325
+ logger.log(`[${lang}] Description translation saved`);
326
+ }
327
+ }
211
328
 
212
- return JSON.parse(jsonMatch[0]);
329
+ // Update cache
330
+ updateCacheHash('description', enDescription);
213
331
  } catch (e) {
214
- // Clean up temp file on error
215
- jetpack.remove(tempFile);
216
- throw new Error(`Claude CLI failed: ${e.message}`);
332
+ logger.error(`Description translation failed: ${e.message}`);
217
333
  }
334
+
335
+ // Log
336
+ logger.log('Description translation finished!');
337
+
338
+ // Complete
339
+ return complete();
218
340
  }
219
341
 
220
342
  // Export task
221
- module.exports = series(translate);
343
+ module.exports = series(copyConfigFiles, translateMessages, translateDescription);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-extension-manager",
3
- "version": "1.3.28",
3
+ "version": "1.3.30",
4
4
  "description": "Browser Extension Manager dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -66,14 +66,15 @@
66
66
  },
67
67
  "homepage": "https://template.itwcreativeworks.com",
68
68
  "dependencies": {
69
- "@babel/core": "^7.28.6",
70
- "@babel/preset-env": "^7.28.6",
69
+ "@anthropic-ai/claude-agent-sdk": "^0.2.20",
70
+ "@babel/core": "^7.29.0",
71
+ "@babel/preset-env": "^7.29.0",
71
72
  "@popperjs/core": "^2.11.8",
72
73
  "babel-loader": "^10.0.0",
73
74
  "chalk": "^5.6.2",
74
- "dotenv": "^17.2.3",
75
+ "dotenv": "^17.2.4",
75
76
  "fs-jetpack": "^5.1.0",
76
- "glob": "^13.0.0",
77
+ "glob": "^13.0.1",
77
78
  "gulp-clean-css": "^4.3.0",
78
79
  "gulp-filter": "^9.0.1",
79
80
  "gulp-rename": "^2.1.0",
@@ -82,13 +83,13 @@
82
83
  "itwcw-package-analytics": "^1.0.8",
83
84
  "json5": "^2.2.3",
84
85
  "lodash": "^4.17.23",
85
- "minimatch": "^10.1.1",
86
+ "minimatch": "^10.1.2",
86
87
  "node-powertools": "^2.3.2",
87
88
  "npm-api": "^1.0.1",
88
89
  "sass": "^1.97.3",
89
90
  "through2": "^4.0.2",
90
91
  "web-manager": "^4.1.6",
91
- "webpack": "^5.104.1",
92
+ "webpack": "^5.105.0",
92
93
  "wonderful-fetch": "^1.3.4",
93
94
  "wonderful-version": "^1.3.2",
94
95
  "ws": "^8.19.0",