sf-decomposer 5.8.0 → 5.9.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,20 @@
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
+ ## [5.9.0](https://github.com/mcarvin8/sf-decomposer/compare/v5.8.1...v5.9.0) (2025-04-22)
9
+
10
+
11
+ ### Features
12
+
13
+ * provide further decomposition on perm sets with grouped by tag strategy ([e5f28ad](https://github.com/mcarvin8/sf-decomposer/commit/e5f28ade9ec96d49b5dd0b4235b83e2d21546bbc))
14
+
15
+ ## [5.8.1](https://github.com/mcarvin8/sf-decomposer/compare/v5.8.0...v5.8.1) (2025-04-18)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * add strategy to decompose hook ([86e6c8d](https://github.com/mcarvin8/sf-decomposer/commit/86e6c8daa11e9c934427e5a98627ebba79a6e47c))
21
+
8
22
  ## [5.8.0](https://github.com/mcarvin8/sf-decomposer/compare/v5.7.2...v5.8.0) (2025-04-18)
9
23
 
10
24
 
package/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
  - [`sf decomposer decompose`](#sf-decomposer-decompose)
13
13
  - [`sf decomposer recompose`](#sf-decomposer-recompose)
14
14
  - [Decompose Structure](#decompose-structure)
15
+ - [Additional Permission Set Decomposition](#additional-permission-set-decomposition)
15
16
  - [Supported Metadata](#supported-metadata)
16
17
  - [Exceptions](#exceptions)
17
18
  - [Troubleshooting](#troubleshooting)
@@ -71,6 +72,7 @@ Salesforce's built-in decomposition has limitations. `sf-decomposer` offers more
71
72
  - `unique-id` (default): disassembles each nested element into its own uniquely named file based on XML content or hash.
72
73
  - `grouped-by-tag`: groups all nested elements by tag into a single file per tag (e.g., all `<fieldPermissions>` in a permission set into `fieldPermissions.xml`).
73
74
  - Both strategies decompose leaf elements into the same file named after the original XML.
75
+ - Additionally opt into further decomposition on permisison sets by using the `grouped-by-tag` strategy with the `--decompose-nested-permissions` flag.
74
76
  - **Fully Decomposes Metadata** – Allow complete decomposition for types that Salesforce only partially decomposes (e.g., `decomposePermissionSetBeta2`).
75
77
  - **Consistent Sorting** – Keeps elements in a predictable order to reduce unnecessary version control noise.
76
78
  > DISCLAIMER: If you use "toml" or "ini" format for decomposed files, the element sorting will vary compared to the other formats
@@ -96,7 +98,7 @@ Decomposes the original metadata files in all local package directories into sma
96
98
 
97
99
  ```
98
100
  USAGE
99
- $ sf decomposer decompose -m <value> -f <value> -i <value> -s <value> [--prepurge --postpurge --debug --json]
101
+ $ sf decomposer decompose -m <value> -f <value> -i <value> -s <value> [--prepurge --postpurge --debug -p --json]
100
102
 
101
103
  FLAGS
102
104
  -m, --metadata-type=<value> The metadata suffix to process, such as 'flow', 'labels', etc.
@@ -116,6 +118,8 @@ FLAGS
116
118
  [default: false]
117
119
  --debug Log debugging results to a text file (disassemble.log).
118
120
  [default: false]
121
+ -p, --decompose-nested-permissions If strategy is "grouped-by-tag", opt into further decomposition
122
+ on object and field permissions on permission sets.
119
123
 
120
124
  GLOBAL FLAGS
121
125
  --json Format output as json.
@@ -206,6 +210,12 @@ Custom labels decomposed under the `unique-id` strategy will look like such, eac
206
210
 
207
211
  ![Decomposed Custom Labels](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/.github/images/decomposed-labels.png)<br>
208
212
 
213
+ ### Additional Permission Set Decomposition
214
+
215
+ When using the `grouped-by-tag` strategy, you can opt into additional decomposition on `<objectPermissions>` and `<fieldPermissions>` on permission sets by supplying the `--decompose-nested-permissions` flag.
216
+
217
+ When you run `sf decompose decompose -m "permissionset" -s "grouped-by-tag" -p`, it will decompose all `<objectPermissions>` into their own files in a sub-directory, i.e. `permissionsets\HR_Admin\objectPermissions\Account.objectPermissions-meta.xml` and decompose `<fieldPermisisons>` into separate files in a sub-directory for each Object, i.e. `permissionsets\HR_Admin\fieldPermissions\Account.fieldPermissions.xml`. This is similar to the `decomposePermissionSetBeta2` behavior provided natively by Salesforce.
218
+
209
219
  ## Supported Metadata
210
220
 
211
221
  All parent metadata types imported from this plugin's version of `@salesforce/source-deploy-retrieve` (SDR) toolkit are supported except for certain types.
@@ -256,6 +266,12 @@ To add debugging to the log, provide the `--debug` flag to the decompose or reco
256
266
  [2024-03-30T14:28:37.959] [DEBUG] default - Created disassembled file: mock\no-nested-elements\HR_Admin\HR_Admin.permissionset-meta.xml
257
267
  ```
258
268
 
269
+ If a file only contains leaf elements, the decomposer has nothing to decompose so it will print this warning and skip processing the file:
270
+
271
+ ```
272
+ Warning: The XML file force-app\main\default\permissionsets\view_of_projects_tab_on_opportunity.permissionset-meta.xml only has leaf elements. This file will not be disassembled.
273
+ ```
274
+
259
275
  Custom labels can only be decomposed via the `unique-id` strategy. If the other one is provided, it will print this warning and skip to the next metadata entry.
260
276
 
261
277
  ```
@@ -270,13 +286,15 @@ Warning: You cannot decompose custom labels using the grouped-by-tag strategy. P
270
286
 
271
287
  You can copy and update the sample [.sfdecomposer.config.json](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/samples/.sfdecomposer.config.json).
272
288
 
273
- | Configuration Option | Required | Description |
274
- | -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
275
- | `metadataSuffixes` | Yes | Comma-separated string of metadata suffixes to decompose and recompose based on the CLI command. |
276
- | `ignorePackageDirectories` | No | Comma-separated string of package directories to ignore. |
277
- | `prePurge` | No | `true` or `false`. If `true`, deletes existing decomposed files before decomposing. Defaults to `false`. |
278
- | `postPurge` | No | `true` or `false`. If `true`, deletes the retrieval file after decomposing or deletes decomposed files after recomposing. Defaults to `false`. |
279
- | `decomposedFormat` | No | Format of decomposed files: `xml`, `json`, `json5`, `toml`, `ini`, or `yaml`. Defaults to `xml`. |
289
+ | Configuration Option | Required | Description |
290
+ | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
291
+ | `metadataSuffixes` | Yes | Comma-separated string of metadata suffixes to decompose and recompose based on the CLI command. |
292
+ | `ignorePackageDirectories` | No | Comma-separated string of package directories to ignore. |
293
+ | `prePurge` | No | `true` or `false`. If `true`, deletes existing decomposed files before decomposing. Defaults to `false`. |
294
+ | `postPurge` | No | `true` or `false`. If `true`, deletes the retrieval file after decomposing or deletes decomposed files after recomposing. Defaults to `false`. |
295
+ | `decomposedFormat` | No | Format of decomposed files: `xml`, `json`, `json5`, `toml`, `ini`, or `yaml`. Defaults to `xml`. |
296
+ | `strategy` | No | Strategy for decomposing the files: `unique-id` or `grouped-by-tag`. Defaults to `unique-id`. |
297
+ | `decomposeNestedPermissions` | No | If strategy is `grouped-by-tag` and this is set to `true`, optionally opt into decomposing permission sets further by object and field permissions. |
280
298
 
281
299
  If `.sfdecomposer.config.json` is found, the hooks will run:
282
300
 
@@ -12,6 +12,7 @@ export default class DecomposerDecompose extends SfCommand<DecomposerResult> {
12
12
  format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
13
  'ignore-package-directory': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
14
  strategy: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ 'decompose-nested-permissions': import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
16
  };
16
17
  run(): Promise<DecomposerResult>;
17
18
  }
@@ -56,6 +56,12 @@ export default class DecomposerDecompose extends SfCommand {
56
56
  default: 'unique-id',
57
57
  options: DECOMPOSED_STRATEGIES,
58
58
  }),
59
+ 'decompose-nested-permissions': Flags.boolean({
60
+ summary: messages.getMessage('flags.decompose-nested-permissions.summary'),
61
+ char: 'p',
62
+ required: false,
63
+ default: false,
64
+ }),
59
65
  };
60
66
  async run() {
61
67
  const { flags } = await this.parse(DecomposerDecompose);
@@ -66,6 +72,7 @@ export default class DecomposerDecompose extends SfCommand {
66
72
  const format = flags['format'];
67
73
  const ignoreDirs = flags['ignore-package-directory'];
68
74
  const strategy = flags['strategy'];
75
+ const decomposeNestedPerms = flags['decompose-nested-permissions'];
69
76
  for (const metadataType of metadataTypes) {
70
77
  const { metaAttributes, ignorePath } = await getRegistryValuesBySuffix(metadataType, 'decompose', ignoreDirs);
71
78
  if (metadataType === 'labels' && strategy === 'grouped-by-tag') {
@@ -73,7 +80,7 @@ export default class DecomposerDecompose extends SfCommand {
73
80
  continue;
74
81
  }
75
82
  const currentLogFile = await readOriginalLogFile(LOG_FILE);
76
- await decomposeFileHandler(metaAttributes, prepurge, postpurge, debug, format, ignorePath, strategy);
83
+ await decomposeFileHandler(metaAttributes, prepurge, postpurge, debug, format, ignorePath, strategy, decomposeNestedPerms);
77
84
  const decomposeErrors = await checkLogForErrors(LOG_FILE, currentLogFile);
78
85
  if (decomposeErrors.length > 0) {
79
86
  decomposeErrors.forEach((error) => {
@@ -1 +1 @@
1
- {"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/decompose.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAG5F,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAAC;AAEhF,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,SAA2B;IACnE,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAC3D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACtD,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACf,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;YACvB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,yBAAyB,CAAC;YACvD,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACf,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;YACnD,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACf,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;YACpD,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,qBAAqB;SAC/B,CAAC;QACF,0BAA0B,EAAE,KAAK,CAAC,SAAS,CAAC;YAC1C,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wCAAwC,CAAC;YACtE,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YACrB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACtD,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,qBAAqB;SAC/B,CAAC;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QACnC,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;YACzC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;YAE9G,IAAI,YAAY,KAAK,QAAQ,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;gBAC/D,IAAI,CAAC,IAAI,CACP,0HAA0H,CAC3H,CAAC;gBACF,SAAS;YACX,CAAC;YACD,MAAM,cAAc,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAC3D,MAAM,oBAAoB,CAAC,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YACrG,MAAM,eAAe,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAC1E,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,eAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;oBAChC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,kEAAkE,YAAY,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,aAAa;SACxB,CAAC;IACJ,CAAC"}
1
+ {"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/decompose.ts"],"names":[],"mappings":"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"}
@@ -9,3 +9,4 @@ export declare const WORKFLOW_SUFFIX_MAPPING: {
9
9
  [key: string]: string;
10
10
  };
11
11
  export declare const HOOK_CONFIG_JSON = ".sfdecomposer.config.json";
12
+ export declare const XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
@@ -17,4 +17,5 @@ export const WORKFLOW_SUFFIX_MAPPING = {
17
17
  'send-meta': 'workflowSend-meta',
18
18
  };
19
19
  export const HOOK_CONFIG_JSON = '.sfdecomposer.config.json';
20
+ export const XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>';
20
21
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/helpers/constants.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAW,eAAe,CAAC;AAClE,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAC/F,MAAM,CAAC,MAAM,qBAAqB,GAAa,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AACjD,MAAM,CAAC,MAAM,uBAAuB,GAA8B;IAChE,aAAa,EAAE,oBAAoB;IACnC,mBAAmB,EAAE,0BAA0B;IAC/C,kBAAkB,EAAE,yBAAyB;IAC7C,yBAAyB,EAAE,+BAA+B;IAC1D,uBAAuB,EAAE,8BAA8B;IACvD,YAAY,EAAE,mBAAmB;IACjC,YAAY,EAAE,mBAAmB;IACjC,WAAW,EAAE,mBAAmB;CACjC,CAAC;AACF,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/helpers/constants.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAW,eAAe,CAAC;AAClE,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAC/F,MAAM,CAAC,MAAM,qBAAqB,GAAa,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AACjD,MAAM,CAAC,MAAM,uBAAuB,GAA8B;IAChE,aAAa,EAAE,oBAAoB;IACnC,mBAAmB,EAAE,0BAA0B;IAC/C,kBAAkB,EAAE,yBAAyB;IAC7C,yBAAyB,EAAE,+BAA+B;IAC1D,uBAAuB,EAAE,8BAA8B;IACvD,YAAY,EAAE,mBAAmB;IACjC,YAAY,EAAE,mBAAmB;IACjC,WAAW,EAAE,mBAAmB;CACjC,CAAC;AACF,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,CAAC,MAAM,eAAe,GAAG,wCAAwC,CAAC"}
@@ -9,6 +9,8 @@ export type ConfigFile = {
9
9
  postPurge: boolean;
10
10
  decomposedFormat: string;
11
11
  ignorePackageDirectories: string;
12
+ strategy: string;
13
+ decomposeNestedPermissions: boolean;
12
14
  };
13
15
  export type SfdxProject = {
14
16
  packageDirectories: Array<{
@@ -34,3 +36,8 @@ export type PostRetrieveHookOptions = {
34
36
  result?: ScopedPostRetrieve;
35
37
  config: Config;
36
38
  };
39
+ export type FieldPermission = {
40
+ editable?: boolean;
41
+ readable?: boolean;
42
+ field: string;
43
+ };
@@ -26,6 +26,8 @@ export const scopedPostRetrieve = async function (options) {
26
26
  const prepurge = configFile.prePurge || false;
27
27
  const postpurge = configFile.postPurge || false;
28
28
  const ignorePackageDirs = configFile.ignorePackageDirectories || '';
29
+ const strategy = configFile.strategy || 'unique-id';
30
+ const decomposeNestedPermissions = configFile.decomposeNestedPermissions || false;
29
31
  if (metadataTypes.trim() === '.') {
30
32
  return;
31
33
  }
@@ -52,6 +54,11 @@ export const scopedPostRetrieve = async function (options) {
52
54
  if (postpurge) {
53
55
  commandArgs.push('--postpurge');
54
56
  }
57
+ if (decomposeNestedPermissions) {
58
+ commandArgs.push('--decompose-nested-permissions');
59
+ }
60
+ commandArgs.push('--strategy');
61
+ commandArgs.push(strategy);
55
62
  await DecomposerDecompose.run(commandArgs);
56
63
  };
57
64
  //# sourceMappingURL=scopedPostRetrieve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scopedPostRetrieve.js","sourceRoot":"","sources":["../../src/hooks/scopedPostRetrieve.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,mBAAmB,MAAM,qCAAqC,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI3D,MAAM,CAAC,MAAM,kBAAkB,GAAiB,KAAK,WAAW,OAAO;IACrE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO;IACT,CAAC;IACD,IAAI,UAAsB,CAAC;IAC3B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,UAAU,GAAW,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/D,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAe,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAW,UAAU,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACjE,MAAM,MAAM,GAAW,UAAU,CAAC,gBAAgB,IAAI,KAAK,CAAC;IAC5D,MAAM,QAAQ,GAAY,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC;IACvD,MAAM,SAAS,GAAY,UAAU,CAAC,SAAS,IAAI,KAAK,CAAC;IACzD,MAAM,iBAAiB,GAAW,UAAU,CAAC,wBAAwB,IAAI,EAAE,CAAC;IAE5E,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,kBAAkB,GAAa,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE9D,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,YAAY,IAAI,kBAAkB,EAAE,CAAC;QAC9C,MAAM,qBAAqB,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7D,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACpC,WAAW,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACpC,MAAM,qBAAqB,GAAa,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrE,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;YACzC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5C,WAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC/C,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,QAAQ,EAAE,CAAC;QACb,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC"}
1
+ {"version":3,"file":"scopedPostRetrieve.js","sourceRoot":"","sources":["../../src/hooks/scopedPostRetrieve.ts"],"names":[],"mappings":"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"}
@@ -4,4 +4,4 @@ export declare function decomposeFileHandler(metaAttributes: {
4
4
  strictDirectoryName: boolean;
5
5
  folderType: string;
6
6
  uniqueIdElements: string;
7
- }, prepurge: boolean, postpurge: boolean, debug: boolean, format: string, ignorePath: string, strategy: string): Promise<void>;
7
+ }, prepurge: boolean, postpurge: boolean, debug: boolean, format: string, ignorePath: string, strategy: string, decomposeNestedPerms: boolean): Promise<void>;
@@ -1,17 +1,21 @@
1
1
  'use strict';
2
2
  /* eslint-disable no-await-in-loop */
3
- import { resolve, relative, join } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ import { resolve, relative, join, dirname } from 'node:path';
4
5
  import { readdir, stat, rm, rename } from 'node:fs/promises';
5
6
  import { DisassembleXMLFileHandler, setLogLevel } from 'xml-disassembler';
6
7
  import { CUSTOM_LABELS_FILE, WORKFLOW_SUFFIX_MAPPING } from '../helpers/constants.js';
7
8
  import { moveFiles } from './moveFiles.js';
8
- export async function decomposeFileHandler(metaAttributes, prepurge, postpurge, debug, format, ignorePath, strategy) {
9
+ import { disassembleAndGroupFieldPermissions } from './disassembleAndGroupFieldPermissions.js';
10
+ import { flattenNestedObjectPermissions } from './flattenNestedObjectPermissions.js';
11
+ import { transformAndCleanup } from './transformers.js';
12
+ export async function decomposeFileHandler(metaAttributes, prepurge, postpurge, debug, format, ignorePath, strategy, decomposeNestedPerms) {
9
13
  const { metadataPaths, metaSuffix, strictDirectoryName, folderType, uniqueIdElements } = metaAttributes;
10
14
  if (debug)
11
15
  setLogLevel('debug');
12
16
  for (const metadataPath of metadataPaths) {
13
17
  if (strictDirectoryName || folderType) {
14
- await subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy);
18
+ await subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
15
19
  }
16
20
  else if (metaSuffix === 'labels') {
17
21
  // do not use the prePurge flag in the xml-disassembler package for labels due to file moving
@@ -19,29 +23,72 @@ export async function decomposeFileHandler(metaAttributes, prepurge, postpurge,
19
23
  await prePurgeLabels(metadataPath);
20
24
  const absoluteLabelFilePath = resolve(metadataPath, CUSTOM_LABELS_FILE);
21
25
  const relativeLabelFilePath = relative(process.cwd(), absoluteLabelFilePath);
22
- await disassembleHandler(relativeLabelFilePath, uniqueIdElements, false, postpurge, format, ignorePath, strategy);
26
+ await disassembleHandler(relativeLabelFilePath, uniqueIdElements, false, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
23
27
  // move labels from the directory they are created in
24
28
  await moveAndRenameLabels(metadataPath);
25
29
  }
26
30
  else {
27
- await disassembleHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy);
31
+ await disassembleHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
28
32
  }
29
33
  if (metaSuffix === 'workflow') {
30
34
  await renameWorkflows(metadataPath);
31
35
  }
32
36
  }
33
37
  }
34
- async function disassembleHandler(filePath, uniqueIdElements, prePurge, postPurge, format, ignorePath, strategy) {
38
+ async function disassembleHandler(filePath, uniqueIdElements, prePurge, postPurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms) {
35
39
  const handler = new DisassembleXMLFileHandler();
40
+ let decomposeFormat;
41
+ let decomposePostPurge;
42
+ if (decomposeNestedPerms && metaSuffix === 'permissionset' && strategy === 'grouped-by-tag') {
43
+ decomposeFormat = 'xml';
44
+ decomposePostPurge = false;
45
+ }
46
+ else {
47
+ decomposeFormat = format;
48
+ decomposePostPurge = postPurge;
49
+ }
36
50
  await handler.disassemble({
37
51
  filePath,
38
52
  uniqueIdElements,
39
53
  prePurge,
40
- postPurge,
54
+ postPurge: decomposePostPurge,
41
55
  ignorePath,
42
- format,
56
+ format: decomposeFormat,
43
57
  strategy,
44
58
  });
59
+ // If permission set, disassemble any objectSettings.xml found recursively
60
+ if (decomposeNestedPerms && metaSuffix === 'permissionset' && strategy === 'grouped-by-tag') {
61
+ const disassembledDir = filePath.replace(/\.xml$/, '');
62
+ const recursivelyDisassembleObjectSettings = async (dir) => {
63
+ const entries = await readdir(dir, { withFileTypes: true });
64
+ for (const entry of entries) {
65
+ const fullPath = join(dir, entry.name);
66
+ if (entry.isDirectory()) {
67
+ await recursivelyDisassembleObjectSettings(fullPath);
68
+ }
69
+ else if (entry.isFile() && entry.name === 'objectPermissions.xml') {
70
+ await handler.disassemble({
71
+ filePath: fullPath,
72
+ uniqueIdElements,
73
+ prePurge: false,
74
+ postPurge: true,
75
+ format: 'xml',
76
+ strategy: 'unique-id',
77
+ });
78
+ await flattenNestedObjectPermissions(dirname(fullPath), format);
79
+ }
80
+ else if (entry.isFile() && entry.name === 'fieldPermissions.xml') {
81
+ await disassembleAndGroupFieldPermissions(fullPath, format);
82
+ }
83
+ else if (entry.isFile() && dirname(fullPath) !== filePath && fullPath.endsWith('.xml')) {
84
+ await transformAndCleanup(fullPath, format);
85
+ }
86
+ }
87
+ };
88
+ if (existsSync(disassembledDir)) {
89
+ await recursivelyDisassembleObjectSettings(disassembledDir);
90
+ }
91
+ }
45
92
  }
46
93
  async function prePurgeLabels(metadataPath) {
47
94
  const subFiles = await readdir(metadataPath);
@@ -67,12 +114,12 @@ async function moveAndRenameLabels(metadataPath) {
67
114
  await moveFiles(sourceDirectory, destinationDirectory, () => true);
68
115
  await rm(join(metadataPath, 'CustomLabels'), { recursive: true });
69
116
  }
70
- async function subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy) {
117
+ async function subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms) {
71
118
  const subFiles = await readdir(metadataPath);
72
119
  for (const subFile of subFiles) {
73
120
  const subFilePath = join(metadataPath, subFile);
74
121
  if ((await stat(subFilePath)).isDirectory()) {
75
- await disassembleHandler(subFilePath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy);
122
+ await disassembleHandler(subFilePath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
76
123
  }
77
124
  }
78
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decomposeFileHandler.js","sourceRoot":"","sources":["../../src/service/decomposeFileHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decomposeFileHandler.js","sourceRoot":"","sources":["../../src/service/decomposeFileHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function disassembleAndGroupFieldPermissions(filePath: string, format: string): Promise<void>;
@@ -0,0 +1,44 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ import { writeFile, rm, mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { buildXMLString, parseXML } from 'xml-disassembler';
5
+ import { XML_DECLARATION } from '../helpers/constants.js';
6
+ import { transformAndCleanup } from './transformers.js';
7
+ export async function disassembleAndGroupFieldPermissions(filePath, format) {
8
+ const parsed = await parseXML(filePath);
9
+ const fieldPermissions = parsed?.PermissionSet?.fieldPermissions;
10
+ if (!fieldPermissions || !Array.isArray(fieldPermissions)) {
11
+ return;
12
+ }
13
+ const groupedByObject = {};
14
+ for (const perm of fieldPermissions) {
15
+ const fieldValue = perm?.field;
16
+ if (typeof fieldValue !== 'string')
17
+ continue;
18
+ const objectName = fieldValue.split('.')[0];
19
+ if (!groupedByObject[objectName]) {
20
+ groupedByObject[objectName] = [];
21
+ }
22
+ groupedByObject[objectName].push(perm);
23
+ }
24
+ const outputDir = filePath.replace(/\.xml$/, '');
25
+ await mkdir(outputDir, { recursive: true });
26
+ for (const [objectName, perms] of Object.entries(groupedByObject)) {
27
+ const groupedElement = {
28
+ PermissionSet: {
29
+ '@_xmlns': 'http://soap.sforce.com/2006/04/metadata',
30
+ fieldPermissions: perms.map((perm) => ({
31
+ editable: String(perm.editable ?? 'false'),
32
+ readable: String(perm.readable ?? 'false'),
33
+ field: perm.field,
34
+ })),
35
+ },
36
+ };
37
+ const xmlString = buildXMLString(groupedElement, 0);
38
+ const outPath = join(outputDir, `${objectName}.fieldPermissions.xml`);
39
+ await writeFile(outPath, `${XML_DECLARATION}\n${xmlString}`, 'utf-8');
40
+ await transformAndCleanup(outPath, format);
41
+ }
42
+ await rm(filePath, { force: true });
43
+ }
44
+ //# sourceMappingURL=disassembleAndGroupFieldPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disassembleAndGroupFieldPermissions.js","sourceRoot":"","sources":["../../src/service/disassembleAndGroupFieldPermissions.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,QAAgB,EAAE,MAAc;IACxF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,gBAAgB,GAAG,MAAM,EAAE,aAAa,EAAE,gBAAiD,CAAC;IAClG,IAAI,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,MAAM,eAAe,GAAsC,EAAE,CAAC;IAE9D,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,EAAE,KAAK,CAAC;QAC/B,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,SAAS;QAE7C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;YACjC,eAAe,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QACnC,CAAC;QAED,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAClE,MAAM,cAAc,GAAe;YACjC,aAAa,EAAE;gBACb,SAAS,EAAE,yCAAyC;gBACpD,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACjD,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;oBAC1C,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;oBAC1C,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;aACJ;SACF,CAAC;QAEF,MAAM,SAAS,GAAG,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,UAAU,uBAAuB,CAAC,CAAC;QACtE,MAAM,SAAS,CAAC,OAAO,EAAE,GAAG,eAAe,KAAK,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,MAAM,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function flattenNestedObjectPermissions(disassembledDir: string, format: string): Promise<void>;
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+ /* eslint-disable no-await-in-loop */
3
+ import { join } from 'node:path';
4
+ import { readdir, rm, rename } from 'node:fs/promises';
5
+ import { transformAndCleanup } from './transformers.js';
6
+ export async function flattenNestedObjectPermissions(disassembledDir, format) {
7
+ const outerDir = join(disassembledDir, 'objectPermissions');
8
+ const nestedDir = join(outerDir, 'objectPermissions');
9
+ const nestedFiles = await readdir(nestedDir);
10
+ for (const file of nestedFiles) {
11
+ const src = join(nestedDir, file);
12
+ const dest = join(outerDir, file);
13
+ await rename(src, dest);
14
+ await transformAndCleanup(dest, format);
15
+ }
16
+ // Remove the now-empty nested folder
17
+ await rm(nestedDir, { recursive: true, force: true });
18
+ }
19
+ //# sourceMappingURL=flattenNestedObjectPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flattenNestedObjectPermissions.js","sourceRoot":"","sources":["../../src/service/flattenNestedObjectPermissions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,eAAuB,EAAE,MAAc;IAC1F,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAEtD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxB,MAAM,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,qCAAqC;IACrC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function transformAndCleanup(filePath: string, format: string): Promise<void>;
@@ -0,0 +1,25 @@
1
+ import { rm } from 'node:fs/promises';
2
+ import { transformToJson, transformToJson5, transformToToml, transformToYaml, transformToIni } from 'xml-disassembler';
3
+ export async function transformAndCleanup(filePath, format) {
4
+ switch (format) {
5
+ case 'json':
6
+ await transformToJson(filePath);
7
+ break;
8
+ case 'yaml':
9
+ await transformToYaml(filePath);
10
+ break;
11
+ case 'json5':
12
+ await transformToJson5(filePath);
13
+ break;
14
+ case 'ini':
15
+ await transformToIni(filePath);
16
+ break;
17
+ case 'toml':
18
+ await transformToToml(filePath);
19
+ break;
20
+ default:
21
+ return; // Skip if 'xml' or unknown
22
+ }
23
+ await rm(filePath, { force: true });
24
+ }
25
+ //# sourceMappingURL=transformers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformers.js","sourceRoot":"","sources":["../../src/service/transformers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB,EAAE,MAAc;IACxE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM;QACR,KAAK,OAAO;YACV,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACjC,MAAM;QACR,KAAK,KAAK;YACR,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,MAAM;YACT,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM;QACR;YACE,OAAO,CAAC,2BAA2B;IACvC,CAAC;IACD,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACtC,CAAC"}
@@ -41,3 +41,7 @@ Ignore a package directory.
41
41
  # flags.strategy.summary
42
42
 
43
43
  Strategy to follow when decomposing files.
44
+
45
+ # flags.decompose-nested-permissions.summary
46
+
47
+ Additionally decompose object and field permissions on a permission set when strategy is set to "grouped-by-tag".
package/oclif.lock CHANGED
@@ -8273,10 +8273,10 @@ write-file-atomic@^3.0.0:
8273
8273
  signal-exit "^3.0.2"
8274
8274
  typedarray-to-buffer "^3.1.5"
8275
8275
 
8276
- xml-disassembler@^1.8.0:
8277
- version "1.8.0"
8278
- resolved "https://registry.yarnpkg.com/xml-disassembler/-/xml-disassembler-1.8.0.tgz#285031033213a64eb97b6990289a23945598911d"
8279
- integrity sha512-17TV3RIWrvPN5MLon/RtBqsHXgKpGJvgWSagnZbTNM6ZIf2Z2/nHaoZA8g9oH1zLN3kscx8tGuoqn33bA8CYiQ==
8276
+ xml-disassembler@^1.9.0:
8277
+ version "1.9.0"
8278
+ resolved "https://registry.yarnpkg.com/xml-disassembler/-/xml-disassembler-1.9.0.tgz#788a5a924981c11f8dbf15fbe01059e540478ae6"
8279
+ integrity sha512-t3/i51IfTx1EFWeDx0zpleehuWExZcfF7QeLWqx82mTDeEfCb+SxSENzj4P5gp1qy3tgk8u0w67Q9YI0tE4V3w==
8280
8280
  dependencies:
8281
8281
  fast-xml-parser "^5.2.0"
8282
8282
  ignore "^7.0.3"
@@ -95,6 +95,14 @@
95
95
  "grouped-by-tag"
96
96
  ],
97
97
  "type": "option"
98
+ },
99
+ "decompose-nested-permissions": {
100
+ "char": "p",
101
+ "name": "decompose-nested-permissions",
102
+ "required": false,
103
+ "summary": "Additionally decompose object and field permissions on a permission set when strategy is set to \"grouped-by-tag\".",
104
+ "allowNo": false,
105
+ "type": "boolean"
98
106
  }
99
107
  },
100
108
  "hasDynamicHelp": false,
@@ -199,5 +207,5 @@
199
207
  ]
200
208
  }
201
209
  },
202
- "version": "5.8.0"
210
+ "version": "5.9.0"
203
211
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "sf-decomposer",
3
3
  "description": "Break down large Salesforce metadata files into smaller, more manageable files for version control and then recreate deployment-compatible files.",
4
- "version": "5.8.0",
4
+ "version": "5.9.0",
5
5
  "dependencies": {
6
6
  "@oclif/core": "^4",
7
7
  "@salesforce/core": "^8.9.0",
8
8
  "@salesforce/sf-plugins-core": "^11.2.1",
9
9
  "@salesforce/source-deploy-retrieve": "^12.19.0",
10
10
  "fs-extra": "^11.3.0",
11
- "xml-disassembler": "^1.8.0"
11
+ "xml-disassembler": "^1.9.0"
12
12
  },
13
13
  "devDependencies": {
14
14
  "@commitlint/cli": "^19.8.0",