browser-extension-manager 1.7.2 → 1.7.4

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.
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env node
2
- const argv = require('yargs')(process.argv.slice(2)).parseSync();
2
+ // Value-less flags must be declared boolean — otherwise yargs treats the next
3
+ // positional as the flag's VALUE (`mgr test --extended some/target` became
4
+ // extended='some/target' with NO target, silently running EVERYTHING in
5
+ // normal mode). Mirrors the same fix in BEM's CLI.
6
+ const argv = require('yargs')(process.argv.slice(2)).boolean(['extended']).parseSync();
3
7
  const cli = new (require('../dist/cli.js'))(argv);
4
8
  (async function() {
5
9
  'use strict';
package/dist/build.js CHANGED
@@ -101,8 +101,11 @@ Manager.getManifest = function () {
101
101
  Manager.prototype.getManifest = Manager.getManifest;
102
102
 
103
103
  // getConfig: requires and parses browser-extension-manager.json
104
+ // Missing file (framework repo, or a consumer before first setup) → {} — same
105
+ // guard as getManifest above; JSON5.parse(undefined) throws a cryptic
106
+ // "invalid character 'u'" otherwise
104
107
  Manager.getConfig = function () {
105
- return JSON5.parse(jetpack.read(path.join(process.cwd(), 'config', 'browser-extension-manager.json')));
108
+ return JSON5.parse(jetpack.read(path.join(process.cwd(), 'config', 'browser-extension-manager.json')) || '{}');
106
109
  }
107
110
  Manager.prototype.getConfig = Manager.getConfig;
108
111
 
@@ -37,6 +37,11 @@ const FILE_MAP = {
37
37
  'src/**/*': {
38
38
  overwrite: false,
39
39
  },
40
+ // Consumer-owned after seeding (e.g. test/_init.js fixture hooks) — copy when
41
+ // missing, never clobber the consumer's version on setup reruns
42
+ 'test/**/*': {
43
+ overwrite: false,
44
+ },
40
45
  'src/**/*.{html,md}': {
41
46
  skip: (file) => {
42
47
  // Get the name
@@ -520,6 +525,11 @@ function defaultsWatcher(complete) {
520
525
  // Default Task
521
526
  module.exports = series(defaults, defaultsWatcher);
522
527
 
528
+ // Exported for tests — the FILE_MAP rules are load-bearing (a missing rule means
529
+ // the fall-through overwrite: true silently clobbers consumer-owned files on
530
+ // setup reruns)
531
+ module.exports.getFileOptions = getFileOptions;
532
+
523
533
  function getFileOptions(filePath) {
524
534
  const defaults = {
525
535
  overwrite: true,
@@ -0,0 +1,64 @@
1
+ // getFileOptions from src/gulp/tasks/defaults.js — the FILE_MAP rules that decide
2
+ // which shipped defaults may overwrite consumer files on `npx bxm setup` reruns.
3
+ // Regression here silently clobbers consumer-owned files: test/_init.js had no
4
+ // matching rule, and the fall-through default is overwrite: true, so every setup
5
+ // rerun reset the consumer's fixture hook to the stub (same gap UJM fixed in 1.9.26).
6
+
7
+ module.exports = {
8
+ type: 'group',
9
+ layer: 'build',
10
+ description: 'defaults FILE_MAP (gulp/tasks/defaults.js getFileOptions)',
11
+ tests: [
12
+ {
13
+ name: 'consumer-owned seeds are copy-once (test/, hooks/, src/)',
14
+ run: async (ctx) => {
15
+ const { getFileOptions } = require('../../../gulp/tasks/defaults.js');
16
+
17
+ // The regression case: consumer fixture hook must survive setup reruns
18
+ ctx.expect(getFileOptions('test/_init.js').overwrite).toBe(false);
19
+ ctx.expect(getFileOptions('test/README.md').overwrite).toBe(false);
20
+
21
+ ctx.expect(getFileOptions('hooks/build/pre.js').overwrite).toBe(false);
22
+ ctx.expect(getFileOptions('src/manifest.json').overwrite).toBe(false);
23
+ ctx.expect(getFileOptions('src/assets/css/main.scss').overwrite).toBe(false);
24
+ },
25
+ },
26
+ {
27
+ name: 'framework-owned files always overwrite',
28
+ run: async (ctx) => {
29
+ const { getFileOptions } = require('../../../gulp/tasks/defaults.js');
30
+
31
+ // .nvmrc is templated and framework-owned (overwrite stays the default true)
32
+ const nvmrc = getFileOptions('.nvmrc');
33
+ ctx.expect(nvmrc.overwrite).toBe(true);
34
+ ctx.expect(!!nvmrc.template).toBe(true);
35
+
36
+ // Unmatched files fall through to overwrite: true — any new consumer-owned
37
+ // default MUST get an explicit rule or setup will clobber it
38
+ const workflow = getFileOptions('.github/workflows/publish.yml');
39
+ ctx.expect(workflow.overwrite).toBe(true);
40
+ ctx.expect(workflow.rule).toBeNull();
41
+ },
42
+ },
43
+ {
44
+ name: 'merge and skip rules resolve as declared',
45
+ run: async (ctx) => {
46
+ const { getFileOptions } = require('../../../gulp/tasks/defaults.js');
47
+
48
+ // Last-match-wins: CLAUDE.md picks up mergeLines AFTER **/*.md set overwrite: false
49
+ const claude = getFileOptions('CLAUDE.md');
50
+ ctx.expect(claude.mergeLines).toBe(true);
51
+ ctx.expect(claude.rule).toBe('CLAUDE.md');
52
+
53
+ const config = getFileOptions('config/browser-extension-manager.json');
54
+ ctx.expect(config.overwrite).toBe(true);
55
+ ctx.expect(config.merge).toBe(true);
56
+
57
+ ctx.expect(getFileOptions('config/messages.json').overwrite).toBe(false);
58
+
59
+ ctx.expect(getFileOptions('test/.DS_Store').skip).toBe(true);
60
+ ctx.expect(getFileOptions('src/__temp/scratch.js').skip).toBe(true);
61
+ },
62
+ },
63
+ ],
64
+ };
package/docs/defaults.md CHANGED
@@ -12,12 +12,16 @@
12
12
 
13
13
  ```js
14
14
  const FILE_MAP = {
15
- 'src/**/*': { overwrite: false }, // never overwrite user code
15
+ '**/*.md': { overwrite: false }, // docs are consumer-owned after seeding
16
16
  'hooks/**/*': { overwrite: false }, // never overwrite hooks
17
- '_.gitignore': { name: () => '.gitignore' }, // rename on copy
18
- '_.env': { name: () => '.env', overwrite: false },
19
- '.nvmrc': { template: { node: '22' } }, // run templating against the source
20
- 'package.json': { skip: (cwd) => /* dynamic skip */ },
17
+ 'src/**/*': { overwrite: false }, // never overwrite user code
18
+ 'test/**/*': { overwrite: false }, // consumer-owned after seeding (test/_init.js!)
19
+ '_.gitignore': { name: () => '.gitignore', mergeLines: true }, // rename + marker-based merge
20
+ '_.env': { name: () => '.env', mergeLines: true },
21
+ 'CLAUDE.md': { mergeLines: true }, // framework section live-syncs; Custom section is consumer-owned
22
+ 'config/browser-extension-manager.json': { overwrite: true, merge: true },
23
+ '.nvmrc': { template: cleanVersions }, // run templating against the source
24
+ '**/.DS_Store': { skip: true },
21
25
  };
22
26
  ```
23
27
 
@@ -31,6 +35,8 @@ const FILE_MAP = {
31
35
  | `template: data` | Run the source through templating with `data` as the var bag, then write. |
32
36
  | `name: function` | Rename on copy — typically used to add a leading `.` (`_.gitignore` → `.gitignore`). |
33
37
 
38
+ ⚠️ **Unmatched files fall through to `overwrite: true`** — any NEW consumer-owned default MUST get an explicit copy-once rule, or every `npx bxm setup` rerun clobbers the consumer's version (exactly how `test/_init.js` got reset before the `test/**/*` rule existed). Rules are last-match-wins — `CLAUDE.md` gains `mergeLines` after `**/*.md` already set copy-once. The rule classes are locked by `src/test/suites/build/defaults-file-options.test.js`.
39
+
34
40
  ## Why the underscore prefix?
35
41
 
36
42
  Files like `_.gitignore`, `_.env` are stored with a `_` prefix in `src/defaults/` so they don't interfere with BXM's own development (the framework repo doesn't want its `.env` overwritten by the template). The `name` rule renames them to the real `.foo` filename on copy.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-extension-manager",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "Browser Extension Manager dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {