sf-decomposer 6.16.0 → 6.18.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 CHANGED
@@ -5,6 +5,26 @@
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.18.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.17.0...v6.18.0) (2026-05-05)
9
+
10
+
11
+ ### Features
12
+
13
+ * **decompose:** bump config-disassembler to 1.2.1 and use compound keys for app ([#433](https://github.com/mcarvin8/sf-decomposer/issues/433)) ([c087664](https://github.com/mcarvin8/sf-decomposer/commit/c087664a44d73116bc375333275cb6f722662013))
14
+ * **deps:** bump config-disassembler to 1.3.0 (sanitize + collision detection) ([#436](https://github.com/mcarvin8/sf-decomposer/issues/436)) ([d53878b](https://github.com/mcarvin8/sf-decomposer/commit/d53878b8c67b4ca42a35695b605b2c489bed5f6c))
15
+
16
+ ## [6.17.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.16.0...v6.17.0) (2026-05-04)
17
+
18
+
19
+ ### Features
20
+
21
+ * **decompose:** expand uniqueIdElements coverage for 11 metadata types ([#432](https://github.com/mcarvin8/sf-decomposer/issues/432)) ([7e8d73a](https://github.com/mcarvin8/sf-decomposer/commit/7e8d73a15fbcc860d1aff78067e5851703216c9a))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * **decompose:** bump config-disassembler to 1.1.3 and add approval/entitlement uniqueIdElements ([#430](https://github.com/mcarvin8/sf-decomposer/issues/430)) ([82b2458](https://github.com/mcarvin8/sf-decomposer/commit/82b2458a228e2a0a9ff5a7a49ad1fcc763fb0274))
27
+
8
28
  ## [6.16.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.15.1...v6.16.0) (2026-05-01)
9
29
 
10
30
 
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/LICENSE.md)
6
6
  [![Maintainability](https://qlty.sh/badges/8492c1c6-0f93-4d37-bfad-32fd3b788a2d/maintainability.svg)](https://qlty.sh/gh/mcarvin8/projects/sf-decomposer)
7
7
  [![codecov](https://codecov.io/gh/mcarvin8/sf-decomposer/graph/badge.svg?token=YFU52L4XM5)](https://codecov.io/gh/mcarvin8/sf-decomposer)
8
+ [![Performance](https://img.shields.io/badge/Performance-Dashboard-58a6ff)](https://mcarvin8.github.io/sf-decomposer/dev/bench/runtime/)
8
9
 
9
10
  A Salesforce CLI plugin that **decomposes** large metadata XML files into smaller, version-control–friendly files (XML, JSON, YAML, JSON5), and **recomposes** them back into deployment-ready metadata.
10
11
 
@@ -23,6 +23,48 @@ declare const _default: {
23
23
  loyaltyProgramSetup: {
24
24
  uniqueIdElements: string[];
25
25
  };
26
+ entitlementProcess: {
27
+ uniqueIdElements: string[];
28
+ };
29
+ approvalProcess: {
30
+ uniqueIdElements: string[];
31
+ };
32
+ quickAction: {
33
+ uniqueIdElements: string[];
34
+ };
35
+ md: {
36
+ uniqueIdElements: string[];
37
+ };
38
+ pathAssistant: {
39
+ uniqueIdElements: string[];
40
+ };
41
+ omniSupervisorConfig: {
42
+ uniqueIdElements: string[];
43
+ };
44
+ genAiPromptTemplate: {
45
+ uniqueIdElements: string[];
46
+ };
47
+ mlDomain: {
48
+ uniqueIdElements: string[];
49
+ };
50
+ liveChatAgentConfig: {
51
+ uniqueIdElements: string[];
52
+ };
53
+ liveChatButton: {
54
+ uniqueIdElements: string[];
55
+ };
56
+ duplicateRule: {
57
+ uniqueIdElements: string[];
58
+ };
59
+ queue: {
60
+ uniqueIdElements: string[];
61
+ };
62
+ reportType: {
63
+ uniqueIdElements: string[];
64
+ };
65
+ app: {
66
+ uniqueIdElements: string[];
67
+ };
26
68
  mutingpermissionset: {
27
69
  uniqueIdElements: string[];
28
70
  };
@@ -71,6 +71,106 @@ export default [
71
71
  loyaltyProgramSetup: {
72
72
  uniqueIdElements: ['processName'],
73
73
  },
74
+ entitlementProcess: {
75
+ // `<milestones>` items have no `<fullName>`/`<name>`; the canonical key
76
+ // is `<milestoneName>`. Without this, every milestone shard falls back
77
+ // to a SHA-256 hash filename.
78
+ uniqueIdElements: ['milestoneName'],
79
+ },
80
+ approvalProcess: {
81
+ // `<approvalStep>` already keys off `<name>` via the default list, but
82
+ // `<allowedSubmitters>` items only carry `<type>` (e.g. `creator`,
83
+ // `owner`, `queue`). Multiple submitters with the same `<type>` in one
84
+ // process will collide and fall back to SHA-256, which is acceptable
85
+ // (and rare in practice) compared to *every* allowedSubmitters shard
86
+ // hashing today.
87
+ uniqueIdElements: ['type'],
88
+ },
89
+ quickAction: {
90
+ // `<fieldOverrides>` and `<quickActionLayoutItems>` both key off
91
+ // `<field>`. Singleton wrappers like `<quickActionLayout>` and
92
+ // `<quickActionSendEmailOptions>` still hash (one stable hash per
93
+ // parent), which is correct and intentional.
94
+ uniqueIdElements: ['field'],
95
+ },
96
+ md: {
97
+ // `<values>` items inside a `<CustomMetadata>` record are keyed by
98
+ // `<field>`. Each customMetadata file holds 1..N values for distinct
99
+ // fields, so `<field>` is unique per shard.
100
+ uniqueIdElements: ['field'],
101
+ },
102
+ pathAssistant: {
103
+ // `<pathAssistantSteps>` items use `<picklistValueName>` (a stage
104
+ // value like "Planning", "Pre-Live Review") as their natural key.
105
+ uniqueIdElements: ['picklistValueName'],
106
+ },
107
+ omniSupervisorConfig: {
108
+ // Six sibling repeating elements: `<omniSupervisorConfigUser>` /
109
+ // `<...Group>` / `<...Queue>` / `<...Profile>` / `<...Skill>` /
110
+ // `<...Action>`. Each item carries exactly one of these inner-name
111
+ // fields, and `find_id_in_subtree` picks whichever one is present.
112
+ uniqueIdElements: ['user', 'group', 'queue', 'profile', 'skill', 'actionName'],
113
+ },
114
+ genAiPromptTemplate: {
115
+ // `<templateVersions>` items carry a unique `<versionIdentifier>` per
116
+ // version. The trailing `_<n>` makes it filesystem-safe.
117
+ uniqueIdElements: ['versionIdentifier'],
118
+ },
119
+ mlDomain: {
120
+ // `<mlIntents>` items use `<developerName>` as their canonical key.
121
+ uniqueIdElements: ['developerName'],
122
+ },
123
+ liveChatAgentConfig: {
124
+ // `<transferableButtons>` items carry `<button>`, `<supervisorSkills>`
125
+ // items carry `<skill>`. `<assignments>` items wrap heterogeneous
126
+ // user/group payloads with no single keyable field, so they continue
127
+ // to hash (stable per content).
128
+ uniqueIdElements: ['button', 'skill'],
129
+ },
130
+ liveChatButton: {
131
+ // `<skills>` items use `<skill>`; `<deployments>` items use
132
+ // `<deployment>`.
133
+ uniqueIdElements: ['skill', 'deployment'],
134
+ },
135
+ duplicateRule: {
136
+ // `<duplicateRuleMatchRules>` items carry `<matchingRule>`. Each
137
+ // match rule appears once per duplicate rule, so the field is unique
138
+ // within the parent.
139
+ uniqueIdElements: ['matchingRule'],
140
+ },
141
+ queue: {
142
+ // `<queueSobject>` items are keyed by `<sobjectType>` (e.g. `Case`,
143
+ // `Lead`). Each sobject appears at most once per queue.
144
+ uniqueIdElements: ['sobjectType'],
145
+ },
146
+ reportType: {
147
+ // `<sections>` items use `<masterLabel>` as their natural key. Same
148
+ // pattern as `globalValueSetTranslation`/`standardValueSetTranslation`.
149
+ uniqueIdElements: ['masterLabel'],
150
+ },
151
+ app: {
152
+ // CustomApplication's `<profileActionOverrides>` and `<actionOverrides>`
153
+ // have a *compound* natural unique key: any single field (e.g. just
154
+ // `<actionName>`) collides for hundreds of siblings sharing
155
+ // `<actionName>View</actionName>`, silently merging on disassembly.
156
+ // Compound keys (config-disassembler >= 0.4.5) join the resolved values
157
+ // with `__` to form a stable, readable, collision-free filename.
158
+ //
159
+ // Fallback chain, widest first:
160
+ // 1. profileActionOverrides with recordType
161
+ // 2. profileActionOverrides without recordType
162
+ // 3. actionOverrides with recordType (no profile)
163
+ // 4. actionOverrides without recordType (no profile)
164
+ // Items missing `pageOrSobjectType` or `formFactor` (very rare) fall
165
+ // through to the SHA-256 outer-element hash, which is correct since
166
+ // we can't safely name them without those keys.
167
+ uniqueIdElements: [
168
+ 'actionName+pageOrSobjectType+formFactor+profile+recordType',
169
+ 'actionName+pageOrSobjectType+formFactor+profile',
170
+ 'actionName+pageOrSobjectType+formFactor+recordType',
171
+ 'actionName+pageOrSobjectType+formFactor',
172
+ ],
173
+ },
74
174
  mutingpermissionset: {
75
175
  uniqueIdElements: [
76
176
  'application',
@@ -1 +1 @@
1
- {"version":3,"file":"uniqueIdElements.js","sourceRoot":"","sources":["../../src/metadata/uniqueIdElements.ts"],"names":[],"mappings":"AAAA,eAAe;IACb;QACE,OAAO,EAAE;YACP,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,cAAc;gBACd,mBAAmB;gBACnB,QAAQ;gBACR,cAAc;gBACd,cAAc;gBACd,WAAW;aACZ;SACF;QACD,aAAa,EAAE;YACb,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,WAAW;gBACX,6BAA6B;gBAC7B,uBAAuB;aACxB;SACF;QACD,IAAI,EAAE;YACJ,gBAAgB,EAAE;gBAChB,WAAW;gBACX,QAAQ;gBACR,OAAO;gBACP,QAAQ;gBACR,YAAY;gBACZ,iBAAiB;gBACjB,mBAAmB;gBACnB,YAAY;gBACZ,YAAY;aACb;SACF;QACD,yBAAyB,EAAE;YACzB,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,2BAA2B,EAAE;YAC3B,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,GAAG,EAAE;YACH,gBAAgB,EAAE;gBAChB,eAAe;gBACf,gBAAgB;gBAChB,sBAAsB;gBACtB,eAAe;gBACf,iBAAiB;gBACjB,QAAQ;gBACR,gBAAgB;aACjB;SACF;QACD,qBAAqB,EAAE;YACrB,gBAAgB,EAAE,CAAC,SAAS,CAAC;SAC9B;QACD,mBAAmB,EAAE;YACnB,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,mBAAmB,EAAE;YACnB,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,WAAW;gBACX,6BAA6B;gBAC7B,uBAAuB;aACxB;SACF;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"uniqueIdElements.js","sourceRoot":"","sources":["../../src/metadata/uniqueIdElements.ts"],"names":[],"mappings":"AAAA,eAAe;IACb;QACE,OAAO,EAAE;YACP,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,cAAc;gBACd,mBAAmB;gBACnB,QAAQ;gBACR,cAAc;gBACd,cAAc;gBACd,WAAW;aACZ;SACF;QACD,aAAa,EAAE;YACb,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,WAAW;gBACX,6BAA6B;gBAC7B,uBAAuB;aACxB;SACF;QACD,IAAI,EAAE;YACJ,gBAAgB,EAAE;gBAChB,WAAW;gBACX,QAAQ;gBACR,OAAO;gBACP,QAAQ;gBACR,YAAY;gBACZ,iBAAiB;gBACjB,mBAAmB;gBACnB,YAAY;gBACZ,YAAY;aACb;SACF;QACD,yBAAyB,EAAE;YACzB,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,2BAA2B,EAAE;YAC3B,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,GAAG,EAAE;YACH,gBAAgB,EAAE;gBAChB,eAAe;gBACf,gBAAgB;gBAChB,sBAAsB;gBACtB,eAAe;gBACf,iBAAiB;gBACjB,QAAQ;gBACR,gBAAgB;aACjB;SACF;QACD,qBAAqB,EAAE;YACrB,gBAAgB,EAAE,CAAC,SAAS,CAAC;SAC9B;QACD,mBAAmB,EAAE;YACnB,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,kBAAkB,EAAE;YAClB,wEAAwE;YACxE,uEAAuE;YACvE,8BAA8B;YAC9B,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;QACD,eAAe,EAAE;YACf,uEAAuE;YACvE,mEAAmE;YACnE,uEAAuE;YACvE,qEAAqE;YACrE,qEAAqE;YACrE,iBAAiB;YACjB,gBAAgB,EAAE,CAAC,MAAM,CAAC;SAC3B;QACD,WAAW,EAAE;YACX,iEAAiE;YACjE,+DAA+D;YAC/D,kEAAkE;YAClE,6CAA6C;YAC7C,gBAAgB,EAAE,CAAC,OAAO,CAAC;SAC5B;QACD,EAAE,EAAE;YACF,mEAAmE;YACnE,qEAAqE;YACrE,4CAA4C;YAC5C,gBAAgB,EAAE,CAAC,OAAO,CAAC;SAC5B;QACD,aAAa,EAAE;YACb,kEAAkE;YAClE,kEAAkE;YAClE,gBAAgB,EAAE,CAAC,mBAAmB,CAAC;SACxC;QACD,oBAAoB,EAAE;YACpB,iEAAiE;YACjE,gEAAgE;YAChE,mEAAmE;YACnE,mEAAmE;YACnE,gBAAgB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC;SAC/E;QACD,mBAAmB,EAAE;YACnB,sEAAsE;YACtE,yDAAyD;YACzD,gBAAgB,EAAE,CAAC,mBAAmB,CAAC;SACxC;QACD,QAAQ,EAAE;YACR,oEAAoE;YACpE,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;QACD,mBAAmB,EAAE;YACnB,uEAAuE;YACvE,kEAAkE;YAClE,qEAAqE;YACrE,gCAAgC;YAChC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;SACtC;QACD,cAAc,EAAE;YACd,4DAA4D;YAC5D,kBAAkB;YAClB,gBAAgB,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;SAC1C;QACD,aAAa,EAAE;YACb,iEAAiE;YACjE,qEAAqE;YACrE,qBAAqB;YACrB,gBAAgB,EAAE,CAAC,cAAc,CAAC;SACnC;QACD,KAAK,EAAE;YACL,oEAAoE;YACpE,wDAAwD;YACxD,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,UAAU,EAAE;YACV,oEAAoE;YACpE,wEAAwE;YACxE,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAClC;QACD,GAAG,EAAE;YACH,yEAAyE;YACzE,oEAAoE;YACpE,4DAA4D;YAC5D,oEAAoE;YACpE,wEAAwE;YACxE,iEAAiE;YACjE,EAAE;YACF,gCAAgC;YAChC,8CAA8C;YAC9C,iDAAiD;YACjD,oDAAoD;YACpD,uDAAuD;YACvD,qEAAqE;YACrE,oEAAoE;YACpE,gDAAgD;YAChD,gBAAgB,EAAE;gBAChB,4DAA4D;gBAC5D,iDAAiD;gBACjD,oDAAoD;gBACpD,yCAAyC;aAC1C;SACF;QACD,mBAAmB,EAAE;YACnB,gBAAgB,EAAE;gBAChB,aAAa;gBACb,WAAW;gBACX,oBAAoB;gBACpB,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,YAAY;gBACZ,KAAK;gBACL,OAAO;gBACP,WAAW;gBACX,6BAA6B;gBAC7B,uBAAuB;aACxB;SACF;KACF;CACF,CAAC"}
@@ -342,5 +342,5 @@
342
342
  ]
343
343
  }
344
344
  },
345
- "version": "6.16.0"
345
+ "version": "6.18.0"
346
346
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "sf-decomposer",
3
3
  "description": "Split large Salesforce metadata files into version-control-friendly pieces and rebuild deployment-ready files.",
4
- "version": "6.16.0",
4
+ "version": "6.18.0",
5
5
  "dependencies": {
6
6
  "@oclif/core": "^4",
7
7
  "@salesforce/core": "^8.26.3",
8
8
  "@salesforce/sf-plugins-core": "^12.2.6",
9
9
  "@salesforce/source-deploy-retrieve": "^12.35.0",
10
- "config-disassembler": "^1.1.2",
10
+ "config-disassembler": "^1.3.0",
11
11
  "fast-xml-parser": "^5.7.2",
12
12
  "p-limit": "^7.3.0"
13
13
  },
@@ -95,6 +95,9 @@
95
95
  "test:only": "wireit",
96
96
  "test:perf": "vitest run --config ./vitest.perf.config.ts",
97
97
  "test:perf:gen": "node --import ts-node/esm scripts/gen-perf-fixtures.ts",
98
+ "audit": "node --loader ts-node/esm --no-warnings=ExperimentalWarning scripts/audit/audit.ts",
99
+ "audit:sweep": "node --loader ts-node/esm --no-warnings=ExperimentalWarning scripts/audit/sweep.ts",
100
+ "audit:roundtrip": "node --loader ts-node/esm --no-warnings=ExperimentalWarning scripts/audit/roundtrip.ts",
98
101
  "version": "oclif readme"
99
102
  },
100
103
  "publishConfig": {