sf-decomposer 6.24.1 → 6.26.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/CHANGELOG.md +19 -0
- package/HANDBOOK.md +24 -24
- package/README.md +235 -191
- package/lib/core/decomposeMetadataTypes.js +12 -12
- package/lib/core/decomposeMetadataTypes.js.map +1 -1
- package/lib/core/recomposeMetadataTypes.js +7 -6
- package/lib/core/recomposeMetadataTypes.js.map +1 -1
- package/lib/core/verifyMetadataTypes.js +3 -7
- package/lib/core/verifyMetadataTypes.js.map +1 -1
- package/lib/helpers/configOverrides.d.ts +14 -0
- package/lib/helpers/configOverrides.js +28 -14
- package/lib/helpers/configOverrides.js.map +1 -1
- package/lib/helpers/types.d.ts +11 -0
- package/lib/metadata/getPackageDirectories.d.ts +1 -1
- package/lib/metadata/getPackageDirectories.js +5 -4
- package/lib/metadata/getPackageDirectories.js.map +1 -1
- package/lib/metadata/getRegistryValuesBySuffix.d.ts +1 -1
- package/lib/metadata/getRegistryValuesBySuffix.js +3 -3
- package/lib/metadata/getRegistryValuesBySuffix.js.map +1 -1
- package/lib/metadata/parseManifest.d.ts +5 -1
- package/lib/metadata/parseManifest.js +30 -28
- package/lib/metadata/parseManifest.js.map +1 -1
- package/lib/service/recompose/recomposeFileHandler.js +1 -2
- package/lib/service/recompose/recomposeFileHandler.js.map +1 -1
- package/lib/service/verify/diffDirectories.js +3 -7
- package/lib/service/verify/diffDirectories.js.map +1 -1
- package/messages/decomposer.decompose.md +1 -1
- package/oclif.manifest.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@
|
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## [6.26.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.25.0...v6.26.0) (2026-06-03)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* support user-configurable uniqueIdElements in overrides config ([#472](https://github.com/mcarvin8/sf-decomposer/issues/472)) ([6d7ed7d](https://github.com/mcarvin8/sf-decomposer/commit/6d7ed7dec516a77205af6d9304f68e2a97942d83))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* remove process.chdir from verify; warn on missing manifest components ([#470](https://github.com/mcarvin8/sf-decomposer/issues/470)) ([81d893e](https://github.com/mcarvin8/sf-decomposer/commit/81d893e323016af712d10c6c0cb818bb1fec34af))
|
|
19
|
+
|
|
20
|
+
## [6.25.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.24.1...v6.25.0) (2026-05-29)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* **metadata:** bump @salesforce/source-deploy-retrieve ([#467](https://github.com/mcarvin8/sf-decomposer/issues/467)) ([30193f2](https://github.com/mcarvin8/sf-decomposer/commit/30193f2b1a0235e77653d05de28ee76fb0971e92))
|
|
26
|
+
|
|
8
27
|
## [6.24.1](https://github.com/mcarvin8/sf-decomposer/compare/v6.24.0...v6.24.1) (2026-05-26)
|
|
9
28
|
|
|
10
29
|
|
package/HANDBOOK.md
CHANGED
|
@@ -11,12 +11,12 @@ If you want the underlying option grammar instead of recipes, see the [main READ
|
|
|
11
11
|
## Contents
|
|
12
12
|
|
|
13
13
|
- [Choosing a strategy](#choosing-a-strategy)
|
|
14
|
+
- [Common pitfalls](#common-pitfalls)
|
|
14
15
|
- [Bots (Agentforce and Einstein)](#bots-agentforce-and-einstein)
|
|
15
16
|
- [Flexipages (Lightning App / Record / Home pages)](#flexipages-lightning-app--record--home-pages)
|
|
16
17
|
- [Layouts (page layouts)](#layouts-page-layouts)
|
|
17
18
|
- [Other deeply-nested types](#other-deeply-nested-types)
|
|
18
19
|
- [The verification workflow](#the-verification-workflow)
|
|
19
|
-
- [Common pitfalls](#common-pitfalls)
|
|
20
20
|
|
|
21
21
|
## Choosing a strategy
|
|
22
22
|
|
|
@@ -44,6 +44,26 @@ The full registry lives in [`src/metadata/multiLevelDefaults.ts`](./src/metadata
|
|
|
44
44
|
|
|
45
45
|
Everything else in this handbook is opt-in.
|
|
46
46
|
|
|
47
|
+
## Common pitfalls
|
|
48
|
+
|
|
49
|
+
**1. "I added two `multiLevel` rules but only one survived."**
|
|
50
|
+
You probably ran two `decompose` invocations back-to-back, one rule each. Don't. The disassembler rewrites `.multi_level.json` on every run, so each call replaces the prior one. Pass every rule for a given component in **one** override entry, in array form.
|
|
51
|
+
|
|
52
|
+
**2. "My `multiLevel` rule is correct but recompose produces a smaller file."**
|
|
53
|
+
On `config-disassembler` Rust ≥ 0.5.0 / Node ≥ 1.3.0 this should not happen — sibling collisions are written to per-element SHA-256 shards and surfaced as a `WARN` (see pitfall #5), not silently overwritten. If you do see a shrunken recomposed file on a current build, treat it as a regression worth capturing as a fixture.
|
|
54
|
+
|
|
55
|
+
**3. "Component-scope override fields look ignored."**
|
|
56
|
+
Component-scope wins over type-scope, but only for fields **the component override explicitly sets**. Fields it leaves out fall through to the type-scope value, then to the run-wide default. If you set `decomposedFormat: "yaml"` on a type and `strategy: "grouped-by-tag"` on the component, the component still gets `decomposedFormat: "yaml"` from the type override.
|
|
57
|
+
|
|
58
|
+
**4. "Reassembly removed my decomposed directory even though I didn't pass `postPurge`."**
|
|
59
|
+
That's by design for `multiLevel` types only. Multi-level recompose has to clean up inner-level directories so the next level can merge their reassembled XML. If you want the decomposed tree preserved for inspection, copy it before running `recompose`.
|
|
60
|
+
|
|
61
|
+
**5. "Decompose succeeded but my decomposed files all have hash names."**
|
|
62
|
+
There are two distinct causes; run the decompose under `RUST_LOG=warn` to tell them apart:
|
|
63
|
+
|
|
64
|
+
- **No `WARN` line.** Your `unique_id_elements` (or the rule's third part) didn't resolve to a non-empty value on those items. Check the source XML for the elements you listed — names are case-sensitive and live at the immediate child level of each repeating item. The plugin only walks one level deep when picking a UID.
|
|
65
|
+
- **A `WARN` line of the form `uniqueIdElements collision: <parentTag> id "X" matched N sibling elements`.** The configured key is too narrow — multiple siblings legitimately share the same value, so the collision detector falls back to per-element SHA-256 hashes for that group rather than overwrite. Add a tiebreaker to `unique_id_elements` (e.g. a compound like `name+recordType`) and re-decompose with `prePurge: true`.
|
|
66
|
+
|
|
47
67
|
## Bots (Agentforce and Einstein)
|
|
48
68
|
|
|
49
69
|
**Why this is hard.** Agentforce and Einstein bots both ship as `.bot-meta.xml`, but their internals diverge:
|
|
@@ -263,37 +283,17 @@ Always verify a new override before committing it:
|
|
|
263
283
|
git stash --include-untracked
|
|
264
284
|
|
|
265
285
|
# 2. Decompose with the new override.
|
|
266
|
-
sf decomposer decompose -
|
|
286
|
+
sf decomposer decompose -m "bot" --config
|
|
267
287
|
|
|
268
288
|
# 3. Recompose back from the decomposed tree.
|
|
269
|
-
sf decomposer recompose -
|
|
289
|
+
sf decomposer recompose -m "bot"
|
|
270
290
|
|
|
271
291
|
# 4. Check the round-trip didn't drift.
|
|
272
|
-
sf decomposer verify -
|
|
292
|
+
sf decomposer verify -m "bot" --config
|
|
273
293
|
```
|
|
274
294
|
|
|
275
295
|
`sf decomposer verify` is non-destructive: it decomposes into a temp dir, recomposes from the temp dir, and compares the result to your committed source. If anything drifts (content, missing file, sibling reorder) it tells you exactly which paths broke. Treat any drift as a blocker — fix the override (or fall back to the previous one) before committing.
|
|
276
296
|
|
|
277
|
-
## Common pitfalls
|
|
278
|
-
|
|
279
|
-
**1. "I added two `multiLevel` rules but only one survived."**
|
|
280
|
-
You probably ran two `decompose` invocations back-to-back, one rule each. Don't. The disassembler rewrites `.multi_level.json` on every run, so each call replaces the prior one. Pass every rule for a given component in **one** override entry, in array form.
|
|
281
|
-
|
|
282
|
-
**2. "My `multiLevel` rule is correct but recompose produces a smaller file."**
|
|
283
|
-
On `config-disassembler` Rust ≥ 0.5.0 / Node ≥ 1.3.0 this should not happen — sibling collisions are written to per-element SHA-256 shards and surfaced as a `WARN` (see pitfall #5), not silently overwritten. If you do see a shrunken recomposed file on a current build, treat it as a regression worth capturing as a fixture.
|
|
284
|
-
|
|
285
|
-
**3. "Component-scope override fields look ignored."**
|
|
286
|
-
Component-scope wins over type-scope, but only for fields **the component override explicitly sets**. Fields it leaves out fall through to the type-scope value, then to the run-wide default. If you set `decomposedFormat: "yaml"` on a type and `strategy: "grouped-by-tag"` on the component, the component still gets `decomposedFormat: "yaml"` from the type override.
|
|
287
|
-
|
|
288
|
-
**4. "Reassembly removed my decomposed directory even though I didn't pass `postPurge`."**
|
|
289
|
-
That's by design for `multiLevel` types only. Multi-level recompose has to clean up inner-level directories so the next level can merge their reassembled XML. If you want the decomposed tree preserved for inspection, copy it before running `recompose`.
|
|
290
|
-
|
|
291
|
-
**5. "Decompose succeeded but my decomposed files all have hash names."**
|
|
292
|
-
There are two distinct causes; run the decompose under `RUST_LOG=warn` to tell them apart:
|
|
293
|
-
|
|
294
|
-
- **No `WARN` line.** Your `unique_id_elements` (or the rule's third part) didn't resolve to a non-empty value on those items. Check the source XML for the elements you listed — names are case-sensitive and live at the immediate child level of each repeating item. The plugin only walks one level deep when picking a UID.
|
|
295
|
-
- **A `WARN` line of the form `uniqueIdElements collision: <parentTag> id "X" matched N sibling elements`.** The configured key is too narrow — multiple siblings legitimately share the same value, so the collision detector falls back to per-element SHA-256 hashes for that group rather than overwrite. Add a tiebreaker to `unique_id_elements` (e.g. a compound like `name+recordType`) and re-decompose with `prePurge: true`.
|
|
296
|
-
|
|
297
297
|
---
|
|
298
298
|
|
|
299
299
|
When in doubt: write the override, run `verify`, read the diff. Every recipe in this handbook was derived that way.
|