@simplysf/simply-utam-core 0.0.0 → 0.1.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 (64) hide show
  1. package/LICENSE.txt +206 -0
  2. package/README.md +98 -12
  3. package/lib/discovery/index.d.ts +1 -0
  4. package/lib/discovery/index.js +17 -0
  5. package/lib/discovery/index.js.map +1 -0
  6. package/lib/discovery/project-discovery.d.ts +55 -0
  7. package/lib/discovery/project-discovery.js +180 -0
  8. package/lib/discovery/project-discovery.js.map +1 -0
  9. package/lib/index.d.ts +8 -2
  10. package/lib/index.js +8 -2
  11. package/lib/index.js.map +1 -1
  12. package/lib/namespaces/index.d.ts +1 -0
  13. package/lib/namespaces/index.js +17 -0
  14. package/lib/namespaces/index.js.map +1 -0
  15. package/lib/namespaces/namespace-rewriter.d.ts +50 -0
  16. package/lib/namespaces/namespace-rewriter.js +223 -0
  17. package/lib/namespaces/namespace-rewriter.js.map +1 -0
  18. package/lib/navigator.d.ts +133 -5
  19. package/lib/navigator.js +224 -12
  20. package/lib/navigator.js.map +1 -1
  21. package/lib/overrides/index.d.ts +1 -0
  22. package/lib/overrides/index.js +17 -0
  23. package/lib/overrides/index.js.map +1 -0
  24. package/lib/overrides/overrides-merger.d.ts +63 -0
  25. package/lib/overrides/overrides-merger.js +280 -0
  26. package/lib/overrides/overrides-merger.js.map +1 -0
  27. package/lib/rules/index.d.ts +1 -0
  28. package/lib/rules/index.js +17 -0
  29. package/lib/rules/index.js.map +1 -0
  30. package/lib/rules/rules-generator.d.ts +49 -0
  31. package/lib/rules/rules-generator.js +199 -0
  32. package/lib/rules/rules-generator.js.map +1 -0
  33. package/lib/scaffold/index.d.ts +1 -0
  34. package/lib/scaffold/index.js +17 -0
  35. package/lib/scaffold/index.js.map +1 -0
  36. package/lib/scaffold/project-scaffolder.d.ts +148 -0
  37. package/lib/scaffold/project-scaffolder.js +313 -0
  38. package/lib/scaffold/project-scaffolder.js.map +1 -0
  39. package/lib/steps/expression-matcher.d.ts +42 -0
  40. package/lib/steps/expression-matcher.js +106 -0
  41. package/lib/steps/expression-matcher.js.map +1 -0
  42. package/lib/steps/gherkin-parser.d.ts +27 -0
  43. package/lib/steps/gherkin-parser.js +98 -0
  44. package/lib/steps/gherkin-parser.js.map +1 -0
  45. package/lib/steps/index.d.ts +4 -0
  46. package/lib/steps/index.js +20 -0
  47. package/lib/steps/index.js.map +1 -0
  48. package/lib/steps/snippet-generator.d.ts +34 -0
  49. package/lib/steps/snippet-generator.js +101 -0
  50. package/lib/steps/snippet-generator.js.map +1 -0
  51. package/lib/steps/step-scaffolder.d.ts +49 -0
  52. package/lib/steps/step-scaffolder.js +225 -0
  53. package/lib/steps/step-scaffolder.js.map +1 -0
  54. package/lib/test-environment.d.ts +99 -4
  55. package/lib/test-environment.js +302 -4
  56. package/lib/test-environment.js.map +1 -1
  57. package/package.json +34 -4
  58. package/templates/generator.config.json +13 -0
  59. package/templates/hello.feature +4 -0
  60. package/templates/hello.steps.mjs +7 -0
  61. package/templates/namespace-map.json +3 -0
  62. package/templates/utam.config.json +9 -0
  63. package/templates/wdio.conf.mjs +68 -0
  64. package/templates/wireit.json +37 -0
package/lib/navigator.js CHANGED
@@ -14,7 +14,20 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { applicationPath, newRecordPath, recordPath, relatedListPath } from './lightning-paths.js';
17
- import { TestEnvironment } from './test-environment.js';
17
+ import { getTestEnvironment } from './test-environment.js';
18
+ /**
19
+ * Resolves an active browser instance from explicit parameters or the global runtime context.
20
+ *
21
+ * @param browserInstance - Optional explicit browser instance.
22
+ * @returns The resolved NavigableBrowser instance.
23
+ */
24
+ export function resolveBrowser(browserInstance) {
25
+ const resolved = browserInstance ?? (typeof browser !== 'undefined' ? browser : undefined);
26
+ if (!resolved || typeof resolved.navigateTo !== 'function') {
27
+ throw new Error('No browser to navigate: pass one as the `browser` option, or run inside WebdriverIO so the global `browser` exists');
28
+ }
29
+ return resolved;
30
+ }
18
31
  /**
19
32
  * Logs the browser in to the test org and opens a Lightning page in one step. Every navigation
20
33
  * goes through a fresh frontdoor URL, so each one also works as the first thing a test does.
@@ -28,43 +41,48 @@ export class LightningNavigator {
28
41
  * @param options The environment and browser to use; both have defaults.
29
42
  */
30
43
  constructor(options = {}) {
31
- this.#environment = options.environment ?? new TestEnvironment();
44
+ this.#environment = options.environment ?? getTestEnvironment();
32
45
  this.#browser = options.browser;
33
46
  }
34
47
  /**
35
48
  * Log in and open `returnUrl`, or the org's default landing page when it is omitted.
36
49
  *
37
50
  * @param returnUrl Path to open after login.
51
+ * @returns The resolved frontdoor URL navigated to.
38
52
  */
39
53
  async goToLoginUrl(returnUrl) {
40
54
  const url = await this.#environment.buildFrontdoorUrl(returnUrl);
41
- await this.#resolveBrowser().navigateTo(url);
55
+ await this.resolveBrowser().navigateTo(url);
56
+ return url;
42
57
  }
43
58
  /**
44
59
  * Log in and open a Lightning app's home page.
45
60
  *
46
61
  * @param applicationName The app's developer name; see `lightningAppName` for namespacing.
62
+ * @returns The resolved application URL.
47
63
  */
48
64
  async goToApplication(applicationName) {
49
- await this.goToLoginUrl(applicationPath(applicationName));
65
+ return this.goToLoginUrl(applicationPath(applicationName));
50
66
  }
51
67
  /**
52
68
  * Log in and open the new-record form for an object.
53
69
  *
54
70
  * @param applicationName The app's developer name.
55
71
  * @param objectApiName The object's API name.
72
+ * @returns The resolved record creation URL.
56
73
  */
57
74
  async goToCreateNewRecord(applicationName, objectApiName) {
58
- await this.goToLoginUrl(newRecordPath(applicationName, objectApiName));
75
+ return this.goToLoginUrl(newRecordPath(applicationName, objectApiName));
59
76
  }
60
77
  /**
61
78
  * Log in and open a record's detail page.
62
79
  *
63
80
  * @param applicationName The app's developer name.
64
81
  * @param recordId The record's id.
82
+ * @returns The resolved record view URL.
65
83
  */
66
84
  async goToRecord(applicationName, recordId) {
67
- await this.goToLoginUrl(recordPath(applicationName, recordId));
85
+ return this.goToLoginUrl(recordPath(applicationName, recordId));
68
86
  }
69
87
  /**
70
88
  * Log in and open one of a record's related lists.
@@ -72,16 +90,210 @@ export class LightningNavigator {
72
90
  * @param applicationName The app's developer name.
73
91
  * @param recordId The parent record's id.
74
92
  * @param relatedListName The relationship name.
93
+ * @returns The resolved related list URL.
75
94
  */
76
95
  async goToRelatedList(applicationName, recordId, relatedListName) {
77
- await this.goToLoginUrl(relatedListPath(applicationName, recordId, relatedListName));
96
+ return this.goToLoginUrl(relatedListPath(applicationName, recordId, relatedListName));
78
97
  }
79
- #resolveBrowser() {
80
- const browser = this.#browser ?? globalThis.browser;
81
- if (!browser) {
82
- throw new Error('No browser to navigate: pass one as the `browser` option, or run inside WebdriverIO so the global `browser` exists');
98
+ /**
99
+ * Navigates the browser to a specific Experience Cloud site page via UI Bridge frontdoor login.
100
+ *
101
+ * @param sitePrefix - The URL prefix of the Experience site.
102
+ * @param pageName - The Experience page name (relative to /s/).
103
+ * @returns The resolved Experience frontdoor URL navigated to.
104
+ */
105
+ async goToExperiencePage(sitePrefix, pageName) {
106
+ const cleanPageName = pageName.startsWith('/') ? pageName.slice(1) : pageName;
107
+ let frontdoorUrl;
108
+ if (typeof this.#environment.buildExperienceFrontdoorUrl === 'function') {
109
+ frontdoorUrl = await this.#environment.buildExperienceFrontdoorUrl(sitePrefix, `/s/${cleanPageName}`);
110
+ }
111
+ else {
112
+ const env = getTestEnvironment();
113
+ frontdoorUrl = await env.buildExperienceFrontdoorUrl(sitePrefix, `/s/${cleanPageName}`);
83
114
  }
84
- return browser;
115
+ await this.resolveBrowser().navigateTo(frontdoorUrl);
116
+ return frontdoorUrl;
117
+ }
118
+ /**
119
+ * Logs in as a specific user using Salesforce user impersonation.
120
+ *
121
+ * @param username - The target user's username.
122
+ * @param returnUrl - The target page to land on once logged in. Defaults to '/'.
123
+ * @returns The resolved impersonation redirect URL.
124
+ */
125
+ async loginAsUser(username, returnUrl = '/') {
126
+ const browserTarget = this.resolveBrowser();
127
+ await this.goToLoginUrl('/');
128
+ const env = this.#environment;
129
+ const orgId = typeof env.getOrgId === 'function' ? await env.getOrgId() : await getTestEnvironment().getOrgId();
130
+ const userId = typeof env.getUserIdByUsername === 'function'
131
+ ? await env.getUserIdByUsername(username)
132
+ : await getTestEnvironment().getUserIdByUsername(username);
133
+ const instanceUrl = typeof env.getInstanceUrl === 'function'
134
+ ? await env.getInstanceUrl()
135
+ : await getTestEnvironment().getInstanceUrl();
136
+ const loginAsUrl = `${instanceUrl}/servlet/servlet.su?oid=${orgId}&suorgadminid=${userId}&targetURL=${encodeURIComponent(returnUrl)}`;
137
+ await browserTarget.navigateTo(loginAsUrl);
138
+ return loginAsUrl;
85
139
  }
140
+ /**
141
+ * Logs in as a specific user and navigates directly to an Experience Cloud site.
142
+ *
143
+ * @param username - The target user's username.
144
+ * @param sitePrefix - The URL prefix of the Experience site.
145
+ * @param pageName - The Experience page name (relative to /s/).
146
+ * @returns The resolved Experience site page URL.
147
+ */
148
+ async loginAsExperienceUser(username, sitePrefix, pageName) {
149
+ const browserTarget = this.resolveBrowser();
150
+ await this.loginAsUser(username, '/');
151
+ const env = this.#environment;
152
+ const networkId = typeof env.getNetworkIdByPrefix === 'function'
153
+ ? await env.getNetworkIdByPrefix(sitePrefix)
154
+ : await getTestEnvironment().getNetworkIdByPrefix(sitePrefix);
155
+ const instanceUrl = typeof env.getInstanceUrl === 'function'
156
+ ? await env.getInstanceUrl()
157
+ : await getTestEnvironment().getInstanceUrl();
158
+ const networkSwitchUrl = `${instanceUrl}/servlet/networks/switch?networkId=${networkId}`;
159
+ await browserTarget.navigateTo(networkSwitchUrl);
160
+ const cleanPageName = pageName.startsWith('/') ? pageName.slice(1) : pageName;
161
+ const experienceUrl = typeof env.buildExperienceUrl === 'function'
162
+ ? await env.buildExperienceUrl(sitePrefix, `/s/${cleanPageName}`)
163
+ : await getTestEnvironment().buildExperienceUrl(sitePrefix, `/s/${cleanPageName}`);
164
+ await browserTarget.navigateTo(experienceUrl);
165
+ return experienceUrl;
166
+ }
167
+ resolveBrowser() {
168
+ return resolveBrowser(this.#browser);
169
+ }
170
+ }
171
+ /**
172
+ * Functional helper: Navigates the browser to the Salesforce Frontdoor login URL.
173
+ *
174
+ * @param returnUrl - Optional landing page path after login.
175
+ * @param browserInstance - Optional browser instance overriding the global runner.
176
+ * @param testEnvironment - Optional TestEnvironment instance.
177
+ * @returns The resolved frontdoor URL navigated to.
178
+ */
179
+ export async function goToLoginUrl(returnUrl, browserInstance, testEnvironment) {
180
+ const navigator = new LightningNavigator({
181
+ browser: browserInstance,
182
+ environment: testEnvironment,
183
+ });
184
+ return navigator.goToLoginUrl(returnUrl);
185
+ }
186
+ /**
187
+ * Functional helper: Navigates the browser to an Experience Cloud page.
188
+ *
189
+ * @param sitePrefix - The URL prefix of the Experience site.
190
+ * @param pageName - The Experience page name.
191
+ * @param browserInstance - Optional browser instance overriding the global runner.
192
+ * @param testEnvironment - Optional TestEnvironment instance.
193
+ * @returns The resolved Experience frontdoor URL navigated to.
194
+ */
195
+ export async function goToExperiencePage(sitePrefix, pageName, browserInstance, testEnvironment) {
196
+ const navigator = new LightningNavigator({
197
+ browser: browserInstance,
198
+ environment: testEnvironment,
199
+ });
200
+ return navigator.goToExperiencePage(sitePrefix, pageName);
201
+ }
202
+ /**
203
+ * Functional helper: Logs in as a specific user using Salesforce user impersonation.
204
+ *
205
+ * @param username - The target user's username.
206
+ * @param returnUrl - Landing path after impersonation.
207
+ * @param browserInstance - Optional browser instance overriding the global runner.
208
+ * @param testEnvironment - Optional TestEnvironment instance.
209
+ * @returns The resolved impersonation redirect URL.
210
+ */
211
+ export async function loginAsUser(username, returnUrl = '/', browserInstance, testEnvironment) {
212
+ const navigator = new LightningNavigator({
213
+ browser: browserInstance,
214
+ environment: testEnvironment,
215
+ });
216
+ return navigator.loginAsUser(username, returnUrl);
217
+ }
218
+ /**
219
+ * Functional helper: Logs in as a user and navigates directly to an Experience Cloud site.
220
+ *
221
+ * @param username - The target user's username.
222
+ * @param sitePrefix - The URL prefix of the Experience site.
223
+ * @param pageName - The Experience page name.
224
+ * @param browserInstance - Optional browser instance overriding the global runner.
225
+ * @param testEnvironment - Optional TestEnvironment instance.
226
+ * @returns The resolved Experience site page URL.
227
+ */
228
+ export async function loginAsExperienceUser(username, sitePrefix, pageName, browserInstance, testEnvironment) {
229
+ const navigator = new LightningNavigator({
230
+ browser: browserInstance,
231
+ environment: testEnvironment,
232
+ });
233
+ return navigator.loginAsExperienceUser(username, sitePrefix, pageName);
234
+ }
235
+ /**
236
+ * Functional helper: Navigates to a standard Lightning Application home page.
237
+ *
238
+ * @param applicationName - The developer name of the Lightning application.
239
+ * @param browserInstance - Optional browser instance.
240
+ * @param testEnvironment - Optional TestEnvironment instance.
241
+ * @returns The resolved frontdoor application URL.
242
+ */
243
+ export async function goToApplication(applicationName, browserInstance, testEnvironment) {
244
+ const navigator = new LightningNavigator({
245
+ browser: browserInstance,
246
+ environment: testEnvironment,
247
+ });
248
+ return navigator.goToApplication(applicationName);
249
+ }
250
+ /**
251
+ * Functional helper: Navigates to a new record creation page for a specific sObject in an application.
252
+ *
253
+ * @param applicationName - The developer name of the Lightning application.
254
+ * @param objectName - The API name of the sObject.
255
+ * @param browserInstance - Optional browser instance.
256
+ * @param testEnvironment - Optional TestEnvironment instance.
257
+ * @returns The resolved frontdoor URL.
258
+ */
259
+ export async function goToCreateNewRecord(applicationName, objectName, browserInstance, testEnvironment) {
260
+ const navigator = new LightningNavigator({
261
+ browser: browserInstance,
262
+ environment: testEnvironment,
263
+ });
264
+ return navigator.goToCreateNewRecord(applicationName, objectName);
265
+ }
266
+ /**
267
+ * Functional helper: Navigates to a record view page in a Lightning application.
268
+ *
269
+ * @param applicationName - The developer name of the Lightning application.
270
+ * @param recordId - The 15 or 18 character Salesforce record ID.
271
+ * @param browserInstance - Optional browser instance.
272
+ * @param testEnvironment - Optional TestEnvironment instance.
273
+ * @returns The resolved frontdoor URL.
274
+ */
275
+ export async function goToRecord(applicationName, recordId, browserInstance, testEnvironment) {
276
+ const navigator = new LightningNavigator({
277
+ browser: browserInstance,
278
+ environment: testEnvironment,
279
+ });
280
+ return navigator.goToRecord(applicationName, recordId);
281
+ }
282
+ /**
283
+ * Functional helper: Navigates to a related list view for a specific record in a Lightning application.
284
+ *
285
+ * @param applicationName - The developer name of the Lightning application.
286
+ * @param recordId - The 15 or 18 character parent record ID.
287
+ * @param relatedListName - The relationship name of the related list.
288
+ * @param browserInstance - Optional browser instance.
289
+ * @param testEnvironment - Optional TestEnvironment instance.
290
+ * @returns The resolved frontdoor URL.
291
+ */
292
+ export async function goToRelatedList(applicationName, recordId, relatedListName, browserInstance, testEnvironment) {
293
+ const navigator = new LightningNavigator({
294
+ browser: browserInstance,
295
+ environment: testEnvironment,
296
+ });
297
+ return navigator.goToRelatedList(applicationName, recordId, relatedListName);
86
298
  }
87
299
  //# sourceMappingURL=navigator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigator.js","sourceRoot":"","sources":["../src/navigator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAmBxD;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACpB,YAAY,CAAqB;IACjC,QAAQ,CAAoB;IAErC;;;;OAIG;IACH,YAAmB,UAAqC,EAAE;QACxD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,eAAe,EAAE,CAAC;QACjE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,YAAY,CAAC,SAAkB;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe,CAAC,eAAuB;QAClD,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,mBAAmB,CAAC,eAAuB,EAAE,aAAqB;QAC7E,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;IACzE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,UAAU,CAAC,eAAuB,EAAE,QAAgB;QAC/D,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjE,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,eAAe,CAAC,eAAuB,EAAE,QAAgB,EAAE,eAAuB;QAC7F,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,eAAe,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IACvF,CAAC;IAED,eAAe;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAK,UAA6C,CAAC,OAAO,CAAC;QACxF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,oHAAoH,CACrH,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"navigator.js","sourceRoot":"","sources":["../src/navigator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from './overrides-merger.js';
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright (c) 2026, SimplySF.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export * from './overrides-merger.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/overrides/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,63 @@
1
+ export interface ApplyOverridesOptions {
2
+ rootDir?: string;
3
+ sourceDirs?: string[];
4
+ dryRun?: boolean;
5
+ verbose?: boolean;
6
+ }
7
+ export interface OverrideChange {
8
+ elementName: string;
9
+ matchCount: number;
10
+ }
11
+ export interface FileOverrideResult {
12
+ overrideFilePath: string;
13
+ generatedUtamFilePath: string;
14
+ changes: OverrideChange[];
15
+ applied: boolean;
16
+ error?: string;
17
+ }
18
+ export interface ApplyOverridesResult {
19
+ scannedFilesCount: number;
20
+ modifiedFilesCount: number;
21
+ totalOverridesApplied: number;
22
+ dryRun: boolean;
23
+ results: FileOverrideResult[];
24
+ }
25
+ export interface UtamOverrideItem {
26
+ name: string;
27
+ element: Record<string, unknown>;
28
+ }
29
+ /**
30
+ * Detects indentation of a JSON string content (e.g. 2 spaces, 4 spaces, or tabs).
31
+ *
32
+ * @param content - Raw JSON string content.
33
+ * @returns Indentation string sequence (spaces or tab).
34
+ */
35
+ export declare function detectIndentation(content: string): string;
36
+ /**
37
+ * Recursively locates all *.utam-overrides.json files in a directory.
38
+ *
39
+ * @param dirPath - Directory to search within.
40
+ * @returns Array of absolute paths to discovered *.utam-overrides.json files.
41
+ */
42
+ export declare function findUtamOverridesFiles(dirPath: string): string[];
43
+ /**
44
+ * Recursively walks the UTAM JSON structure to find element nodes.
45
+ *
46
+ * @param node - Current AST node.
47
+ * @param callback - Function invoked for each element object encountered.
48
+ */
49
+ export declare function walkElements(node: unknown, callback: (element: Record<string, unknown>) => void): void;
50
+ /**
51
+ * Safely merges the override element properties into the target element.
52
+ *
53
+ * @param target - Target AST element node to mutate.
54
+ * @param source - Override properties to merge into target.
55
+ */
56
+ export declare function mergeElements(target: Record<string, unknown>, source: Record<string, unknown>): void;
57
+ /**
58
+ * Merges custom overrides from *.utam-overrides.json files into generated UTAM schemas.
59
+ *
60
+ * @param options - Override application options.
61
+ * @returns Summary of scanned and modified UTAM schemas.
62
+ */
63
+ export declare function applyUtamOverrides(options?: ApplyOverridesOptions): ApplyOverridesResult;
@@ -0,0 +1,280 @@
1
+ /*
2
+ * Copyright (c) 2026, SimplySF.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import fs from 'node:fs';
17
+ import path from 'node:path';
18
+ import { discoverProject } from '../discovery/index.js';
19
+ /**
20
+ * Detects indentation of a JSON string content (e.g. 2 spaces, 4 spaces, or tabs).
21
+ *
22
+ * @param content - Raw JSON string content.
23
+ * @returns Indentation string sequence (spaces or tab).
24
+ */
25
+ export function detectIndentation(content) {
26
+ const match = content.match(/^[ \t]+(?=")/m);
27
+ return match ? match[0] : ' ';
28
+ }
29
+ /**
30
+ * Recursively locates all *.utam-overrides.json files in a directory.
31
+ *
32
+ * @param dirPath - Directory to search within.
33
+ * @returns Array of absolute paths to discovered *.utam-overrides.json files.
34
+ */
35
+ export function findUtamOverridesFiles(dirPath) {
36
+ const filesList = [];
37
+ try {
38
+ if (!fs.existsSync(dirPath)) {
39
+ return filesList;
40
+ }
41
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ const fullPath = path.join(dirPath, entry.name);
44
+ if (entry.isDirectory()) {
45
+ const name = entry.name;
46
+ if (name !== 'node_modules' &&
47
+ name !== '.git' &&
48
+ name !== 'dist' &&
49
+ name !== 'lib' &&
50
+ name !== '.wireit' &&
51
+ name !== 'pageObjects' &&
52
+ name !== 'allure-results') {
53
+ filesList.push(...findUtamOverridesFiles(fullPath));
54
+ }
55
+ }
56
+ else if (entry.isFile() && entry.name.endsWith('.utam-overrides.json')) {
57
+ filesList.push(fullPath);
58
+ }
59
+ }
60
+ }
61
+ catch {
62
+ // Gracefully ignore directory read errors
63
+ }
64
+ return filesList;
65
+ }
66
+ /**
67
+ * Recursively walks the UTAM JSON structure to find element nodes.
68
+ *
69
+ * @param node - Current AST node.
70
+ * @param callback - Function invoked for each element object encountered.
71
+ */
72
+ export function walkElements(node, callback) {
73
+ if (!node || typeof node !== 'object') {
74
+ return;
75
+ }
76
+ if (Array.isArray(node)) {
77
+ for (const item of node) {
78
+ if (item && typeof item === 'object' && !Array.isArray(item)) {
79
+ const itemObj = item;
80
+ if (typeof itemObj['name'] === 'string') {
81
+ callback(itemObj);
82
+ }
83
+ if (itemObj['elements']) {
84
+ walkElements(itemObj['elements'], callback);
85
+ }
86
+ if (itemObj['shadow'] &&
87
+ typeof itemObj['shadow'] === 'object' &&
88
+ itemObj['shadow']['elements']) {
89
+ walkElements(itemObj['shadow']['elements'], callback);
90
+ }
91
+ }
92
+ }
93
+ return;
94
+ }
95
+ const objNode = node;
96
+ if (objNode['elements']) {
97
+ walkElements(objNode['elements'], callback);
98
+ }
99
+ if (objNode['shadow'] &&
100
+ typeof objNode['shadow'] === 'object' &&
101
+ objNode['shadow']['elements']) {
102
+ walkElements(objNode['shadow']['elements'], callback);
103
+ }
104
+ }
105
+ /**
106
+ * Safely merges the override element properties into the target element.
107
+ *
108
+ * @param target - Target AST element node to mutate.
109
+ * @param source - Override properties to merge into target.
110
+ */
111
+ export function mergeElements(target, source) {
112
+ for (const [key, val] of Object.entries(source)) {
113
+ if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
114
+ if (typeof target[key] !== 'object' || target[key] === null || Array.isArray(target[key])) {
115
+ target[key] = {};
116
+ }
117
+ mergeElements(target[key], val);
118
+ }
119
+ else {
120
+ target[key] = val;
121
+ }
122
+ }
123
+ }
124
+ function applyItemsToUtam(utamJson, overrides) {
125
+ const changes = [];
126
+ let count = 0;
127
+ for (const item of overrides) {
128
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
129
+ continue;
130
+ }
131
+ const overrideItem = item;
132
+ const { name, element } = overrideItem;
133
+ if (typeof name !== 'string' || !element || typeof element !== 'object' || Array.isArray(element)) {
134
+ continue;
135
+ }
136
+ let matchCount = 0;
137
+ walkElements(utamJson, (elementNode) => {
138
+ if (elementNode['name'] === name) {
139
+ mergeElements(elementNode, element);
140
+ matchCount++;
141
+ }
142
+ });
143
+ if (matchCount > 0) {
144
+ count += matchCount;
145
+ changes.push({ elementName: name, matchCount });
146
+ }
147
+ }
148
+ return { changes, count };
149
+ }
150
+ function processSingleOverrideFile(overrideFile, dryRun) {
151
+ let overrides;
152
+ try {
153
+ overrides = JSON.parse(fs.readFileSync(overrideFile, 'utf-8'));
154
+ }
155
+ catch (err) {
156
+ return {
157
+ result: {
158
+ overrideFilePath: overrideFile,
159
+ generatedUtamFilePath: '',
160
+ changes: [],
161
+ applied: false,
162
+ error: `Failed to parse overrides file: ${err.message}`,
163
+ },
164
+ appliedCount: 0,
165
+ };
166
+ }
167
+ if (!Array.isArray(overrides)) {
168
+ return {
169
+ result: {
170
+ overrideFilePath: overrideFile,
171
+ generatedUtamFilePath: '',
172
+ changes: [],
173
+ applied: false,
174
+ error: 'Overrides content is not a JSON array',
175
+ },
176
+ appliedCount: 0,
177
+ };
178
+ }
179
+ const componentDir = path.dirname(overrideFile);
180
+ const componentName = path.basename(overrideFile).replace('.utam-overrides.json', '');
181
+ const generatedFilePath = path.join(componentDir, '__utam__', `${componentName}.utam.json`);
182
+ if (!fs.existsSync(generatedFilePath)) {
183
+ return {
184
+ result: {
185
+ overrideFilePath: overrideFile,
186
+ generatedUtamFilePath: generatedFilePath,
187
+ changes: [],
188
+ applied: false,
189
+ error: 'Target generated UTAM file does not exist',
190
+ },
191
+ appliedCount: 0,
192
+ };
193
+ }
194
+ let fileContent;
195
+ let utamJson;
196
+ try {
197
+ fileContent = fs.readFileSync(generatedFilePath, 'utf-8');
198
+ utamJson = JSON.parse(fileContent);
199
+ }
200
+ catch (err) {
201
+ return {
202
+ result: {
203
+ overrideFilePath: overrideFile,
204
+ generatedUtamFilePath: generatedFilePath,
205
+ changes: [],
206
+ applied: false,
207
+ error: `Failed to parse target UTAM JSON: ${err.message}`,
208
+ },
209
+ appliedCount: 0,
210
+ };
211
+ }
212
+ const { changes, count } = applyItemsToUtam(utamJson, overrides);
213
+ if (changes.length > 0) {
214
+ if (!dryRun) {
215
+ const indent = detectIndentation(fileContent);
216
+ const endsWithNewline = fileContent.endsWith('\n');
217
+ let outputContent = JSON.stringify(utamJson, null, indent);
218
+ if (endsWithNewline && !outputContent.endsWith('\n')) {
219
+ outputContent += '\n';
220
+ }
221
+ fs.writeFileSync(generatedFilePath, outputContent, 'utf-8');
222
+ }
223
+ return {
224
+ result: {
225
+ overrideFilePath: overrideFile,
226
+ generatedUtamFilePath: generatedFilePath,
227
+ changes,
228
+ applied: true,
229
+ },
230
+ appliedCount: count,
231
+ };
232
+ }
233
+ return {
234
+ result: {
235
+ overrideFilePath: overrideFile,
236
+ generatedUtamFilePath: generatedFilePath,
237
+ changes: [],
238
+ applied: false,
239
+ },
240
+ appliedCount: 0,
241
+ };
242
+ }
243
+ /**
244
+ * Merges custom overrides from *.utam-overrides.json files into generated UTAM schemas.
245
+ *
246
+ * @param options - Override application options.
247
+ * @returns Summary of scanned and modified UTAM schemas.
248
+ */
249
+ export function applyUtamOverrides(options = {}) {
250
+ const rootDir = path.resolve(options.rootDir ?? process.cwd());
251
+ const dryRun = Boolean(options.dryRun);
252
+ let sourceDirs = options.sourceDirs;
253
+ if (!sourceDirs || sourceDirs.length === 0) {
254
+ const discovered = discoverProject(rootDir);
255
+ sourceDirs = discovered.packageDirectories.length > 0 ? discovered.packageDirectories : ['./sfdx-source'];
256
+ }
257
+ const allOverrideFiles = [];
258
+ for (const sourceDir of sourceDirs) {
259
+ const resolvedSource = path.isAbsolute(sourceDir) ? sourceDir : path.resolve(rootDir, sourceDir);
260
+ allOverrideFiles.push(...findUtamOverridesFiles(resolvedSource));
261
+ }
262
+ const uniqueOverrideFiles = Array.from(new Set(allOverrideFiles));
263
+ const result = {
264
+ scannedFilesCount: uniqueOverrideFiles.length,
265
+ modifiedFilesCount: 0,
266
+ totalOverridesApplied: 0,
267
+ dryRun,
268
+ results: [],
269
+ };
270
+ for (const overrideFile of uniqueOverrideFiles) {
271
+ const { result: fileResult, appliedCount } = processSingleOverrideFile(overrideFile, dryRun);
272
+ if (fileResult.applied) {
273
+ result.modifiedFilesCount++;
274
+ result.totalOverridesApplied += appliedCount;
275
+ }
276
+ result.results.push(fileResult);
277
+ }
278
+ return result;
279
+ }
280
+ //# sourceMappingURL=overrides-merger.js.map