@salesforce/webapp-template-cli-experimental 1.3.3
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/LICENSE.txt +82 -0
- package/README.md +1464 -0
- package/dist/commands/apply-patches.d.ts +23 -0
- package/dist/commands/apply-patches.d.ts.map +1 -0
- package/dist/commands/apply-patches.js +650 -0
- package/dist/commands/apply-patches.js.map +1 -0
- package/dist/commands/new-app-feature.d.ts +7 -0
- package/dist/commands/new-app-feature.d.ts.map +1 -0
- package/dist/commands/new-app-feature.js +208 -0
- package/dist/commands/new-app-feature.js.map +1 -0
- package/dist/commands/new-app.d.ts +6 -0
- package/dist/commands/new-app.d.ts.map +1 -0
- package/dist/commands/new-app.js +7 -0
- package/dist/commands/new-app.js.map +1 -0
- package/dist/commands/watch-patches.d.ts +4 -0
- package/dist/commands/watch-patches.d.ts.map +1 -0
- package/dist/commands/watch-patches.js +128 -0
- package/dist/commands/watch-patches.js.map +1 -0
- package/dist/core/dependency-resolver.d.ts +40 -0
- package/dist/core/dependency-resolver.d.ts.map +1 -0
- package/dist/core/dependency-resolver.js +126 -0
- package/dist/core/dependency-resolver.js.map +1 -0
- package/dist/core/file-operations.d.ts +55 -0
- package/dist/core/file-operations.d.ts.map +1 -0
- package/dist/core/file-operations.js +350 -0
- package/dist/core/file-operations.js.map +1 -0
- package/dist/core/package-json-merger.d.ts +31 -0
- package/dist/core/package-json-merger.d.ts.map +1 -0
- package/dist/core/package-json-merger.js +149 -0
- package/dist/core/package-json-merger.js.map +1 -0
- package/dist/core/patch-loader.d.ts +18 -0
- package/dist/core/patch-loader.d.ts.map +1 -0
- package/dist/core/patch-loader.js +115 -0
- package/dist/core/patch-loader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/debounce.d.ts +9 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/debounce.js +20 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/import-merger.d.ts +17 -0
- package/dist/utils/import-merger.d.ts.map +1 -0
- package/dist/utils/import-merger.js +244 -0
- package/dist/utils/import-merger.js.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +22 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path-mappings.d.ts +94 -0
- package/dist/utils/path-mappings.d.ts.map +1 -0
- package/dist/utils/path-mappings.js +139 -0
- package/dist/utils/path-mappings.js.map +1 -0
- package/dist/utils/paths.d.ts +61 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +178 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/route-merger.d.ts +107 -0
- package/dist/utils/route-merger.d.ts.map +1 -0
- package/dist/utils/route-merger.js +358 -0
- package/dist/utils/route-merger.js.map +1 -0
- package/dist/utils/validation.d.ts +35 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +137 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { type PathMapping, type PathMappings } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Get default path mappings for a feature
|
|
9
|
+
* Maps webApp → webapplications/<featureName> (old format for path translation)
|
|
10
|
+
* Note: This still uses the old format because translatePathToTargetApp will convert it to SFDX format
|
|
11
|
+
*
|
|
12
|
+
* @param featureName - The name of the feature (e.g., 'feature-react-nav-menu')
|
|
13
|
+
* @returns Array containing the default path mapping
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* getDefaultPathMappings('feature-nav')
|
|
17
|
+
* // Returns: [{ from: 'webApp', to: 'webapplications/feature-nav' }]
|
|
18
|
+
*/
|
|
19
|
+
export declare function getDefaultPathMappings(featureName: string): PathMapping[];
|
|
20
|
+
/**
|
|
21
|
+
* Check if path mappings are enabled for a feature
|
|
22
|
+
* Default: true (enabled by default, opt-out)
|
|
23
|
+
*
|
|
24
|
+
* @param pathMappings - The path mappings configuration from the feature
|
|
25
|
+
* @returns true if mappings are enabled (default), false if explicitly disabled
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* arePathMappingsEnabled(undefined) // Returns: true (default enabled)
|
|
29
|
+
* arePathMappingsEnabled({ enabled: false }) // Returns: false
|
|
30
|
+
* arePathMappingsEnabled({ enabled: true }) // Returns: true
|
|
31
|
+
* arePathMappingsEnabled({ mappings: [...] }) // Returns: true (enabled by default)
|
|
32
|
+
*/
|
|
33
|
+
export declare function arePathMappingsEnabled(pathMappings?: PathMappings): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get the effective path mappings for a feature
|
|
36
|
+
* Returns custom mappings if provided, otherwise default mappings
|
|
37
|
+
*
|
|
38
|
+
* @param featureName - The name of the feature
|
|
39
|
+
* @param pathMappings - The path mappings configuration from the feature
|
|
40
|
+
* @returns Array of path mappings to apply (empty if disabled)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Default behavior (no config)
|
|
44
|
+
* getEffectivePathMappings('feature-nav', undefined)
|
|
45
|
+
* // Returns: [{ from: 'webApp', to: 'webapplications/feature-nav' }]
|
|
46
|
+
*
|
|
47
|
+
* // Disabled
|
|
48
|
+
* getEffectivePathMappings('feature-nav', { enabled: false })
|
|
49
|
+
* // Returns: []
|
|
50
|
+
*
|
|
51
|
+
* // Custom mappings
|
|
52
|
+
* getEffectivePathMappings('feature-nav', { mappings: [{ from: 'web', to: 'custom/path' }] })
|
|
53
|
+
* // Returns: [{ from: 'web', to: 'custom/path' }]
|
|
54
|
+
*/
|
|
55
|
+
export declare function getEffectivePathMappings(featureName: string, pathMappings?: PathMappings): PathMapping[];
|
|
56
|
+
/**
|
|
57
|
+
* Apply path mappings to a template file path
|
|
58
|
+
*
|
|
59
|
+
* This function transforms simplified paths (e.g., "webApp/src/app.tsx") into
|
|
60
|
+
* their full target paths (e.g., "webapplications/feature-name/src/app.tsx")
|
|
61
|
+
* based on the provided mappings.
|
|
62
|
+
*
|
|
63
|
+
* The function checks each mapping in order and applies the first one that matches.
|
|
64
|
+
* If no mapping matches, the path is returned unchanged (backwards compatibility).
|
|
65
|
+
*
|
|
66
|
+
* @param templatePath - Path relative to template directory (e.g., "webApp/src/app.tsx")
|
|
67
|
+
* @param mappings - Array of path mappings to apply
|
|
68
|
+
* @returns Transformed path with mapping applied
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Apply default webApp mapping
|
|
72
|
+
* applyPathMappings('webApp/src/app.tsx', [{
|
|
73
|
+
* from: 'webApp',
|
|
74
|
+
* to: 'webapplications/feature-react-nav-menu'
|
|
75
|
+
* }])
|
|
76
|
+
* // Returns: 'webapplications/feature-react-nav-menu/src/app.tsx'
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Backwards compatibility - old paths pass through
|
|
80
|
+
* applyPathMappings('webapplications/feature-react-nav-menu/src/app.tsx', [...])
|
|
81
|
+
* // Returns: 'webapplications/feature-react-nav-menu/src/app.tsx'
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // No mappings - path unchanged
|
|
85
|
+
* applyPathMappings('webApp/src/app.tsx', [])
|
|
86
|
+
* // Returns: 'webApp/src/app.tsx'
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // No match - path unchanged
|
|
90
|
+
* applyPathMappings('src/app.tsx', [{ from: 'webApp', to: '...' }])
|
|
91
|
+
* // Returns: 'src/app.tsx'
|
|
92
|
+
*/
|
|
93
|
+
export declare function applyPathMappings(templatePath: string, mappings: PathMapping[]): string;
|
|
94
|
+
//# sourceMappingURL=path-mappings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-mappings.d.ts","sourceRoot":"","sources":["../../src/utils/path-mappings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE,CAOzE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAS3E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACvC,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,YAAY,GACzB,WAAW,EAAE,CAaf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CA4BvF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get default path mappings for a feature
|
|
3
|
+
* Maps webApp → webapplications/<featureName> (old format for path translation)
|
|
4
|
+
* Note: This still uses the old format because translatePathToTargetApp will convert it to SFDX format
|
|
5
|
+
*
|
|
6
|
+
* @param featureName - The name of the feature (e.g., 'feature-react-nav-menu')
|
|
7
|
+
* @returns Array containing the default path mapping
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* getDefaultPathMappings('feature-nav')
|
|
11
|
+
* // Returns: [{ from: 'webApp', to: 'webapplications/feature-nav' }]
|
|
12
|
+
*/
|
|
13
|
+
export function getDefaultPathMappings(featureName) {
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
from: "webApp",
|
|
17
|
+
to: `webapplications/${featureName}`,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Check if path mappings are enabled for a feature
|
|
23
|
+
* Default: true (enabled by default, opt-out)
|
|
24
|
+
*
|
|
25
|
+
* @param pathMappings - The path mappings configuration from the feature
|
|
26
|
+
* @returns true if mappings are enabled (default), false if explicitly disabled
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* arePathMappingsEnabled(undefined) // Returns: true (default enabled)
|
|
30
|
+
* arePathMappingsEnabled({ enabled: false }) // Returns: false
|
|
31
|
+
* arePathMappingsEnabled({ enabled: true }) // Returns: true
|
|
32
|
+
* arePathMappingsEnabled({ mappings: [...] }) // Returns: true (enabled by default)
|
|
33
|
+
*/
|
|
34
|
+
export function arePathMappingsEnabled(pathMappings) {
|
|
35
|
+
// If pathMappings is undefined, default to enabled
|
|
36
|
+
if (!pathMappings)
|
|
37
|
+
return true;
|
|
38
|
+
// If pathMappings.enabled is explicitly set, use that value
|
|
39
|
+
if (pathMappings.enabled !== undefined)
|
|
40
|
+
return pathMappings.enabled;
|
|
41
|
+
// Otherwise, enabled by default
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the effective path mappings for a feature
|
|
46
|
+
* Returns custom mappings if provided, otherwise default mappings
|
|
47
|
+
*
|
|
48
|
+
* @param featureName - The name of the feature
|
|
49
|
+
* @param pathMappings - The path mappings configuration from the feature
|
|
50
|
+
* @returns Array of path mappings to apply (empty if disabled)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Default behavior (no config)
|
|
54
|
+
* getEffectivePathMappings('feature-nav', undefined)
|
|
55
|
+
* // Returns: [{ from: 'webApp', to: 'webapplications/feature-nav' }]
|
|
56
|
+
*
|
|
57
|
+
* // Disabled
|
|
58
|
+
* getEffectivePathMappings('feature-nav', { enabled: false })
|
|
59
|
+
* // Returns: []
|
|
60
|
+
*
|
|
61
|
+
* // Custom mappings
|
|
62
|
+
* getEffectivePathMappings('feature-nav', { mappings: [{ from: 'web', to: 'custom/path' }] })
|
|
63
|
+
* // Returns: [{ from: 'web', to: 'custom/path' }]
|
|
64
|
+
*/
|
|
65
|
+
export function getEffectivePathMappings(featureName, pathMappings) {
|
|
66
|
+
// If disabled, return empty array (no mappings)
|
|
67
|
+
if (!arePathMappingsEnabled(pathMappings)) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
// If custom mappings provided, use those
|
|
71
|
+
if (pathMappings?.mappings && pathMappings.mappings.length > 0) {
|
|
72
|
+
return pathMappings.mappings;
|
|
73
|
+
}
|
|
74
|
+
// Otherwise, use default mappings
|
|
75
|
+
return getDefaultPathMappings(featureName);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Apply path mappings to a template file path
|
|
79
|
+
*
|
|
80
|
+
* This function transforms simplified paths (e.g., "webApp/src/app.tsx") into
|
|
81
|
+
* their full target paths (e.g., "webapplications/feature-name/src/app.tsx")
|
|
82
|
+
* based on the provided mappings.
|
|
83
|
+
*
|
|
84
|
+
* The function checks each mapping in order and applies the first one that matches.
|
|
85
|
+
* If no mapping matches, the path is returned unchanged (backwards compatibility).
|
|
86
|
+
*
|
|
87
|
+
* @param templatePath - Path relative to template directory (e.g., "webApp/src/app.tsx")
|
|
88
|
+
* @param mappings - Array of path mappings to apply
|
|
89
|
+
* @returns Transformed path with mapping applied
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Apply default webApp mapping
|
|
93
|
+
* applyPathMappings('webApp/src/app.tsx', [{
|
|
94
|
+
* from: 'webApp',
|
|
95
|
+
* to: 'webapplications/feature-react-nav-menu'
|
|
96
|
+
* }])
|
|
97
|
+
* // Returns: 'webapplications/feature-react-nav-menu/src/app.tsx'
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* // Backwards compatibility - old paths pass through
|
|
101
|
+
* applyPathMappings('webapplications/feature-react-nav-menu/src/app.tsx', [...])
|
|
102
|
+
* // Returns: 'webapplications/feature-react-nav-menu/src/app.tsx'
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* // No mappings - path unchanged
|
|
106
|
+
* applyPathMappings('webApp/src/app.tsx', [])
|
|
107
|
+
* // Returns: 'webApp/src/app.tsx'
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // No match - path unchanged
|
|
111
|
+
* applyPathMappings('src/app.tsx', [{ from: 'webApp', to: '...' }])
|
|
112
|
+
* // Returns: 'src/app.tsx'
|
|
113
|
+
*/
|
|
114
|
+
export function applyPathMappings(templatePath, mappings) {
|
|
115
|
+
// If no mappings, return path as-is (backwards compatibility)
|
|
116
|
+
if (mappings.length === 0) {
|
|
117
|
+
return templatePath;
|
|
118
|
+
}
|
|
119
|
+
// Try each mapping in order (first match wins)
|
|
120
|
+
for (const mapping of mappings) {
|
|
121
|
+
const fromPrefix = mapping.from + "/";
|
|
122
|
+
// Check if path starts with the mapping's "from" prefix
|
|
123
|
+
if (templatePath.startsWith(fromPrefix)) {
|
|
124
|
+
// Replace prefix with "to" prefix
|
|
125
|
+
const remainder = templatePath.substring(fromPrefix.length);
|
|
126
|
+
return mapping.to + "/" + remainder;
|
|
127
|
+
}
|
|
128
|
+
// Also handle exact match (no trailing slash)
|
|
129
|
+
if (templatePath === mapping.from) {
|
|
130
|
+
return mapping.to;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// No mapping matched, return original path
|
|
134
|
+
// This handles both:
|
|
135
|
+
// 1. Old-style full paths (webapplications/...)
|
|
136
|
+
// 2. Other paths that don't use the mapping shorthand
|
|
137
|
+
return templatePath;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=path-mappings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-mappings.js","sourceRoot":"","sources":["../../src/utils/path-mappings.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACzD,OAAO;QACN;YACC,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,mBAAmB,WAAW,EAAE;SACpC;KACD,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAA2B;IACjE,mDAAmD;IACnD,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAE/B,4DAA4D;IAC5D,IAAI,YAAY,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC,OAAO,CAAC;IAEpE,gCAAgC;IAChC,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,wBAAwB,CACvC,WAAmB,EACnB,YAA2B;IAE3B,gDAAgD;IAChD,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,CAAC;IACX,CAAC;IAED,yCAAyC;IACzC,IAAI,YAAY,EAAE,QAAQ,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,OAAO,YAAY,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,kCAAkC;IAClC,OAAO,sBAAsB,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB,EAAE,QAAuB;IAC9E,8DAA8D;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC;QAEtC,wDAAwD;QACxD,IAAI,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,kCAAkC;YAClC,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC5D,OAAO,OAAO,CAAC,EAAE,GAAG,GAAG,GAAG,SAAS,CAAC;QACrC,CAAC;QAED,8CAA8C;QAC9C,IAAI,YAAY,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,EAAE,CAAC;QACnB,CAAC;IACF,CAAC;IAED,2CAA2C;IAC3C,qBAAqB;IACrB,gDAAgD;IAChD,sDAAsD;IACtD,OAAO,YAAY,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the monorepo root by searching upward for package.json with workspaces
|
|
3
|
+
*/
|
|
4
|
+
export declare function getMonorepoRoot(): string;
|
|
5
|
+
/**
|
|
6
|
+
* Get the features directory path
|
|
7
|
+
*/
|
|
8
|
+
export declare function getFeaturesDir(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Get the directory path for a specific feature
|
|
11
|
+
*/
|
|
12
|
+
export declare function getFeatureDir(featureName: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a file path within a feature
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveFeatureFile(featureName: string, filePath: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get the SFDX project template path
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSfdxProjectTemplatePath(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Get the site-container template path (force-app/main/default with digitalExperienceConfigs, etc.)
|
|
23
|
+
*/
|
|
24
|
+
export declare function getSiteContainerTemplatePath(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Get the web application path in SFDX structure
|
|
27
|
+
* Structure: force-app/main/default/webapplications/<appName>
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSfdxWebApplicationPath(targetDir: string, appName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Translate a feature file path to the corresponding base app path
|
|
32
|
+
* Replaces feature name with base app name in the nested structure
|
|
33
|
+
*
|
|
34
|
+
* Handles multiple formats:
|
|
35
|
+
* 1. SFDX path: "force-app/main/default/webapplications/feature-simple/src/routes.tsx"
|
|
36
|
+
* → "force-app/main/default/webapplications/base-app/src/routes.tsx" (SFDX structure)
|
|
37
|
+
* → "webapplications/base-app/src/routes.tsx" (legacy structure)
|
|
38
|
+
* 2. Full path: "webapplications/feature-simple/src/routes.tsx"
|
|
39
|
+
* → "webapplications/base-app/src/routes.tsx"
|
|
40
|
+
* 3. WebApp path: "webApp/src/routes.tsx"
|
|
41
|
+
* → "webapplications/base-app/src/routes.tsx"
|
|
42
|
+
* 4. Other SFDX paths: "classes/NavMenu.cls"
|
|
43
|
+
* → "classes/NavMenu.cls" (unchanged, stays at root)
|
|
44
|
+
*/
|
|
45
|
+
export declare function translatePathToBaseApp(featurePath: string, featureName: string, baseAppPath: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Translate a feature file path to use a target app name in SFDX structure
|
|
48
|
+
* Replaces feature name with target app name in the nested structure
|
|
49
|
+
*
|
|
50
|
+
* Handles multiple formats:
|
|
51
|
+
* 1. SFDX path: "force-app/main/default/webapplications/feature-simple/src/routes.tsx"
|
|
52
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
53
|
+
* 2. Full path: "webapplications/feature-simple/src/routes.tsx"
|
|
54
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
55
|
+
* 3. WebApp path: "webApp/src/routes.tsx"
|
|
56
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
57
|
+
* 4. Other SFDX paths: "classes/NavMenu.cls"
|
|
58
|
+
* → "force-app/main/default/classes/NavMenu.cls" (moved to SFDX structure)
|
|
59
|
+
*/
|
|
60
|
+
export declare function translatePathToTargetApp(featurePath: string, featureName: string, targetAppName: string): string;
|
|
61
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAiBxC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAWrD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACrC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GACjB,MAAM,CAoDR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CACvC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACnB,MAAM,CAwCR"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "fs";
|
|
7
|
+
import { join, dirname, basename } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
/**
|
|
10
|
+
* Find the monorepo root by searching upward for package.json with workspaces
|
|
11
|
+
*/
|
|
12
|
+
export function getMonorepoRoot() {
|
|
13
|
+
let currentDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
while (currentDir !== "/") {
|
|
15
|
+
const packageJsonPath = join(currentDir, "package.json");
|
|
16
|
+
if (existsSync(packageJsonPath)) {
|
|
17
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
18
|
+
if (packageJson.workspaces) {
|
|
19
|
+
return currentDir;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
currentDir = dirname(currentDir);
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Could not find monorepo root (package.json with workspaces)");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the features directory path
|
|
28
|
+
*/
|
|
29
|
+
export function getFeaturesDir() {
|
|
30
|
+
return join(getMonorepoRoot(), "packages", "template", "feature");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the directory path for a specific feature
|
|
34
|
+
*/
|
|
35
|
+
export function getFeatureDir(featureName) {
|
|
36
|
+
return join(getFeaturesDir(), featureName);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a file path within a feature
|
|
40
|
+
*/
|
|
41
|
+
export function resolveFeatureFile(featureName, filePath) {
|
|
42
|
+
return join(getFeatureDir(featureName), filePath);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the SFDX project template path
|
|
46
|
+
*/
|
|
47
|
+
export function getSfdxProjectTemplatePath() {
|
|
48
|
+
return join(getMonorepoRoot(), "packages", "template", "template", "template-sfdx-project");
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get the site-container template path (force-app/main/default with digitalExperienceConfigs, etc.)
|
|
52
|
+
*/
|
|
53
|
+
export function getSiteContainerTemplatePath() {
|
|
54
|
+
return join(getMonorepoRoot(), "packages", "template", "template", "template-site-container", "force-app", "main", "default");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the web application path in SFDX structure
|
|
58
|
+
* Structure: force-app/main/default/webapplications/<appName>
|
|
59
|
+
*/
|
|
60
|
+
export function getSfdxWebApplicationPath(targetDir, appName) {
|
|
61
|
+
return join(targetDir, "force-app", "main", "default", "webapplications", appName);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Translate a feature file path to the corresponding base app path
|
|
65
|
+
* Replaces feature name with base app name in the nested structure
|
|
66
|
+
*
|
|
67
|
+
* Handles multiple formats:
|
|
68
|
+
* 1. SFDX path: "force-app/main/default/webapplications/feature-simple/src/routes.tsx"
|
|
69
|
+
* → "force-app/main/default/webapplications/base-app/src/routes.tsx" (SFDX structure)
|
|
70
|
+
* → "webapplications/base-app/src/routes.tsx" (legacy structure)
|
|
71
|
+
* 2. Full path: "webapplications/feature-simple/src/routes.tsx"
|
|
72
|
+
* → "webapplications/base-app/src/routes.tsx"
|
|
73
|
+
* 3. WebApp path: "webApp/src/routes.tsx"
|
|
74
|
+
* → "webapplications/base-app/src/routes.tsx"
|
|
75
|
+
* 4. Other SFDX paths: "classes/NavMenu.cls"
|
|
76
|
+
* → "classes/NavMenu.cls" (unchanged, stays at root)
|
|
77
|
+
*/
|
|
78
|
+
export function translatePathToBaseApp(featurePath, featureName, baseAppPath) {
|
|
79
|
+
// Extract base app name from base app path (last directory component)
|
|
80
|
+
const baseAppName = basename(baseAppPath);
|
|
81
|
+
const sfdxPrefix = "force-app/main/default/";
|
|
82
|
+
const webAppPrefix = "webapplications/";
|
|
83
|
+
// Check for SFDX structure path
|
|
84
|
+
if (featurePath.startsWith(sfdxPrefix + webAppPrefix)) {
|
|
85
|
+
// SFDX path format: force-app/main/default/webapplications/<feature-name>/...
|
|
86
|
+
const remainder = featurePath.substring((sfdxPrefix + webAppPrefix).length);
|
|
87
|
+
if (remainder.startsWith(featureName + "/")) {
|
|
88
|
+
// Replace feature name with base app name
|
|
89
|
+
const pathAfterFeatureName = remainder.substring(featureName.length + 1);
|
|
90
|
+
// Check if base app uses SFDX structure
|
|
91
|
+
if (existsSync(join(baseAppPath, "src", "force-app"))) {
|
|
92
|
+
// Base app uses SFDX structure - include src/ prefix
|
|
93
|
+
return `src/${sfdxPrefix}${webAppPrefix}${baseAppName}/${pathAfterFeatureName}`;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Base app uses legacy structure
|
|
97
|
+
return `${webAppPrefix}${baseAppName}/${pathAfterFeatureName}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Pattern: webapplications/<feature-name>/...
|
|
102
|
+
if (featurePath.startsWith(webAppPrefix)) {
|
|
103
|
+
// Full path format - remove prefix to get: <feature-name>/...
|
|
104
|
+
const remainder = featurePath.substring(webAppPrefix.length);
|
|
105
|
+
// Check if it starts with the feature name
|
|
106
|
+
if (remainder.startsWith(featureName + "/")) {
|
|
107
|
+
// Replace feature name with base app name
|
|
108
|
+
const pathAfterFeatureName = remainder.substring(featureName.length + 1);
|
|
109
|
+
// Match base app structure (SFDX vs legacy)
|
|
110
|
+
if (existsSync(join(baseAppPath, "src", "force-app"))) {
|
|
111
|
+
return `src/${sfdxPrefix}${webAppPrefix}${baseAppName}/${pathAfterFeatureName}`;
|
|
112
|
+
}
|
|
113
|
+
return `${webAppPrefix}${baseAppName}/${pathAfterFeatureName}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (featurePath.startsWith("webApp/")) {
|
|
117
|
+
// WebApp path - strip webApp/ prefix and add full webapplications path
|
|
118
|
+
const pathAfterWebApp = featurePath.substring("webApp/".length);
|
|
119
|
+
if (existsSync(join(baseAppPath, "src", "force-app"))) {
|
|
120
|
+
return `src/${sfdxPrefix}${webAppPrefix}${baseAppName}/${pathAfterWebApp}`;
|
|
121
|
+
}
|
|
122
|
+
return `${webAppPrefix}${baseAppName}/${pathAfterWebApp}`;
|
|
123
|
+
}
|
|
124
|
+
// All other paths (SFDX metadata, etc.) - return as is (stays at root level)
|
|
125
|
+
return featurePath;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Translate a feature file path to use a target app name in SFDX structure
|
|
129
|
+
* Replaces feature name with target app name in the nested structure
|
|
130
|
+
*
|
|
131
|
+
* Handles multiple formats:
|
|
132
|
+
* 1. SFDX path: "force-app/main/default/webapplications/feature-simple/src/routes.tsx"
|
|
133
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
134
|
+
* 2. Full path: "webapplications/feature-simple/src/routes.tsx"
|
|
135
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
136
|
+
* 3. WebApp path: "webApp/src/routes.tsx"
|
|
137
|
+
* → "force-app/main/default/webapplications/target-app/src/routes.tsx"
|
|
138
|
+
* 4. Other SFDX paths: "classes/NavMenu.cls"
|
|
139
|
+
* → "force-app/main/default/classes/NavMenu.cls" (moved to SFDX structure)
|
|
140
|
+
*/
|
|
141
|
+
export function translatePathToTargetApp(featurePath, featureName, targetAppName) {
|
|
142
|
+
const sfdxPrefix = "force-app/main/default/";
|
|
143
|
+
const webAppPrefix = "webapplications/";
|
|
144
|
+
// Check for SFDX structure path (already has force-app prefix)
|
|
145
|
+
if (featurePath.startsWith(sfdxPrefix + webAppPrefix)) {
|
|
146
|
+
// SFDX path format: force-app/main/default/webapplications/<feature-name>/...
|
|
147
|
+
const remainder = featurePath.substring((sfdxPrefix + webAppPrefix).length);
|
|
148
|
+
if (remainder.startsWith(featureName + "/")) {
|
|
149
|
+
// Replace feature name with target app name
|
|
150
|
+
const pathAfterFeatureName = remainder.substring(featureName.length + 1);
|
|
151
|
+
return `${sfdxPrefix}${webAppPrefix}${targetAppName}/${pathAfterFeatureName}`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Pattern: webapplications/<feature-name>/...
|
|
155
|
+
if (featurePath.startsWith(webAppPrefix)) {
|
|
156
|
+
// Full path format - remove prefix to get: <feature-name>/...
|
|
157
|
+
const remainder = featurePath.substring(webAppPrefix.length);
|
|
158
|
+
// Check if it starts with the feature name
|
|
159
|
+
if (remainder.startsWith(featureName + "/")) {
|
|
160
|
+
// Replace feature name with target app name and add SFDX prefix
|
|
161
|
+
const pathAfterFeatureName = remainder.substring(featureName.length + 1);
|
|
162
|
+
return `${sfdxPrefix}${webAppPrefix}${targetAppName}/${pathAfterFeatureName}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (featurePath.startsWith("webApp/")) {
|
|
166
|
+
// WebApp path - strip webApp/ prefix and add full SFDX webapplications path
|
|
167
|
+
const pathAfterWebApp = featurePath.substring("webApp/".length);
|
|
168
|
+
return `${sfdxPrefix}${webAppPrefix}${targetAppName}/${pathAfterWebApp}`;
|
|
169
|
+
}
|
|
170
|
+
// All other paths (SFDX metadata, etc.) - move to SFDX structure
|
|
171
|
+
// e.g., "classes/NavMenu.cls" → "force-app/main/default/classes/NavMenu.cls"
|
|
172
|
+
// But skip if already has SFDX prefix
|
|
173
|
+
if (featurePath.startsWith(sfdxPrefix)) {
|
|
174
|
+
return featurePath;
|
|
175
|
+
}
|
|
176
|
+
return `${sfdxPrefix}${featurePath}`;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Project } from "ts-morph";
|
|
2
|
+
/**
|
|
3
|
+
* Route Merging Strategy: Replace-Matching with Deep Children Merge
|
|
4
|
+
*
|
|
5
|
+
* This function merges React Router routes from a feature into a base app using
|
|
6
|
+
* a "replace-matching" strategy with intelligent children array merging.
|
|
7
|
+
*
|
|
8
|
+
* ## How It Works:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Top-Level Routes:**
|
|
11
|
+
* - Routes with the SAME path → Merge their children arrays
|
|
12
|
+
* - Routes with DIFFERENT paths → Add feature route to result
|
|
13
|
+
*
|
|
14
|
+
* 2. **Children Array Merging (when parent paths match):**
|
|
15
|
+
* - Index routes (`index: true`) → Feature replaces base if both exist
|
|
16
|
+
* - Named routes (`path: 'about'`) → Feature replaces base if paths match
|
|
17
|
+
* - New routes → Added to children array
|
|
18
|
+
* - Preserves base routes not in feature
|
|
19
|
+
*
|
|
20
|
+
* 3. **Route Deletion:**
|
|
21
|
+
* - Routes with path starting with `__delete__` are deletion markers
|
|
22
|
+
* - The route with matching path (without prefix) is removed from result
|
|
23
|
+
* - Example: `{ path: '__delete__new' }` removes the route with `path: 'new'`
|
|
24
|
+
*
|
|
25
|
+
* 4. **Recursion:**
|
|
26
|
+
* - Applies same logic to nested children arrays
|
|
27
|
+
*
|
|
28
|
+
* ## Example:
|
|
29
|
+
*
|
|
30
|
+
* **Base App Routes:**
|
|
31
|
+
* ```typescript
|
|
32
|
+
* [{
|
|
33
|
+
* path: '/',
|
|
34
|
+
* element: <AppLayout />,
|
|
35
|
+
* children: [
|
|
36
|
+
* { index: true, element: <Home /> }
|
|
37
|
+
* ]
|
|
38
|
+
* }]
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* **Feature Routes:**
|
|
42
|
+
* ```typescript
|
|
43
|
+
* [{
|
|
44
|
+
* path: '/',
|
|
45
|
+
* element: <AppLayout />,
|
|
46
|
+
* children: [
|
|
47
|
+
* { path: 'about', element: <About /> },
|
|
48
|
+
* { path: 'contact', element: <Contact /> }
|
|
49
|
+
* ]
|
|
50
|
+
* }]
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* **Merged Result:**
|
|
54
|
+
* ```typescript
|
|
55
|
+
* [{
|
|
56
|
+
* path: '/',
|
|
57
|
+
* element: <AppLayout />, // Uses feature's element
|
|
58
|
+
* children: [
|
|
59
|
+
* { index: true, element: <Home /> }, // Preserved from base
|
|
60
|
+
* { path: 'about', element: <About /> }, // Added from feature
|
|
61
|
+
* { path: 'contact', element: <Contact /> } // Added from feature
|
|
62
|
+
* ]
|
|
63
|
+
* }]
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* ## Deletion Example:
|
|
67
|
+
*
|
|
68
|
+
* **Base/Previous Routes:**
|
|
69
|
+
* ```typescript
|
|
70
|
+
* [{
|
|
71
|
+
* path: '/',
|
|
72
|
+
* children: [
|
|
73
|
+
* { path: 'home', element: <Home /> },
|
|
74
|
+
* { path: 'about', element: <About /> },
|
|
75
|
+
* { path: 'new', element: <New /> }
|
|
76
|
+
* ]
|
|
77
|
+
* }]
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* **Feature Routes (deleting 'new'):**
|
|
81
|
+
* ```typescript
|
|
82
|
+
* [{
|
|
83
|
+
* path: '/',
|
|
84
|
+
* children: [
|
|
85
|
+
* { path: '__delete__new', element: <></> }
|
|
86
|
+
* ]
|
|
87
|
+
* }]
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* **Merged Result:**
|
|
91
|
+
* ```typescript
|
|
92
|
+
* [{
|
|
93
|
+
* path: '/',
|
|
94
|
+
* children: [
|
|
95
|
+
* { path: 'home', element: <Home /> }, // Preserved
|
|
96
|
+
* { path: 'about', element: <About /> } // Preserved
|
|
97
|
+
* // 'new' route removed
|
|
98
|
+
* ]
|
|
99
|
+
* }]
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @param featurePath - Path to the feature's routes.tsx file
|
|
103
|
+
* @param targetPath - Path to the base app's routes.tsx file
|
|
104
|
+
* @returns The merged routes source code
|
|
105
|
+
*/
|
|
106
|
+
export declare function mergeRoutes(featurePath: string, targetPath: string, project?: Project): string;
|
|
107
|
+
//# sourceMappingURL=route-merger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-merger.d.ts","sourceRoot":"","sources":["../../src/utils/route-merger.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAiD,MAAM,UAAU,CAAC;AAkBlF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CA0D9F"}
|