sf-decomposer 6.9.0 → 6.11.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +74 -13
  3. package/lib/commands/decomposer/decompose.d.ts +2 -1
  4. package/lib/commands/decomposer/decompose.js +11 -1
  5. package/lib/commands/decomposer/decompose.js.map +1 -1
  6. package/lib/commands/decomposer/recompose.d.ts +2 -1
  7. package/lib/commands/decomposer/recompose.js +11 -1
  8. package/lib/commands/decomposer/recompose.js.map +1 -1
  9. package/lib/core/decomposeMetadataTypes.js +44 -5
  10. package/lib/core/decomposeMetadataTypes.js.map +1 -1
  11. package/lib/core/recomposeMetadataTypes.js +43 -5
  12. package/lib/core/recomposeMetadataTypes.js.map +1 -1
  13. package/lib/helpers/types.d.ts +5 -2
  14. package/lib/hooks/prerun.js +29 -24
  15. package/lib/hooks/prerun.js.map +1 -1
  16. package/lib/hooks/scopedPostRetrieve.js +39 -38
  17. package/lib/hooks/scopedPostRetrieve.js.map +1 -1
  18. package/lib/metadata/getPackageDirectories.js +1 -0
  19. package/lib/metadata/getPackageDirectories.js.map +1 -1
  20. package/lib/metadata/parseManifest.d.ts +5 -0
  21. package/lib/metadata/parseManifest.js +164 -0
  22. package/lib/metadata/parseManifest.js.map +1 -0
  23. package/lib/service/decompose/decomposeFileHandler.d.ts +1 -1
  24. package/lib/service/decompose/decomposeFileHandler.js +41 -2
  25. package/lib/service/decompose/decomposeFileHandler.js.map +1 -1
  26. package/lib/service/recompose/recomposeFileHandler.d.ts +1 -1
  27. package/lib/service/recompose/recomposeFileHandler.js +57 -2
  28. package/lib/service/recompose/recomposeFileHandler.js.map +1 -1
  29. package/messages/decomposer.decompose.md +11 -1
  30. package/messages/decomposer.recompose.md +11 -1
  31. package/oclif.manifest.json +29 -7
  32. package/package.json +31 -19
  33. package/oclif.lock +0 -10406
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
+ ## [6.11.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.10.0...v6.11.0) (2026-04-24)
9
+
10
+
11
+ ### Features
12
+
13
+ * add --manifest/-x flag for scoped decompose and recompose ([#405](https://github.com/mcarvin8/sf-decomposer/issues/405)) ([2a1f39f](https://github.com/mcarvin8/sf-decomposer/commit/2a1f39f572362899265c6d6092adb8284b9c4427))
14
+
15
+ ## [6.10.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.9.0...v6.10.0) (2026-04-23)
16
+
17
+
18
+ ### Features
19
+
20
+ * **metadata:** bump @salesforce/source-deploy-retrieve ([#403](https://github.com/mcarvin8/sf-decomposer/issues/403)) ([f02a8a2](https://github.com/mcarvin8/sf-decomposer/commit/f02a8a2fd3bcb7c58ee2beb6ff3d637ed27d0e7f))
21
+
8
22
  ## [6.9.0](https://github.com/mcarvin8/sf-decomposer/compare/v6.8.0...v6.9.0) (2026-04-16)
9
23
 
10
24
 
package/README.md CHANGED
@@ -17,6 +17,7 @@ A Salesforce CLI plugin that **decomposes** large metadata XML files into smalle
17
17
  - [Commands](#commands)
18
18
  - [sf decomposer decompose](#sf-decomposer-decompose)
19
19
  - [sf decomposer recompose](#sf-decomposer-recompose)
20
+ - [Manifest-scoped runs](#manifest-scoped-runs)
20
21
  - [Decompose Strategies](#decompose-strategies)
21
22
  - [Custom Labels](#custom-labels-decomposition)
22
23
  - [Permission Sets (grouped-by-tag)](#additional-permission-set-decomposition)
@@ -66,6 +67,13 @@ A Salesforce CLI plugin that **decomposes** large metadata XML files into smalle
66
67
  sf project deploy start
67
68
  ```
68
69
 
70
+ Or scope the recompose to just the components in your deploy manifest:
71
+
72
+ ```bash
73
+ sf decomposer recompose -x "manifest/package.xml"
74
+ sf project deploy start -x "manifest/package.xml"
75
+ ```
76
+
69
77
  ---
70
78
 
71
79
  ## Requirements
@@ -90,6 +98,7 @@ Salesforce’s built-in decomposition is limited. sf-decomposer gives admins and
90
98
 
91
99
  - **Broader metadata support** – Works with most Metadata API types, not just the subset Salesforce decomposes.
92
100
  - **Selective decomposition** – Decompose only what you need; use [.sfdecomposerignore](#sfdecomposerignore) to skip specific files.
101
+ - **Manifest-scoped runs** – Pass `-x package.xml` to decompose or recompose only the components listed in a Salesforce manifest, mirroring `sf project deploy start -x`. Ideal for CI/CD pipelines that only ship a subset of metadata per deployment.
93
102
  - **Two [strategies](#decompose-strategies)**:
94
103
  - **unique-id** (default): one file per nested element, named by content or hash.
95
104
  - **grouped-by-tag**: one file per tag (e.g. all `fieldPermissions` in a permission set in `fieldPermissions.xml`). Use `--decompose-nested-permissions` for deeper permission set and muting permission set decomposition.
@@ -114,10 +123,11 @@ Decomposes metadata in all local package directories (from `sfdx-project.json`)
114
123
 
115
124
  ```
116
125
  USAGE
117
- $ sf decomposer decompose -m <value> -f <value> -i <value> -s <value> [--prepurge --postpurge -p --json]
126
+ $ sf decomposer decompose [-m <value>] [-x <value>] [-f <value>] [-i <value>] [-s <value>] [--prepurge --postpurge -p --json]
118
127
 
119
128
  FLAGS
120
- -m, --metadata-type=<value> Metadata suffix to process (e.g. flow, labels). Repeatable.
129
+ -m, --metadata-type=<value> Metadata suffix to process (e.g. flow, labels). Repeatable. Optional when --manifest is provided.
130
+ -x, --manifest=<value> Path to a package.xml manifest. When provided, only the components listed in the manifest are decomposed.
121
131
  -f, --format=<value> Output format: xml | yaml | json | json5 [default: xml]
122
132
  -i, --ignore-package-directory=<value> Package directory to skip (as in sfdx-project.json). Repeatable.
123
133
  -s, --strategy=<value> unique-id | grouped-by-tag [default: unique-id]
@@ -129,6 +139,8 @@ GLOBAL FLAGS
129
139
  --json Output as JSON.
130
140
  ```
131
141
 
142
+ > At least one of `--metadata-type` or `--manifest` is required. When both are supplied, the run is scoped to the intersection of the two.
143
+
132
144
  **Examples**
133
145
 
134
146
  ```bash
@@ -140,6 +152,12 @@ sf decomposer decompose -m "flow" -m "labels" -f "yaml" --prepurge --postpurge
140
152
 
141
153
  # Decompose flows, excluding the force-app package
142
154
  sf decomposer decompose -m "flow" -i "force-app"
155
+
156
+ # Decompose only the components listed in a manifest
157
+ sf decomposer decompose -x "manifest/package.xml" --prepurge
158
+
159
+ # Restrict a manifest run to a single metadata type
160
+ sf decomposer decompose -x "manifest/package.xml" -m "permissionset"
143
161
  ```
144
162
 
145
163
  ### sf decomposer recompose
@@ -148,10 +166,11 @@ Recomposes decomposed files into deployment-compatible metadata.
148
166
 
149
167
  ```
150
168
  USAGE
151
- $ sf decomposer recompose -m <value> -i <value> [--postpurge --json]
169
+ $ sf decomposer recompose [-m <value>] [-x <value>] [-i <value>] [--postpurge --json]
152
170
 
153
171
  FLAGS
154
- -m, --metadata-type=<value> Metadata suffix to process (e.g. flow, labels). Repeatable.
172
+ -m, --metadata-type=<value> Metadata suffix to process (e.g. flow, labels). Repeatable. Optional when --manifest is provided.
173
+ -x, --manifest=<value> Path to a package.xml manifest. When provided, only the components listed in the manifest are recomposed.
155
174
  -i, --ignore-package-directory=<value> Package directory to skip. Repeatable.
156
175
  --postpurge Remove decomposed files after recomposing [default: false]
157
176
 
@@ -159,11 +178,52 @@ GLOBAL FLAGS
159
178
  --json Output as JSON.
160
179
  ```
161
180
 
181
+ > At least one of `--metadata-type` or `--manifest` is required. When both are supplied, the run is scoped to the intersection of the two.
182
+
162
183
  **Examples**
163
184
 
164
185
  ```bash
165
186
  sf decomposer recompose -m "flow" --postpurge
166
187
  sf decomposer recompose -m "flow" -i "force-app"
188
+
189
+ # Recompose only the components listed in a deploy manifest before deploying
190
+ sf decomposer recompose -x "manifest/package.xml"
191
+ sf project deploy start -x "manifest/package.xml"
192
+ ```
193
+
194
+ ### Manifest-scoped runs
195
+
196
+ The `-x` / `--manifest` flag accepts any standard Salesforce `package.xml` and limits the work to just the components it lists. This is especially useful for CI/CD pipelines that deploy a subset of metadata per change.
197
+
198
+ How it works:
199
+
200
+ - The manifest is parsed with `@salesforce/source-deploy-retrieve`'s `ManifestResolver`, so the same XML you pass to `sf project deploy start -x` is honored here.
201
+ - For each entry, the plugin resolves the matching parent metadata files in your local package directories (using each metadata type's `directoryName`, `suffix`, `strictDirectoryName`, and `folderType` from the SDR registry).
202
+ - Only those files are decomposed/recomposed; everything else on disk is left untouched.
203
+ - Wildcards (`<members>*</members>`) expand against your local source. Folder-typed members (e.g. `MyFolder/MyReport`) are resolved by walking the folder.
204
+ - Types in the manifest that the plugin does not support (e.g. `CustomObject`, `ApexClass`) are skipped with a warning instead of failing the run, so a single manifest can drive both deploys and decomposer runs.
205
+ - If both `--metadata-type` and `--manifest` are provided, the run is scoped to the intersection (only types present in both).
206
+
207
+ Example manifest:
208
+
209
+ ```xml
210
+ <?xml version="1.0" encoding="UTF-8"?>
211
+ <Package xmlns="http://soap.sforce.com/2006/04/metadata">
212
+ <types>
213
+ <members>HR_Admin</members>
214
+ <name>PermissionSet</name>
215
+ </types>
216
+ <types>
217
+ <members>Case</members>
218
+ <name>Workflow</name>
219
+ </types>
220
+ <version>58.0</version>
221
+ </Package>
222
+ ```
223
+
224
+ ```bash
225
+ sf decomposer recompose -x "manifest/package.xml"
226
+ sf project deploy start -x "manifest/package.xml"
167
227
  ```
168
228
 
169
229
  ---
@@ -299,15 +359,16 @@ Put **.sfdecomposer.config.json** in the project root to run:
299
359
 
300
360
  Copy and customize the [sample config](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/examples/.sfdecomposer.config.json).
301
361
 
302
- | Option | Required | Description |
303
- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
304
- | `metadataSuffixes` | Yes | Comma-separated metadata suffixes to decompose/recompose. |
305
- | `ignorePackageDirectories` | No | Comma-separated package directories to skip. |
306
- | `prePurge` | No | Remove existing decomposed files before decomposing (default: false). |
307
- | `postPurge` | No | After decompose: remove originals; after recompose: remove decomposed files (default: false). |
308
- | `decomposedFormat` | No | xml, json, json5, or yaml (default: xml). |
309
- | `strategy` | No | `unique-id` \| `grouped-by-tag` (default: unique-id). |
310
- | `decomposeNestedPermissions` | No | With grouped-by-tag, set true to further decompose permission set and muting permission set object/field permissions. |
362
+ | Option | Required | Description |
363
+ | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
364
+ | `metadataSuffixes` | Conditional | Comma-separated metadata suffixes to decompose/recompose. Required unless `manifest` is set; when both are set, the run is scoped to the intersection. |
365
+ | `manifest` | Conditional | Path (relative to the project root) to a `package.xml` manifest. When set, only the components listed in the manifest are decomposed/recomposed. See `-x` above. |
366
+ | `ignorePackageDirectories` | No | Comma-separated package directories to skip. |
367
+ | `prePurge` | No | Remove existing decomposed files before decomposing (default: false). |
368
+ | `postPurge` | No | After decompose: remove originals; after recompose: remove decomposed files (default: false). |
369
+ | `decomposedFormat` | No | xml, json, json5, or yaml (default: xml). |
370
+ | `strategy` | No | `unique-id` \| `grouped-by-tag` (default: unique-id). |
371
+ | `decomposeNestedPermissions` | No | With grouped-by-tag, set true to further decompose permission set and muting permission set object/field permissions. |
311
372
 
312
373
  ---
313
374
 
@@ -5,7 +5,8 @@ export default class DecomposerDecompose extends SfCommand<DecomposerResult> {
5
5
  static readonly description: string;
6
6
  static readonly examples: string[];
7
7
  static readonly flags: {
8
- 'metadata-type': import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
8
+ 'metadata-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ manifest: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
10
  prepurge: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  postpurge: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
12
  format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
@@ -14,7 +14,13 @@ export default class DecomposerDecompose extends SfCommand {
14
14
  summary: messages.getMessage('flags.metadata-type.summary'),
15
15
  char: 'm',
16
16
  multiple: true,
17
- required: true,
17
+ required: false,
18
+ }),
19
+ manifest: Flags.file({
20
+ summary: messages.getMessage('flags.manifest.summary'),
21
+ char: 'x',
22
+ required: false,
23
+ exists: true,
18
24
  }),
19
25
  prepurge: Flags.boolean({
20
26
  summary: messages.getMessage('flags.prepurge.summary'),
@@ -57,6 +63,9 @@ export default class DecomposerDecompose extends SfCommand {
57
63
  };
58
64
  async run() {
59
65
  const { flags } = await this.parse(DecomposerDecompose);
66
+ if (!flags['metadata-type'] && !flags['manifest']) {
67
+ throw messages.createError('error.missingMetadataOrManifest');
68
+ }
60
69
  return decomposeMetadataTypes({
61
70
  metadataTypes: flags['metadata-type'],
62
71
  prepurge: flags['prepurge'],
@@ -65,6 +74,7 @@ export default class DecomposerDecompose extends SfCommand {
65
74
  ignoreDirs: flags['ignore-package-directory'],
66
75
  strategy: flags['strategy'],
67
76
  decomposeNestedPerms: flags['decompose-nested-permissions'],
77
+ manifest: flags['manifest'],
68
78
  log: this.log.bind(this),
69
79
  });
70
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/decompose.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/decompose.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,8 @@ export default class DecomposerRecompose extends SfCommand<DecomposerResult> {
5
5
  static readonly description: string;
6
6
  static readonly examples: string[];
7
7
  static readonly flags: {
8
- 'metadata-type': import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
8
+ 'metadata-type': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ manifest: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
10
  postpurge: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  'ignore-package-directory': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
12
  };
@@ -13,7 +13,13 @@ export default class DecomposerRecompose extends SfCommand {
13
13
  summary: messages.getMessage('flags.metadata-type.summary'),
14
14
  char: 'm',
15
15
  multiple: true,
16
- required: true,
16
+ required: false,
17
+ }),
18
+ manifest: Flags.file({
19
+ summary: messages.getMessage('flags.manifest.summary'),
20
+ char: 'x',
21
+ required: false,
22
+ exists: true,
17
23
  }),
18
24
  postpurge: Flags.boolean({
19
25
  summary: messages.getMessage('flags.postpurge.summary'),
@@ -29,10 +35,14 @@ export default class DecomposerRecompose extends SfCommand {
29
35
  };
30
36
  async run() {
31
37
  const { flags } = await this.parse(DecomposerRecompose);
38
+ if (!flags['metadata-type'] && !flags['manifest']) {
39
+ throw messages.createError('error.missingMetadataOrManifest');
40
+ }
32
41
  return recomposeMetadataTypes({
33
42
  metadataTypes: flags['metadata-type'],
34
43
  postpurge: flags['postpurge'],
35
44
  ignoreDirs: flags['ignore-package-directory'],
45
+ manifest: flags['manifest'],
36
46
  log: this.log.bind(this),
37
47
  });
38
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"recompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/recompose.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,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,CAAmB,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,CAAmB,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC1E,MAAM,CAAmB,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAErE,MAAM,CAAmB,KAAK,GAAG;QACtC,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,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,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;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAExD,OAAO,sBAAsB,CAAC;YAC5B,aAAa,EAAE,KAAK,CAAC,eAAe,CAAC;YACrC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;YAC7B,UAAU,EAAE,KAAK,CAAC,0BAA0B,CAAC;YAC7C,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;SACzB,CAAC,CAAC;IACL,CAAC"}
1
+ {"version":3,"file":"recompose.js","sourceRoot":"","sources":["../../../src/commands/decomposer/recompose.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,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,CAAmB,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,CAAmB,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC1E,MAAM,CAAmB,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAErE,MAAM,CAAmB,KAAK,GAAG;QACtC,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,KAAK;SAChB,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACtD,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,IAAI;SACb,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,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;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAExD,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAClD,MAAM,QAAQ,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;QAChE,CAAC;QAED,OAAO,sBAAsB,CAAC;YAC5B,aAAa,EAAE,KAAK,CAAC,eAAe,CAAC;YACrC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;YAC7B,UAAU,EAAE,KAAK,CAAC,0BAA0B,CAAC;YAC7C,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC;YAC3B,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;SACzB,CAAC,CAAC;IACL,CAAC"}
@@ -1,14 +1,52 @@
1
1
  'use strict';
2
2
  import pLimit from 'p-limit';
3
3
  import { getRegistryValuesBySuffix } from '../metadata/getRegistryValuesBySuffix.js';
4
+ import { parseManifest } from '../metadata/parseManifest.js';
4
5
  import { decomposeFileHandler } from '../service/decompose/decomposeFileHandler.js';
5
6
  import { CONCURRENCY_LIMITS } from '../helpers/constants.js';
6
7
  export async function decomposeMetadataTypes(options) {
7
- const { metadataTypes, prepurge, postpurge, format, ignoreDirs, strategy, decomposeNestedPerms, log } = options;
8
+ const { metadataTypes, prepurge, postpurge, format, ignoreDirs, strategy, decomposeNestedPerms, manifest, log } = options;
9
+ let manifestFilter;
10
+ let effectiveTypes;
11
+ if (manifest) {
12
+ manifestFilter = await parseManifest(manifest, ignoreDirs);
13
+ if (metadataTypes && metadataTypes.length > 0) {
14
+ const manifestTypes = new Set(manifestFilter.suffixes);
15
+ effectiveTypes = metadataTypes.filter((type) => manifestTypes.has(type));
16
+ }
17
+ else {
18
+ effectiveTypes = manifestFilter.suffixes;
19
+ }
20
+ }
21
+ else {
22
+ if (!metadataTypes || metadataTypes.length === 0) {
23
+ throw Error('Either --metadata-type or --manifest must be provided.');
24
+ }
25
+ effectiveTypes = metadataTypes;
26
+ }
27
+ if (effectiveTypes.length === 0) {
28
+ log('No metadata types to decompose after applying the manifest filter.');
29
+ return { metadata: [] };
30
+ }
8
31
  // Limit concurrent metadata type processing to prevent file system overload
9
32
  const limit = pLimit(CONCURRENCY_LIMITS.METADATA_TYPES);
10
- const tasks = metadataTypes.map((metadataType) => limit(async () => {
11
- const { metaAttributes, ignorePath } = await getRegistryValuesBySuffix(metadataType, 'decompose', ignoreDirs);
33
+ const processed = [];
34
+ const tasks = effectiveTypes.map((metadataType) => limit(async () => {
35
+ const manifestXmlPaths = manifestFilter?.parentXmlsBySuffix.get(metadataType);
36
+ let metaAttributes;
37
+ let ignorePath;
38
+ try {
39
+ ({ metaAttributes, ignorePath } = await getRegistryValuesBySuffix(metadataType, 'decompose', ignoreDirs));
40
+ }
41
+ catch (err) {
42
+ /* istanbul ignore if -- @preserve: preserves non-manifest behavior; unreachable via known CLI types */
43
+ if (!manifestFilter)
44
+ throw err;
45
+ /* istanbul ignore next -- @preserve: getRegistryValuesBySuffix always throws Error instances */
46
+ const message = err instanceof Error ? err.message : String(err);
47
+ log(`Skipping ${metadataType}: ${message}`);
48
+ return;
49
+ }
12
50
  let effectiveStrategy = strategy;
13
51
  if (metadataType === 'labels' && strategy === 'grouped-by-tag') {
14
52
  effectiveStrategy = 'unique-id';
@@ -16,10 +54,11 @@ export async function decomposeMetadataTypes(options) {
16
54
  if (metadataType === 'loyaltyProgramSetup' && strategy === 'grouped-by-tag') {
17
55
  effectiveStrategy = 'unique-id';
18
56
  }
19
- await decomposeFileHandler(metaAttributes, prepurge, postpurge, format, ignorePath, effectiveStrategy, decomposeNestedPerms);
57
+ await decomposeFileHandler(metaAttributes, prepurge, postpurge, format, ignorePath, effectiveStrategy, decomposeNestedPerms, manifestXmlPaths);
58
+ processed.push(metadataType);
20
59
  log(`All metadata files have been decomposed for the metadata type: ${metadataType}`);
21
60
  }));
22
61
  await Promise.all(tasks);
23
- return { metadata: metadataTypes };
62
+ return { metadata: processed };
24
63
  }
25
64
  //# sourceMappingURL=decomposeMetadataTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decomposeMetadataTypes.js","sourceRoot":"","sources":["../../src/core/decomposeMetadataTypes.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAyB;IACpE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAEhH,4EAA4E;IAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAC/C,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QAC9G,IAAI,iBAAiB,GAAG,QAAQ,CAAC;QAEjC,IAAI,YAAY,KAAK,QAAQ,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;YAC/D,iBAAiB,GAAG,WAAW,CAAC;QAClC,CAAC;QAED,IAAI,YAAY,KAAK,qBAAqB,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;YAC5E,iBAAiB,GAAG,WAAW,CAAC;QAClC,CAAC;QAED,MAAM,oBAAoB,CACxB,cAAc,EACd,QAAQ,EACR,SAAS,EACT,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,oBAAoB,CACrB,CAAC;QAEF,GAAG,CAAC,kEAAkE,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEzB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"decomposeMetadataTypes.js","sourceRoot":"","sources":["../../src/core/decomposeMetadataTypes.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,58 @@
1
1
  'use strict';
2
2
  import pLimit from 'p-limit';
3
3
  import { getRegistryValuesBySuffix } from '../metadata/getRegistryValuesBySuffix.js';
4
+ import { parseManifest } from '../metadata/parseManifest.js';
4
5
  import { recomposeFileHandler } from '../service/recompose/recomposeFileHandler.js';
5
6
  import { CONCURRENCY_LIMITS } from '../helpers/constants.js';
6
7
  export async function recomposeMetadataTypes(options) {
7
- const { metadataTypes, postpurge, ignoreDirs, log } = options;
8
+ const { metadataTypes, postpurge, ignoreDirs, manifest, log } = options;
9
+ let manifestFilter;
10
+ let effectiveTypes;
11
+ if (manifest) {
12
+ manifestFilter = await parseManifest(manifest, ignoreDirs);
13
+ if (metadataTypes && metadataTypes.length > 0) {
14
+ const manifestTypes = new Set(manifestFilter.suffixes);
15
+ effectiveTypes = metadataTypes.filter((type) => manifestTypes.has(type));
16
+ }
17
+ else {
18
+ effectiveTypes = manifestFilter.suffixes;
19
+ }
20
+ }
21
+ else {
22
+ if (!metadataTypes || metadataTypes.length === 0) {
23
+ throw Error('Either --metadata-type or --manifest must be provided.');
24
+ }
25
+ effectiveTypes = metadataTypes;
26
+ }
27
+ if (effectiveTypes.length === 0) {
28
+ log('No metadata types to recompose after applying the manifest filter.');
29
+ return { metadata: [] };
30
+ }
8
31
  // Limit concurrent metadata type processing to prevent file system overload
9
32
  const limit = pLimit(CONCURRENCY_LIMITS.METADATA_TYPES);
10
- const tasks = metadataTypes.map((metadataType) => limit(async () => {
11
- const { metaAttributes } = await getRegistryValuesBySuffix(metadataType, 'recompose', ignoreDirs);
12
- await recomposeFileHandler(metaAttributes, postpurge);
33
+ const processed = [];
34
+ const tasks = effectiveTypes.map((metadataType) => limit(async () => {
35
+ const manifestXmlPaths = manifestFilter?.parentXmlsBySuffix.get(metadataType);
36
+ let metaAttributes;
37
+ try {
38
+ ({ metaAttributes } = await getRegistryValuesBySuffix(metadataType, 'recompose', ignoreDirs));
39
+ }
40
+ catch (err) {
41
+ /* istanbul ignore if -- @preserve: preserves non-manifest behavior; unreachable via known CLI types */
42
+ if (!manifestFilter)
43
+ throw err;
44
+ /* istanbul ignore next -- @preserve: getRegistryValuesBySuffix always throws Error instances */
45
+ const message = err instanceof Error ? err.message : String(err);
46
+ log(`Skipping ${metadataType}: ${message}`);
47
+ return;
48
+ }
49
+ await recomposeFileHandler(metaAttributes, postpurge, manifestXmlPaths);
50
+ processed.push(metadataType);
13
51
  log(`All metadata files have been recomposed for the metadata type: ${metadataType}`);
14
52
  }));
15
53
  await Promise.all(tasks);
16
54
  return {
17
- metadata: metadataTypes,
55
+ metadata: processed,
18
56
  };
19
57
  }
20
58
  //# sourceMappingURL=recomposeMetadataTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recomposeMetadataTypes.js","sourceRoot":"","sources":["../../src/core/recomposeMetadataTypes.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAyB;IACpE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAE9D,4EAA4E;IAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAC/C,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QAClG,MAAM,oBAAoB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QACtD,GAAG,CAAC,kEAAkE,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEzB,OAAO;QACL,QAAQ,EAAE,aAAa;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"recomposeMetadataTypes.js","sourceRoot":"","sources":["../../src/core/recomposeMetadataTypes.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,aAAa,EAAkB,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAyB;IACpE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAExE,IAAI,cAA0C,CAAC;IAC/C,IAAI,cAAwB,CAAC;IAE7B,IAAI,QAAQ,EAAE,CAAC;QACb,cAAc,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC3D,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACvD,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC;QAC3C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;QACD,cAAc,GAAG,aAAa,CAAC;IACjC,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,oEAAoE,CAAC,CAAC;QAC1E,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IAED,4EAA4E;IAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAExD,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAChD,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,gBAAgB,GAAG,cAAc,EAAE,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE9E,IAAI,cAAc,CAAC;QACnB,IAAI,CAAC;YACH,CAAC,EAAE,cAAc,EAAE,GAAG,MAAM,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;QAChG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uGAAuG;YACvG,IAAI,CAAC,cAAc;gBAAE,MAAM,GAAG,CAAC;YAC/B,gGAAgG;YAChG,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,GAAG,CAAC,YAAY,YAAY,KAAK,OAAO,EAAE,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,MAAM,oBAAoB,CAAC,cAAc,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;QACxE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7B,GAAG,CAAC,kEAAkE,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEzB,OAAO;QACL,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
@@ -11,6 +11,7 @@ export type ConfigFile = {
11
11
  ignorePackageDirectories: string;
12
12
  strategy: string;
13
13
  decomposeNestedPermissions: boolean;
14
+ manifest?: string;
14
15
  };
15
16
  export type SfdxProject = {
16
17
  packageDirectories: Array<{
@@ -37,18 +38,20 @@ export type FieldPermission = {
37
38
  readable?: boolean;
38
39
  };
39
40
  export type DecomposeOptions = {
40
- metadataTypes: string[];
41
+ metadataTypes?: string[];
41
42
  prepurge: boolean;
42
43
  postpurge: boolean;
43
44
  format: string;
44
45
  ignoreDirs?: string[];
45
46
  strategy: string;
46
47
  decomposeNestedPerms: boolean;
48
+ manifest?: string;
47
49
  log: (msg: string) => void;
48
50
  };
49
51
  export type RecomposeOptions = {
50
- metadataTypes: string[];
52
+ metadataTypes?: string[];
51
53
  postpurge: boolean;
52
54
  ignoreDirs?: string[];
55
+ manifest?: string;
53
56
  log: (msg: string) => void;
54
57
  };
@@ -4,16 +4,42 @@ import { resolve } from 'node:path';
4
4
  import DecomposerRecompose from '../commands/decomposer/recompose.js';
5
5
  import { getRepoRoot } from '../service/core/getRepoRoot.js';
6
6
  import { HOOK_CONFIG_JSON } from '../helpers/constants.js';
7
+ function buildRecomposeArgs(configFile) {
8
+ const metadataTypes = configFile.metadataSuffixes || '.';
9
+ const postpurge = configFile.postPurge || false;
10
+ const ignorePackageDirs = configFile.ignorePackageDirectories || '';
11
+ const manifest = configFile.manifest ?? '';
12
+ if (metadataTypes.trim() === '.' && manifest.trim() === '') {
13
+ return undefined;
14
+ }
15
+ const commandArgs = [];
16
+ if (metadataTypes.trim() !== '.') {
17
+ for (const metadataType of metadataTypes.split(',')) {
18
+ commandArgs.push('--metadata-type', metadataType.replace(/,/g, ''));
19
+ }
20
+ }
21
+ if (ignorePackageDirs.trim() !== '') {
22
+ for (const dir of ignorePackageDirs.split(',')) {
23
+ commandArgs.push('--ignore-package-directory', dir.replace(/,/g, ''));
24
+ }
25
+ }
26
+ if (manifest.trim() !== '') {
27
+ commandArgs.push('--manifest', manifest.trim());
28
+ }
29
+ if (postpurge)
30
+ commandArgs.push('--postpurge');
31
+ return commandArgs;
32
+ }
7
33
  export const prerun = async function (options) {
8
34
  if (!['project:deploy:validate', 'project:deploy:start'].includes(options.Command.id)) {
9
35
  return;
10
36
  }
11
- let configFile;
12
37
  const { repoRoot } = await getRepoRoot();
13
38
  if (!repoRoot) {
14
39
  return;
15
40
  }
16
41
  const configPath = resolve(repoRoot, HOOK_CONFIG_JSON);
42
+ let configFile;
17
43
  try {
18
44
  const jsonString = await readFile(configPath, 'utf-8');
19
45
  configFile = JSON.parse(jsonString);
@@ -21,30 +47,9 @@ export const prerun = async function (options) {
21
47
  catch (error) {
22
48
  return;
23
49
  }
24
- const metadataTypes = configFile.metadataSuffixes || '.';
25
- const postpurge = configFile.postPurge || false;
26
- const ignorePackageDirs = configFile.ignorePackageDirectories || '';
27
- if (metadataTypes.trim() === '.') {
50
+ const commandArgs = buildRecomposeArgs(configFile);
51
+ if (!commandArgs)
28
52
  return;
29
- }
30
- const metadataTypesArray = metadataTypes.split(',');
31
- const commandArgs = [];
32
- for (const metadataType of metadataTypesArray) {
33
- const sanitizedMetadataType = metadataType.replace(/,/g, '');
34
- commandArgs.push('--metadata-type');
35
- commandArgs.push(sanitizedMetadataType);
36
- }
37
- if (ignorePackageDirs.trim() !== '') {
38
- const ignorePackageDirArray = ignorePackageDirs.split(',');
39
- for (const dirs of ignorePackageDirArray) {
40
- const sanitizedDir = dirs.replace(/,/g, '');
41
- commandArgs.push('--ignore-package-directory');
42
- commandArgs.push(sanitizedDir);
43
- }
44
- }
45
- if (postpurge) {
46
- commandArgs.push('--postpurge');
47
- }
48
53
  await DecomposerRecompose.run(commandArgs);
49
54
  };
50
55
  //# sourceMappingURL=prerun.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../src/hooks/prerun.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,gCAAgC,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,CAAC,MAAM,MAAM,GAAmB,KAAK,WAAW,OAAO;IAC3D,IAAI,CAAC,CAAC,yBAAyB,EAAE,sBAAsB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACtF,OAAO;IACT,CAAC;IAED,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,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,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":"prerun.js","sourceRoot":"","sources":["../../src/hooks/prerun.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,gCAAgC,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,SAAS,kBAAkB,CAAC,UAAsB;IAChD,MAAM,aAAa,GAAW,UAAU,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACjE,MAAM,SAAS,GAAY,UAAU,CAAC,SAAS,IAAI,KAAK,CAAC;IACzD,MAAM,iBAAiB,GAAW,UAAU,CAAC,wBAAwB,IAAI,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAW,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC;IAEnD,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;QACjC,KAAK,MAAM,YAAY,IAAI,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,WAAW,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,WAAW,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3B,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,SAAS;QAAE,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE/C,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAmB,KAAK,WAAW,OAAO;IAC3D,IAAI,CAAC,CAAC,yBAAyB,EAAE,sBAAsB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACtF,OAAO;IACT,CAAC;IAED,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,UAAsB,CAAC;IAC3B,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,WAAW,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,WAAW;QAAE,OAAO;IAEzB,MAAM,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC"}