browser-extension-manager 1.5.0 → 1.6.0

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 CHANGED
@@ -61,10 +61,13 @@ BXM ships a built-in four-layer test framework. Write tests under `test/<layer>/
61
61
  npx bxm test # all layers
62
62
  npx bxm test --layer build # build layer only (plain Node, fast)
63
63
  npx bxm test --layer boot # real-Chromium end-to-end test
64
- npx bxm test --integration # also run integration suites against REAL external services (Firebase, etc.)
64
+ npx bxm test project: # ONLY your project's tests (mgr: only framework tests)
65
+ npx bxm test --extended # also run extended suites against REAL external services (Firebase, etc.)
65
66
  ```
66
67
 
67
- Tests run against the **real** harness — a real MV3 service worker, a real Chromium tab, the real packaged extension. **Never mock** (`chrome`, the Manager, contexts are all real); only pure, I/O-free functions are called directly. Real external APIs are gated behind `--integration` (skipped in-source otherwise, never mocked).
68
+ Tests run against the **real** harness — a real MV3 service worker, a real Chromium tab, the real packaged extension. **Never mock** (`chrome`, the Manager, contexts are all real); only pure, I/O-free functions are called directly. Real external APIs are gated behind **extended mode** — `--extended` or the shared, unprefixed `TEST_EXTENDED_MODE=true` env var (skipped in-source otherwise, never mocked).
69
+
70
+ All CLI output also lands in `logs/` (ANSI-stripped, truncated each run) — `test.log` from `npx bxm test`, `dev.log` from `npm start`, `build.log` from `npm run build`. Details: [docs/logging.md](docs/logging.md).
68
71
 
69
72
  Test files use Jest-compatible matchers:
70
73
 
@@ -4,15 +4,34 @@ const fs = require('fs');
4
4
  const Manager = new (require('../build.js'));
5
5
  const logger = Manager.logger('test');
6
6
  const { run } = require('../test/runner.js');
7
+ const attachLogFile = require('../utils/attach-log-file.js');
8
+ const { EXTENDED_MODE_WARNING } = require('../test/utils/extended-mode-warning.js');
7
9
 
8
10
  module.exports = async function (options) {
11
+ // Tee all test output to <projectRoot>/logs/test.log (ANSI-stripped) — mirrors
12
+ // EM's test.log and BEM's test.log pattern.
13
+ attachLogFile(path.join(process.cwd(), 'logs', 'test.log'));
14
+
9
15
  const layer = options.layer || 'all';
16
+ // Positional target: `npx mgr test <target>` where target supports source
17
+ // prefixes — `project:`, `project:<path>`, `mgr:`, `bxm:`, or a bare `<path>`.
18
+ const target = (options._ && options._[1]) || null;
19
+ // `--filter` flag: substring match on test NAMES/descriptions (orthogonal to target).
10
20
  const filter = options.filter || null;
11
21
  const reporter = options.reporter || 'pretty';
12
- const integration = options.integration === true || options.integration === 'true';
22
+ // Extended mode opt into tests that hit REAL external services (Firebase via web-manager,
23
+ // push, any network call) instead of skipping them. Off by default so `npx mgr test` stays
24
+ // fast and offline-safe. The canonical signal is the unprefixed `TEST_EXTENDED_MODE` env var
25
+ // — the SAME name across BEM/BXM/UJM/EM (cross-framework parity); `--extended` is the CLI
26
+ // shorthand. Once set on process.env it propagates to every spawned test environment (the
27
+ // in-process Node runner, and Puppeteer's Chromium which inherits process.env).
28
+ const extended = options.extended === true
29
+ || options.extended === 'true'
30
+ || process.env.TEST_EXTENDED_MODE === 'true'
31
+ || process.env.TEST_EXTENDED_MODE === '1';
13
32
 
14
- if (integration) {
15
- process.env.BXM_TEST_INTEGRATION = '1';
33
+ if (extended) {
34
+ process.env.TEST_EXTENDED_MODE = 'true';
16
35
  }
17
36
 
18
37
  // Canonical signal — every Manager picks this up via isTesting().
@@ -32,10 +51,15 @@ module.exports = async function (options) {
32
51
  }
33
52
 
34
53
  if (reporter !== 'json') {
35
- logger.log(`Running tests (layer=${layer}${filter ? ` filter="${filter}"` : ''}${integration ? ' +integration' : ''})`);
54
+ logger.log(`Running tests (layer=${layer}${target ? ` target="${target}"` : ''}${filter ? ` filter="${filter}"` : ''}${extended ? ' +extended' : ''})`);
55
+ logger.log(`Test mode: ${extended ? 'extended (real external APIs)' : 'normal (external APIs skipped)'}`);
56
+ if (extended) {
57
+ logger.warn(EXTENDED_MODE_WARNING[0]);
58
+ EXTENDED_MODE_WARNING.slice(1).forEach((line) => logger.warn(line));
59
+ }
36
60
  }
37
61
 
38
- const result = await run({ layer, filter, reporter });
62
+ const result = await run({ layer, target, filter, reporter });
39
63
 
40
64
  if (reporter === 'json') {
41
65
  // Final machine-readable summary.
@@ -50,6 +74,11 @@ module.exports = async function (options) {
50
74
 
51
75
  if (result.failed > 0) {
52
76
  process.exitCode = 1;
77
+ await attachLogFile.detach();
53
78
  throw new Error(`${result.failed} test(s) failed`);
54
79
  }
80
+
81
+ // Flush test.log fully and restore stdout/stderr. Stream writes are async, so
82
+ // detach() resolves once the buffered tail (the Results block) is on disk.
83
+ await attachLogFile.detach();
55
84
  };
@@ -28,6 +28,13 @@ npm start # dev with live reload (gulp → webpack → serve)
28
28
  npm run build # production build → dist/ + packaged/<browser>/raw/ + .zip per browser
29
29
  BXM_IS_PUBLISH=true npm run build # build + auto-upload to Chrome / Firefox / Edge stores
30
30
  npx mgr test # run framework + project test suites
31
+ npx mgr test build/config # bare path: run tests matching a path in BOTH sources
32
+ npx mgr test project: # run ONLY your project tests (project:<path> to narrow)
33
+ npx mgr test mgr: # run ONLY framework tests (bxm: / framework: are equivalent aliases)
34
+ npx mgr test bxm:build/config # run only framework tests matching a path
35
+ # Positional target selects which test FILES run; --filter=<substring> matches test NAMES within them
36
+ npx mgr test --extended # also run tests that hit REAL external services (off by default; TEST_EXTENDED_MODE=true is the env equivalent — shared name across BEM/BXM/UJM/EM)
37
+ # (output is teed to logs/ — dev.log on `npm start`, build.log on `npm run build`, test.log on `npx mgr test`; cat instead of scrolling scrollback)
31
38
  npx mgr install dev # use LOCAL browser-extension-manager source (to test framework edits)
32
39
  npx mgr install live # restore the published browser-extension-manager from npm
33
40
  ```
@@ -75,6 +82,16 @@ After `initialize()`, every Manager exposes:
75
82
 
76
83
  Auth UI is declarative — add `.auth-signin-btn` / `.auth-signout-btn` / `.auth-account-btn` to buttons; BXM wires them. Show/hide based on auth state via `data-wm-bind="@show auth.user"`.
77
84
 
85
+ ## Dependency resolution
86
+
87
+ - **Do NOT install framework dependencies directly** (`firebase`, `web-manager`, etc.). BXM's webpack config resolves them through the framework's own `node_modules/`. If something doesn't resolve, the issue is in BXM's webpack config — not your `package.json`.
88
+ - **web-manager owns Firebase.** Never `import firebase from 'firebase/app'`. Use `import webManager from 'web-manager'` → `webManager.auth()`, `webManager.firestore()`.
89
+ - **`Manager.require(name)`** resolves from BXM's module context at runtime for unbundled code (gulp tasks, test fixtures).
90
+
91
+ ## Testing
92
+
93
+ Every feature ships with tests at every layer it has a surface in: **logic** (`test/build/`, `test/background/`), **UI** (`test/view/` — real events on the real DOM), and **end-to-end** (`test/boot/`). Skip a layer only when the feature genuinely has no surface there — "the logic test covers it" does not excuse the UI test. See `test/README.md` and `node_modules/browser-extension-manager/docs/test-framework.md`.
94
+
78
95
  <!-- Everything above this marker is owned by the framework and rewritten on every `npx mgr setup`. Add your project-specific notes below — they are preserved across setups. -->
79
96
 
80
97
  # ========== Custom Values ==========
@@ -13,6 +13,12 @@ Match the framework's four layers — Browser Extension Manager's test runner di
13
13
  | `test/view/` | Popup / options / sidepanel page | DOM, view-side controllers, `data-wm-bind` directives |
14
14
  | `test/boot/` | Consumer's actual built extension | End-to-end smoke tests (does the extension load, does the background register, do views render) |
15
15
 
16
+ ## Coverage
17
+
18
+ Every feature ships with tests at every layer it has a surface in — logic (`build`/`background`), UI (`view`), end-to-end (`boot`). Skip a layer only when the feature genuinely has no surface there; "the logic test covers it" does not excuse the UI test.
19
+
20
+ Tests that hit REAL external services (Firebase, push, network) are skipped by default — gate them on `process.env.TEST_EXTENDED_MODE` (`if (process.env.TEST_EXTENDED_MODE !== 'true') ctx.skip('extended mode off');`) and run them with `npx mgr test --extended` (or `TEST_EXTENDED_MODE=true`). `TEST_EXTENDED_MODE` is the shared, unprefixed name across BEM/BXM/UJM/EM. Never mock the external service — skip it in-source.
21
+
16
22
  ## Quick example
17
23
 
18
24
  ```js
package/dist/gulp/main.js CHANGED
@@ -14,6 +14,19 @@ const projectRoot = Manager.getRootPath('project');
14
14
  // Load .env file from project root
15
15
  require('dotenv').config({ path: path.join(projectRoot, '.env') });
16
16
 
17
+ // Tee all stdout/stderr to <projectRoot>/logs/<dev|build>.log for easy `tail -f` / grep / Claude
18
+ // inspection — captures gulp task output, webpack/serve output, console.log calls, the works.
19
+ // build.log for production builds (BXM_BUILD_MODE=true), dev.log for `npm start`.
20
+ // Disable via BXM_LOG_FILE=false. Override path via BXM_LOG_FILE=<path>.
21
+ const attachLogFile = require('../utils/attach-log-file.js');
22
+ const logFileEnv = process.env.BXM_LOG_FILE;
23
+ if (logFileEnv !== 'false' && logFileEnv !== '0') {
24
+ const defaultName = Manager.isBuildMode() ? 'build.log' : 'dev.log';
25
+ const logPath = (logFileEnv && logFileEnv !== 'true') ? logFileEnv : path.join(projectRoot, 'logs', defaultName);
26
+ attachLogFile(logPath);
27
+ logger.log(`Logs tee'd to ${logPath}`);
28
+ }
29
+
17
30
  // Log
18
31
  logger.log('Starting...', argv);
19
32
 
@@ -39,12 +39,13 @@ class SkipError extends Error {
39
39
 
40
40
  async function run(options = {}) {
41
41
  options.layer = options.layer || 'all';
42
+ options.target = options.target || null;
42
43
  options.filter = options.filter || null;
43
44
  options.reporter = options.reporter || 'pretty';
44
45
 
45
46
  const startTime = Date.now();
46
47
 
47
- const sources = discoverTestFiles();
48
+ const sources = discoverTestFiles(options.target);
48
49
 
49
50
  console.log('');
50
51
  console.log(chalk.bold(' Browser Extension Manager Tests'));
@@ -360,7 +361,49 @@ function reportResults(results, durationMs) {
360
361
  console.log(chalk.gray(`\n Total: ${total} tests in ${durationMs}ms\n`));
361
362
  }
362
363
 
363
- function discoverTestFiles() {
364
+ // Parse a positional test target into a source filter + path part.
365
+ // Source prefixes (standardized across all OMEGA frameworks):
366
+ // 'mgr:' / 'bxm:' / 'framework:' → framework tests ('mgr:' is the universal alias)
367
+ // 'project:' → project tests
368
+ // no prefix → both sources, matched by path
369
+ function parseTarget(target) {
370
+ if (!target) {
371
+ return { source: null, pathPart: null };
372
+ }
373
+
374
+ const m = String(target).match(/^(project|mgr|bxm|framework):(.*)$/);
375
+ if (m) {
376
+ const source = m[1] === 'project' ? 'project' : 'framework';
377
+ return { source, pathPart: m[2] || null };
378
+ }
379
+
380
+ return { source: null, pathPart: target };
381
+ }
382
+
383
+ // Narrow a source's file list by the parsed target. A source-prefixed target
384
+ // excludes the other source entirely; the path part (if any) matches by
385
+ // relative path prefix.
386
+ function filterBySource(source, files, sourceFilter, pathPart) {
387
+ if (sourceFilter && sourceFilter !== source) {
388
+ return [];
389
+ }
390
+ if (!pathPart) {
391
+ return files;
392
+ }
393
+
394
+ return files.filter((file) => {
395
+ const rel = relativizePath(file, source);
396
+ const relNoExt = rel.replace(/\.js$/, '').replace(/\.test$/, '');
397
+ const partNoExt = pathPart.replace(/\.js$/, '').replace(/\.test$/, '');
398
+ return rel.startsWith(pathPart)
399
+ || relNoExt === partNoExt
400
+ || relNoExt.startsWith(partNoExt + '/')
401
+ || rel.includes(pathPart);
402
+ });
403
+ }
404
+
405
+ function discoverTestFiles(target) {
406
+ const { source: sourceFilter, pathPart } = parseTarget(target);
364
407
  const framework = [];
365
408
  const project = [];
366
409
 
@@ -398,7 +441,10 @@ function discoverTestFiles() {
398
441
  });
399
442
  }
400
443
 
401
- return { framework, project };
444
+ return {
445
+ framework: filterBySource('framework', framework, sourceFilter, pathPart),
446
+ project: filterBySource('project', project, sourceFilter, pathPart),
447
+ };
402
448
  }
403
449
 
404
450
  function relativizePath(file, source) {
@@ -0,0 +1,90 @@
1
+ // Build-layer tests for src/utils/attach-log-file.js — tee process.stdout/stderr to a file
2
+ // with ANSI stripping. Each test attaches, writes, detaches, then inspects the file.
3
+ //
4
+ // CRITICAL: these tests run INSIDE a live `npx mgr test` process whose own output is being
5
+ // teed to logs/test.log by the singleton. So they must NOT touch the singleton — exercising
6
+ // attach()/detach() on it would detach the live tee mid-run and truncate logs/test.log. Each
7
+ // test uses its OWN `createTee()` instance, which stacks under the live singleton tee and
8
+ // restores it cleanly on detach.
9
+
10
+ const path = require('path');
11
+ const fs = require('fs');
12
+ const os = require('os');
13
+
14
+ module.exports = {
15
+ type: 'suite',
16
+ layer: 'build',
17
+ description: 'attach-log-file — tee stdout/stderr to a file',
18
+ tests: [
19
+ {
20
+ name: 'exports the expected surface',
21
+ run: (ctx) => {
22
+ const mod = require(path.join(__dirname, '..', '..', '..', 'utils', 'attach-log-file.js'));
23
+ ctx.expect(typeof mod).toBe('function');
24
+ ctx.expect(typeof mod.detach).toBe('function');
25
+ ctx.expect(typeof mod.stripAnsi).toBe('function');
26
+ ctx.expect(typeof mod.createTee).toBe('function');
27
+ },
28
+ },
29
+ {
30
+ name: 'stripAnsi removes color escape codes',
31
+ run: (ctx) => {
32
+ const { stripAnsi } = require(path.join(__dirname, '..', '..', '..', 'utils', 'attach-log-file.js'));
33
+ const colored = '\x1B[31mred\x1B[0m and \x1B[32mgreen\x1B[0m';
34
+ ctx.expect(stripAnsi(colored)).toBe('red and green');
35
+ },
36
+ },
37
+ {
38
+ name: 'attach + stdout.write + detach: file contains the writes',
39
+ run: async (ctx) => {
40
+ const attach = require(path.join(__dirname, '..', '..', '..', 'utils', 'attach-log-file.js'));
41
+ // Isolated instance — stacks under the live test.log tee, never clobbers it.
42
+ const tee = attach.createTee();
43
+ const tmpPath = path.join(os.tmpdir(), `bxm-log-${Date.now()}.log`);
44
+ try {
45
+ const stream = tee.attach(tmpPath);
46
+ process.stdout.write('hello world\n');
47
+ process.stdout.write('\x1B[31mcolored\x1B[0m line\n');
48
+ // Wait for stream to flush before detaching + reading.
49
+ await new Promise((resolve) => stream.write('', resolve));
50
+ tee.detach();
51
+ // detach() ends the stream; wait for the close event.
52
+ await new Promise((resolve) => stream.on('close', resolve));
53
+
54
+ const contents = fs.readFileSync(tmpPath, 'utf8');
55
+ ctx.expect(contents).toContain('hello world');
56
+ ctx.expect(contents).toContain('colored line');
57
+ ctx.expect(contents).not.toContain('\x1B[');
58
+ } finally {
59
+ tee.detach();
60
+ try { fs.unlinkSync(tmpPath); } catch (e) {}
61
+ }
62
+ },
63
+ },
64
+ {
65
+ name: 'idempotent: attaching twice with same path returns same stream',
66
+ run: (ctx) => {
67
+ const attach = require(path.join(__dirname, '..', '..', '..', 'utils', 'attach-log-file.js'));
68
+ const tee = attach.createTee();
69
+ const tmpPath = path.join(os.tmpdir(), `bxm-log-idem-${Date.now()}.log`);
70
+ try {
71
+ const s1 = tee.attach(tmpPath);
72
+ const s2 = tee.attach(tmpPath);
73
+ ctx.expect(s1).toBe(s2);
74
+ } finally {
75
+ tee.detach();
76
+ try { fs.unlinkSync(tmpPath); } catch (e) {}
77
+ }
78
+ },
79
+ },
80
+ {
81
+ name: 'attach with falsy path returns null and does nothing',
82
+ run: (ctx) => {
83
+ const attach = require(path.join(__dirname, '..', '..', '..', 'utils', 'attach-log-file.js'));
84
+ const tee = attach.createTee();
85
+ ctx.expect(tee.attach(null)).toBe(null);
86
+ ctx.expect(tee.attach('')).toBe(null);
87
+ },
88
+ },
89
+ ],
90
+ };
@@ -0,0 +1,13 @@
1
+ // TEST_EXTENDED_MODE warning — SSOT for consistent messaging.
2
+ //
3
+ // Mirrors BEM/EM/UJM: `TEST_EXTENDED_MODE` is the shared, unprefixed env var that opts a
4
+ // test run into hitting REAL external services instead of skipping/stubbing them. Off by
5
+ // default so `npx mgr test` stays fast and offline-safe. Used by the test command (printed to
6
+ // console + teed to logs/test.log).
7
+ const EXTENDED_MODE_WARNING = [
8
+ '⚠️⚠️⚠️ WARNING: TEST_EXTENDED_MODE IS TRUE ⚠️⚠️⚠️',
9
+ 'Tests that hit real external services (Firebase via web-manager, push, any network call) are ENABLED!',
10
+ 'This makes real network calls from the background service worker, popup, and content scripts against live backends.',
11
+ ];
12
+
13
+ module.exports = { EXTENDED_MODE_WARNING };
@@ -0,0 +1,105 @@
1
+ // attachLogFile(filePath) — duplicate process.stdout + process.stderr writes to a log file.
2
+ //
3
+ // Inspired by BEM's per-command log pattern, mirrored from EM. Lets devs (and Claude) `tail -f` a
4
+ // log file to see every line of output a process produces — test runner output, child process
5
+ // stdout/stderr, console.log calls, the works.
6
+ //
7
+ // ANSI color codes are stripped from the file output so it's grep-friendly. The console
8
+ // continues to receive the original colored output unchanged.
9
+ //
10
+ // The default export is a process-wide SINGLETON (the common case: a CLI command tees its
11
+ // whole run to one file). `attachLogFile.createTee()` returns an INDEPENDENT tee with its own
12
+ // state. Tees STACK: a later attach() captures the CURRENT `process.stdout.write` (which may
13
+ // already be an outer tee) as its "original", so writes fan out through every layer and
14
+ // detach() restores the exact prior writer in LIFO order. That stacking is what lets the
15
+ // attach-log-file unit tests exercise attach/detach on a throwaway instance WITHOUT killing
16
+ // the live singleton tee that's capturing the actual test run — the bug that previously
17
+ // truncated `logs/test.log` to ~9 lines (the test detached the live tee mid-run).
18
+ //
19
+ // Idempotent: calling attach() twice with the same path on one tee returns the existing handle.
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ const ANSI_PATTERN = /\x1B\[[0-9;]*[a-zA-Z]/g;
25
+
26
+ function stripAnsi(s) {
27
+ return String(s).replace(ANSI_PATTERN, '');
28
+ }
29
+
30
+ // Factory — each call returns an independent tee with its own closure state.
31
+ function createTee() {
32
+ let activeStream = null;
33
+ let activePath = null;
34
+ let originalStdoutWrite = null;
35
+ let originalStderrWrite = null;
36
+
37
+ function attach(filePath) {
38
+ if (!filePath) return null;
39
+ const abs = path.resolve(filePath);
40
+
41
+ if (activeStream && activePath === abs) return activeStream;
42
+ if (activeStream) detach();
43
+
44
+ // Truncate fresh on each invocation — same as BEM's `flags: 'w'`. Devs running multiple
45
+ // sessions back to back don't want stale lines from the previous run mixed in.
46
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
47
+ const stream = fs.createWriteStream(abs, { flags: 'w' });
48
+
49
+ // Header so the file is self-documenting.
50
+ stream.write(`# bxm log — ${new Date().toISOString()} — pid=${process.pid}\n`);
51
+
52
+ // Capture whatever the CURRENT writer is — could be the raw stream OR an outer tee.
53
+ // Restoring this exact reference on detach() is what makes stacked tees safe.
54
+ originalStdoutWrite = process.stdout.write.bind(process.stdout);
55
+ originalStderrWrite = process.stderr.write.bind(process.stderr);
56
+
57
+ process.stdout.write = function (chunk, ...rest) {
58
+ try { stream.write(stripAnsi(String(chunk))); } catch (e) { /* ignore */ }
59
+ return originalStdoutWrite(chunk, ...rest);
60
+ };
61
+ process.stderr.write = function (chunk, ...rest) {
62
+ try { stream.write(stripAnsi(String(chunk))); } catch (e) { /* ignore */ }
63
+ return originalStderrWrite(chunk, ...rest);
64
+ };
65
+
66
+ activeStream = stream;
67
+ activePath = abs;
68
+
69
+ return stream;
70
+ }
71
+
72
+ // Restores stdout/stderr and ends the stream. Returns a Promise that resolves once all
73
+ // buffered writes have been flushed to disk — await it before process.exit(), otherwise the
74
+ // tail of the log is silently dropped.
75
+ function detach() {
76
+ if (originalStdoutWrite) process.stdout.write = originalStdoutWrite;
77
+ if (originalStderrWrite) process.stderr.write = originalStderrWrite;
78
+ const stream = activeStream;
79
+ activeStream = null;
80
+ activePath = null;
81
+ originalStdoutWrite = null;
82
+ originalStderrWrite = null;
83
+
84
+ return new Promise((resolve) => {
85
+ if (!stream) {
86
+ return resolve();
87
+ }
88
+ stream.end(resolve);
89
+ });
90
+ }
91
+
92
+ return { attach, detach };
93
+ }
94
+
95
+ // Process-wide singleton — the production entry point.
96
+ const singleton = createTee();
97
+
98
+ function attachLogFile(filePath) {
99
+ return singleton.attach(filePath);
100
+ }
101
+
102
+ module.exports = attachLogFile;
103
+ module.exports.detach = singleton.detach;
104
+ module.exports.stripAnsi = stripAnsi;
105
+ module.exports.createTee = createTee;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-extension-manager",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Browser Extension Manager dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -76,8 +76,8 @@
76
76
  "homepage": "https://template.itwcreativeworks.com",
77
77
  "dependencies": {
78
78
  "@anthropic-ai/claude-agent-sdk": "^0.2.138",
79
- "@babel/core": "^7.29.0",
80
- "@babel/preset-env": "^7.29.5",
79
+ "@babel/core": "^7.29.7",
80
+ "@babel/preset-env": "^7.29.7",
81
81
  "@popperjs/core": "^2.11.8",
82
82
  "babel-loader": "^10.1.1",
83
83
  "chalk": "^5.6.2",
@@ -95,12 +95,12 @@
95
95
  "minimatch": "^10.2.5",
96
96
  "node-powertools": "^3.0.0",
97
97
  "npm-api": "^1.0.1",
98
- "sass": "^1.99.0",
99
- "web-manager": "^4.1.42",
100
- "webpack": "^5.106.2",
98
+ "sass": "^1.100.0",
99
+ "web-manager": "^4.2.0",
100
+ "webpack": "^5.107.2",
101
101
  "wonderful-fetch": "^2.0.5",
102
102
  "wonderful-version": "^1.3.2",
103
- "ws": "^8.20.0",
103
+ "ws": "^8.21.0",
104
104
  "yargs": "^18.0.0"
105
105
  },
106
106
  "peerDependencies": {