@salesforce/webapp-template-cli-experimental 1.42.0 → 1.43.1

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/README.md CHANGED
@@ -19,14 +19,14 @@ npm run build --workspace=@salesforce/webapp-template-cli-experimental
19
19
  npm run apply-patches -- <feature-path> <app-path> <target-dir>
20
20
 
21
21
  # Examples:
22
- # Apply navigation-menu patches to my-app (using base-react-app as reference)
23
- npm run apply-patches -- packages/feature/feature-react-nav-menu packages/base-app/base-react-app my-app
22
+ # Apply shadcn UI patches to my-app (using base-react-app as reference)
23
+ npm run apply-patches -- packages/template/feature/feature-react-shadcn packages/template/base-app/base-react-app my-app
24
24
 
25
25
  # Skip dependency installation
26
- npm run apply-patches -- packages/feature/feature-react-nav-menu packages/base-app/base-react-app my-app --skip-dependency-changes
26
+ npm run apply-patches -- packages/template/feature/feature-react-shadcn packages/template/base-app/base-react-app my-app --skip-dependency-changes
27
27
 
28
28
  # Reset target directory to base app state before applying (preserves node_modules)
29
- npm run apply-patches -- packages/feature/feature-react-nav-menu packages/base-app/base-react-app my-app --reset
29
+ npm run apply-patches -- packages/template/feature/feature-react-shadcn packages/template/base-app/base-react-app my-app --reset
30
30
  ```
31
31
 
32
32
  ### Direct usage
@@ -141,9 +141,9 @@ The CLI tool:
141
141
  ### Example: Apply feature patches to create a new app
142
142
 
143
143
  ```bash
144
- $ npm run apply-patches -- packages/feature/feature-react-nav-menu packages/base-app/base-react-app my-app
144
+ $ npm run apply-patches -- packages/template/feature/feature-react-shadcn packages/template/base-app/base-react-app my-app
145
145
 
146
- Applying patches: packages/feature-react-nav-menu → my-app
146
+ Applying patches: packages/template/feature/feature-react-shadcn → my-app
147
147
  ℹ Validating paths...
148
148
  ✓ Validation passed
149
149
  ℹ Creating target directory my-app...
@@ -153,17 +153,14 @@ Resolving Dependencies
153
153
  ℹ No dependencies to resolve
154
154
 
155
155
 
156
- Applying: packages/feature-react-nav-menu
156
+ Applying: packages/template/feature/feature-react-shadcn
157
157
  ℹ Discovering files...
158
- ℹ Found 6 file(s)
158
+ ℹ Found 14 file(s)
159
159
  ℹ Validating paths...
160
160
  ✓ Paths validated
161
- ✓ Added webapplications/feature-react-nav-menu/src/navigationMenu.tsx
162
- ✓ Added webapplications/feature-react-nav-menu/src/appLayout.tsx
163
- ✓ Added webapplications/feature-react-nav-menu/src/routes.tsx
164
- ✓ Added webapplications/feature-react-nav-menu/src/router-utils.tsx
165
- ✓ Added webapplications/feature-react-nav-menu/src/about.tsx
166
- ✓ Added webapplications/feature-react-nav-menu/src/new.tsx
161
+ ✓ Added webapplications/feature-react-shadcn/src/components/ui/button.tsx
162
+ ✓ Added webapplications/feature-react-shadcn/src/components/ui/card.tsx
163
+ ...
167
164
 
168
165
  Installing dependencies
169
166
  ℹ Installing dependencies...
@@ -249,9 +246,9 @@ export default feature;
249
246
  import type { Feature } from "../cli/src/types.js";
250
247
 
251
248
  const feature: Feature = {
252
- // This feature depends on navigation-menu feature
253
- // navigation-menu will be applied first, then this feature
254
- dependencies: ["packages/feature/feature-react-nav-menu"],
249
+ // This feature depends on shadcn UI feature
250
+ // shadcn will be applied first, then this feature
251
+ dependencies: ["packages/template/feature/feature-react-shadcn"],
255
252
  packageJson: {
256
253
  dependencies: {
257
254
  "some-package": "^1.0.0",
@@ -284,7 +281,7 @@ export default feature;
284
281
  **Notes:**
285
282
 
286
283
  - `templateDir`: All files in this directory will be discovered and applied to the target app
287
- - `webAppName`: Used to construct the default route path and organize files. Defaults to the feature directory name (e.g., `feature-react-nav-menu` → `feature-react-nav-menu`)
284
+ - `webAppName`: Used to construct the default route path and organize files. Defaults to the feature directory name (e.g., `feature-react-shadcn` → `feature-react-shadcn`)
288
285
  - `routeFilePath`: Must be a path relative to `templateDir`. If not specified, defaults to `webapplications/<webAppName>/src/routes.tsx`
289
286
 
290
287
  ## Path Mappings
@@ -293,10 +290,10 @@ Path mappings allow features to use simplified directory structures that are aut
293
290
 
294
291
  ### Default Behavior (Enabled by Default)
295
292
 
296
- By default, all features automatically get the `webApp` mapping, which transforms web application files into the proper nested structure. For example, in `feature-react-nav-menu`:
293
+ By default, all features automatically get the `webApp` mapping, which transforms web application files into the proper nested structure. For example, in `feature-react-shadcn`:
297
294
 
298
295
  ```
299
- template/webApp/src/app.tsx → dist/webapplications/feature-react-nav-menu/src/app.tsx
296
+ template/webApp/src/app.tsx → dist/webapplications/feature-react-shadcn/src/app.tsx
300
297
  ```
301
298
 
302
299
  This simplifies feature templates by removing the repetitive nested directory structure.
@@ -304,12 +301,12 @@ This simplifies feature templates by removing the repetitive nested directory st
304
301
  **Important**: Only files under `webApp/` get the nested structure. SFDX metadata types (like `classes/`, `triggers/`, `objects/`, `lwc/`, etc.) are placed at root level:
305
302
 
306
303
  ```
307
- feature-react-nav-menu/template/
304
+ feature-react-shadcn/template/
308
305
  ├── webApp/
309
306
  │ └── src/
310
- │ └── app.tsx → dist/webapplications/feature-react-nav-menu/src/app.tsx
307
+ │ └── app.tsx → dist/webapplications/feature-react-shadcn/src/app.tsx
311
308
  └── classes/
312
- └── NavMenu.cls → dist/classes/NavMenu.cls (root level)
309
+ └── MyClass.cls → dist/classes/MyClass.cls (root level)
313
310
  ```
314
311
 
315
312
  ### Using the Default Mapping
@@ -506,26 +503,26 @@ Application order: C → B → A (dependencies first)
506
503
 
507
504
  The CLI builds a complete dependency graph and applies features in topological order.
508
505
 
509
- ### Example: Building on Navigation Features
506
+ ### Example: Building on Shared UI Features
510
507
 
511
508
  ```typescript
512
- // packages/feature/feature-react-nav-menu/feature.ts
509
+ // packages/template/feature/feature-react-shadcn/feature.ts
513
510
  import type { Feature } from "../../../cli/src/types.js";
514
511
 
515
512
  const feature: Feature = {
516
- // Navigation menu has no dependencies
513
+ // Shadcn UI has no dependencies
517
514
  };
518
515
 
519
516
  export default feature;
520
517
  ```
521
518
 
522
519
  ```typescript
523
- // packages/feature/feature-admin-dashboard/feature.ts
520
+ // packages/template/feature/feature-admin-dashboard/feature.ts
524
521
  import type { Feature } from "../../../cli/src/types.js";
525
522
 
526
523
  const feature: Feature = {
527
- // Admin dashboard builds on top of navigation menu
528
- dependencies: ["packages/feature/feature-react-nav-menu"],
524
+ // Admin dashboard builds on top of shadcn UI
525
+ dependencies: ["packages/template/feature/feature-react-shadcn"],
529
526
  };
530
527
 
531
528
  export default feature;
@@ -533,10 +530,10 @@ export default feature;
533
530
 
534
531
  When you apply `feature-admin-dashboard`:
535
532
 
536
- 1. CLI resolves `feature-react-nav-menu` as a dependency
537
- 2. Applies `feature-react-nav-menu` first (navigation menu files and routes)
533
+ 1. CLI resolves `feature-react-shadcn` as a dependency
534
+ 2. Applies `feature-react-shadcn` first (UI components)
538
535
  3. Applies `feature-admin-dashboard` second (dashboard files and routes)
539
- 4. Result: App has both navigation menu and admin dashboard
536
+ 4. Result: App has both shared UI and admin dashboard
540
537
 
541
538
  ### Nested Dependencies
542
539
 
@@ -577,11 +574,11 @@ When multiple features modify the same file:
577
574
  Example:
578
575
 
579
576
  ```
580
- feature-react-nav-menu provides: src/appLayout.tsx
577
+ feature-react-shadcn provides: src/appLayout.tsx
581
578
  feature-custom-app also provides: src/appLayout.tsx
582
579
 
583
580
  When applying feature-custom-app:
584
- 1. navigation-menu's appLayout.tsx is applied
581
+ 1. shadcn's appLayout.tsx is applied
585
582
  2. custom-app's appLayout.tsx overwrites it
586
583
  3. Final result: custom-app's version is used
587
584
  ```
@@ -638,7 +635,7 @@ Routes accumulate across all features, preserving routes from base app and all d
638
635
 
639
636
  Dependency paths can be:
640
637
 
641
- - **Relative to monorepo root**: `'packages/feature/feature-react-nav-menu'`
638
+ - **Relative to monorepo root**: `'packages/template/feature/feature-react-shadcn'`
642
639
  - **Absolute paths**: `'/absolute/path/to/feature'`
643
640
 
644
641
  The CLI normalizes and resolves all paths consistently.
@@ -1534,7 +1531,7 @@ You can set default options for all projects in `nx.json`:
1534
1531
 
1535
1532
  #### `build-dist-app`
1536
1533
 
1537
- Builds the application in the dist folder by running `npm ci` and `npm run build`. This executor is useful for building feature apps after patches have been applied.
1534
+ Builds the application in the dist folder by running `npm ci` (or `npm install` when no `package-lock.json` exists) and `npm run build`. This executor is useful for building feature apps after patches have been applied.
1538
1535
 
1539
1536
  **Usage in `package.json`:**
1540
1537
 
@@ -1594,7 +1591,7 @@ nx run-many -t build test
1594
1591
 
1595
1592
  2. **build-dist-app executor**:
1596
1593
  - Locates the built application in `dist/force-app/main/default/webapplications/<project-name>/`
1597
- - Runs `npm ci` to install dependencies
1594
+ - Runs `npm ci` to install dependencies (or `npm install` when no `package-lock.json` exists)
1598
1595
  - Runs `npm run build` to build the application
1599
1596
  - Suitable for CI/CD pipelines and automated testing
1600
1597
 
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/apply-patches/executor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAA8B,WAAW,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,0BAA0B,CAAC,CAiFrC"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/apply-patches/executor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAA8B,WAAW,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,0BAA0B,CAAC,CA6DrC"}
@@ -4,8 +4,9 @@
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
6
  import { execSync } from "child_process";
7
- import { basename, join } from "path";
7
+ import { join } from "path";
8
8
  import { logger } from "@nx/devkit";
9
+ import { createProjectPaths } from "../utils";
9
10
  /**
10
11
  * Nx executor for applying template patches
11
12
  *
@@ -18,30 +19,18 @@ import { logger } from "@nx/devkit";
18
19
  */
19
20
  export default async function runExecutor(options, context) {
20
21
  try {
21
- // Validate that we have a project name
22
- if (!context.projectName) {
23
- logger.error("Project name is required");
24
- return { success: false };
25
- }
26
- // Get project configuration
27
- const project = context.projectGraph?.nodes[context.projectName];
28
- if (!project) {
29
- logger.error(`Project ${context.projectName} not found in project graph`);
22
+ const projectPaths = createProjectPaths(context);
23
+ if (!projectPaths) {
30
24
  return { success: false };
31
25
  }
32
26
  // Get workspace root (absolute path)
33
27
  const workspaceRoot = context.root;
34
- // Get project root (relative to workspace root)
35
- const projectRoot = project.data.root;
36
- // Get the folder name from the project root path
37
- const projectFolderName = basename(projectRoot);
38
28
  // Build paths for CLI command
29
+ const featurePath = projectPaths.root;
39
30
  const baseAppPath = options.baseAppPath || "packages/template/base-app/base-react-app";
40
- const outputPath = join(projectRoot, "dist");
41
- // Build the path to webapp
42
- const webAppPath = join(outputPath, "force-app/main/default/webapplications", projectFolderName);
31
+ const outputPath = projectPaths.dist;
43
32
  logger.info(`Applying patches for ${context.projectName}...`);
44
- logger.info(` Feature path: ${projectRoot}`);
33
+ logger.info(` Feature path: ${featurePath}`);
45
34
  logger.info(` Base app: ${baseAppPath}`);
46
35
  logger.info(` Output: ${outputPath}`);
47
36
  // Execute the CLI command via npx tsx
@@ -51,7 +40,7 @@ export default async function runExecutor(options, context) {
51
40
  * when it comes to `feature.ts`
52
41
  */
53
42
  // Build command with arguments
54
- let command = `npx tsx ${cliPath} apply-patches ${projectRoot} ${baseAppPath} ${outputPath}`;
43
+ let command = `npx tsx ${cliPath} apply-patches ${featurePath} ${baseAppPath} ${outputPath}`;
55
44
  // Add flags
56
45
  if (options.reset !== false) {
57
46
  command += " --reset";
@@ -66,7 +55,7 @@ export default async function runExecutor(options, context) {
66
55
  env: process.env,
67
56
  });
68
57
  // Clean up node_modules to prevent it from being cached
69
- const nodeModulesPath = join(webAppPath, "node_modules");
58
+ const nodeModulesPath = join(projectPaths.webApp, "node_modules");
70
59
  logger.info(`\n\nRemoving ${nodeModulesPath} to exclude from Nx cache...`);
71
60
  execSync(`rm -rf "${nodeModulesPath}"`, {
72
61
  cwd: workspaceRoot,
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/apply-patches/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/apply-patches/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAS9C;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACxC,OAAoC,EACpC,OAAwB;IAExB,IAAI,CAAC;QACJ,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,qCAAqC;QACrC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;QAEnC,8BAA8B;QAC9B,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,2CAA2C,CAAC;QACvF,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC;QAErC,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,WAAW,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,eAAe,WAAW,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;QAEvC,sCAAsC;QACtC,MAAM,OAAO,GAAG,oCAAoC,CAAC;QAErD;;;WAGG;QAEH,+BAA+B;QAC/B,IAAI,OAAO,GAAG,WAAW,OAAO,kBAAkB,WAAW,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;QAE7F,YAAY;QACZ,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAC7B,OAAO,IAAI,UAAU,CAAC;QACvB,CAAC;QACD,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;YACnC,OAAO,IAAI,4BAA4B,CAAC;QACzC,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QAEvC,QAAQ,CAAC,OAAO,EAAE;YACjB,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,wDAAwD;QACxD,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,gBAAgB,eAAe,8BAA8B,CAAC,CAAC;QAC3E,QAAQ,CAAC,WAAW,eAAe,GAAG,EAAE;YACvC,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,SAAS;SAChB,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC;QACzD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;AACF,CAAC"}
@@ -9,7 +9,8 @@ export interface BuildDistAppExecutorResult {
9
9
  /**
10
10
  * Nx executor for building the application in the dist folder
11
11
  *
12
- * This executor navigates to the project's dist folder and runs npm ci followed by npm run build.
12
+ * This executor navigates to the project's dist folder and runs npm ci (or npm install when
13
+ * no package-lock.json exists) followed by npm run build.
13
14
  *
14
15
  * @param options - Executor options
15
16
  * @param context - Nx executor context
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/build-dist-app/executor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAA8B,WAAW,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,0BAA0B,CAAC,CAyDrC"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/build-dist-app/executor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAA8B,WAAW,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,0BAA0B,CAAC,CAkCrC"}
@@ -4,12 +4,15 @@
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
6
  import { execSync } from "child_process";
7
- import { join, basename } from "path";
7
+ import { existsSync } from "fs";
8
+ import { join } from "path";
8
9
  import { logger } from "@nx/devkit";
10
+ import { createProjectPaths } from "../utils";
9
11
  /**
10
12
  * Nx executor for building the application in the dist folder
11
13
  *
12
- * This executor navigates to the project's dist folder and runs npm ci followed by npm run build.
14
+ * This executor navigates to the project's dist folder and runs npm ci (or npm install when
15
+ * no package-lock.json exists) followed by npm run build.
13
16
  *
14
17
  * @param options - Executor options
15
18
  * @param context - Nx executor context
@@ -17,40 +20,26 @@ import { logger } from "@nx/devkit";
17
20
  */
18
21
  export default async function runExecutor(options, context) {
19
22
  try {
20
- // Validate that we have a project name
21
- if (!context.projectName) {
22
- logger.error("Project name is required");
23
+ const projectPaths = createProjectPaths(context);
24
+ if (!projectPaths) {
23
25
  return { success: false };
24
26
  }
25
- // Get project configuration
26
- const project = context.projectGraph?.nodes[context.projectName];
27
- if (!project) {
28
- logger.error(`Project ${context.projectName} not found in project graph`);
29
- return { success: false };
30
- }
31
- // Get workspace root (absolute path)
32
- const workspaceRoot = context.root;
33
- // Get project root (relative to workspace root)
34
- const projectRoot = project.data.root;
35
- // Get the folder name from the project root path
36
- const projectFolderName = basename(projectRoot);
37
- // Build the path to the dist folder (static path)
38
- const targetPath = join(workspaceRoot, projectRoot, "dist/force-app/main/default/webapplications", projectFolderName);
27
+ // Build absolute path to the web app
28
+ const targetPath = join(context.root, projectPaths.webApp);
39
29
  logger.info(`Building application in ${targetPath}...`);
40
- // Execute npm ci
41
- logger.info("Running npm ci...");
42
- execSync("npm ci", {
43
- cwd: targetPath,
44
- stdio: "inherit",
45
- env: process.env,
46
- });
30
+ const execOptions = { cwd: targetPath, stdio: "inherit", env: process.env };
31
+ const hasLockfile = existsSync(join(targetPath, "package-lock.json"));
32
+ if (hasLockfile) {
33
+ logger.info("Running npm ci...");
34
+ execSync("npm ci", execOptions);
35
+ }
36
+ else {
37
+ logger.info("No package-lock.json found; running npm install...");
38
+ execSync("npm install", execOptions);
39
+ }
47
40
  // Execute npm run build
48
41
  logger.info("Running npm run build...");
49
- execSync("npm run build", {
50
- cwd: targetPath,
51
- stdio: "inherit",
52
- env: process.env,
53
- });
42
+ execSync("npm run build", execOptions);
54
43
  logger.info("Build completed successfully");
55
44
  return { success: true };
56
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/build-dist-app/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACxC,OAAoC,EACpC,OAAwB;IAExB,IAAI,CAAC;QACJ,uCAAuC;QACvC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;YACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,4BAA4B;QAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,WAAW,6BAA6B,CAAC,CAAC;YAC1E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,qCAAqC;QACrC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;QAEnC,gDAAgD;QAChD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAEtC,iDAAiD;QACjD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QAEhD,kDAAkD;QAClD,MAAM,UAAU,GAAG,IAAI,CACtB,aAAa,EACb,WAAW,EACX,6CAA6C,EAC7C,iBAAiB,CACjB,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,2BAA2B,UAAU,KAAK,CAAC,CAAC;QAExD,iBAAiB;QACjB,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACjC,QAAQ,CAAC,QAAQ,EAAE;YAClB,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,wBAAwB;QACxB,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxC,QAAQ,CAAC,eAAe,EAAE;YACzB,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/build-dist-app/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAwB,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAS9C;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACxC,OAAoC,EACpC,OAAwB;IAExB,IAAI,CAAC;QACJ,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,qCAAqC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QAE3D,MAAM,CAAC,IAAI,CAAC,2BAA2B,UAAU,KAAK,CAAC,CAAC;QAExD,MAAM,WAAW,GAAoB,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QAE7F,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACtE,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;YAClE,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACtC,CAAC;QAED,wBAAwB;QACxB,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QAEvC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;AACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type ExecutorContext } from "@nx/devkit";
2
+ import type { DevServerExecutorOptions } from "./schema";
3
+ /**
4
+ * Result of the executor
5
+ */
6
+ export interface DevServerExecutorResult {
7
+ success: boolean;
8
+ }
9
+ /**
10
+ * Nx executor for starting the dev server
11
+ *
12
+ * This executor starts a Vite dev server for the web application.
13
+ * It runs npm install first, then starts the dev server asynchronously.
14
+ *
15
+ * @param options - Executor options
16
+ * @param context - Nx executor context
17
+ * @returns Async generator yielding executor results
18
+ */
19
+ export default function runExecutor(options: DevServerExecutorOptions, context: ExecutorContext): AsyncGenerator<DevServerExecutorResult>;
20
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/dev-server/executor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGzD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAA+B,WAAW,CACzC,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,eAAe,GACtB,cAAc,CAAC,uBAAuB,CAAC,CA8CzC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { execSync, spawn } from "child_process";
7
+ import { join } from "path";
8
+ import { logger } from "@nx/devkit";
9
+ import { createProjectPaths } from "../utils";
10
+ /**
11
+ * Nx executor for starting the dev server
12
+ *
13
+ * This executor starts a Vite dev server for the web application.
14
+ * It runs npm install first, then starts the dev server asynchronously.
15
+ *
16
+ * @param options - Executor options
17
+ * @param context - Nx executor context
18
+ * @returns Async generator yielding executor results
19
+ */
20
+ export default async function* runExecutor(options, context) {
21
+ try {
22
+ const projectPaths = createProjectPaths(context);
23
+ if (!projectPaths) {
24
+ yield { success: false };
25
+ return;
26
+ }
27
+ // Build absolute path to the web app
28
+ const targetPath = join(context.root, projectPaths.webApp);
29
+ logger.info(`Starting application dev server in ${targetPath}...`);
30
+ // Execute npm install synchronously (short-lived)
31
+ logger.info("Running npm install...");
32
+ execSync("npm install", { cwd: targetPath, stdio: "inherit", env: process.env });
33
+ // Start dev server asynchronously (long-running)
34
+ logger.info("Running npm run dev...");
35
+ const devServer = spawn("npm", ["run", "dev"], {
36
+ cwd: targetPath,
37
+ stdio: "inherit",
38
+ shell: true,
39
+ env: process.env,
40
+ });
41
+ yield { success: true };
42
+ // Keep running until process exits
43
+ await new Promise((resolve, reject) => {
44
+ devServer.on("exit", (code) => {
45
+ if (code === 0) {
46
+ resolve();
47
+ }
48
+ else {
49
+ reject(new Error(`Dev server exited with code ${code}`));
50
+ }
51
+ });
52
+ devServer.on("error", reject);
53
+ });
54
+ yield { success: true };
55
+ }
56
+ catch (error) {
57
+ const errorMessage = error instanceof Error ? error.message : String(error);
58
+ logger.error(`Failed to start dev server: ${errorMessage}`);
59
+ yield { success: false };
60
+ }
61
+ }
62
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/dev-server/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAS9C;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,CACzC,OAAiC,EACjC,OAAwB;IAExB,IAAI,CAAC;QACJ,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACzB,OAAO;QACR,CAAC;QAED,qCAAqC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QAE3D,MAAM,CAAC,IAAI,CAAC,sCAAsC,UAAU,KAAK,CAAC,CAAC;QAEnE,kDAAkD;QAClD,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACtC,QAAQ,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAEjF,iDAAiD;QACjD,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;YAC9C,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAExB,mCAAmC;QACnC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC7B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBAChB,OAAO,EAAE,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACP,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC1D,CAAC;YACF,CAAC,CAAC,CAAC;YACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;AACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ExecutorContext } from "@nx/devkit";
2
+ interface Paths {
3
+ root: string;
4
+ dist: string;
5
+ webApp: string;
6
+ }
7
+ export declare function createProjectPaths(context: ExecutorContext): null | Paths;
8
+ export {};
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/nx-plugin/executors/utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAE1D,UAAU,KAAK;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,KAAK,CAmBzE"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { basename, join } from "path";
7
+ import { logger } from "@nx/devkit";
8
+ export function createProjectPaths(context) {
9
+ // Validate that we have a project name
10
+ if (!context.projectName) {
11
+ logger.error("Project name is required");
12
+ return null;
13
+ }
14
+ // Get project configuration
15
+ const project = context.projectGraph?.nodes[context.projectName];
16
+ if (!project) {
17
+ logger.error(`Project ${context.projectName} not found in project graph`);
18
+ return null;
19
+ }
20
+ const root = project.data.root;
21
+ const dist = join(root, "dist");
22
+ const webApp = join(dist, "force-app/main/default/webapplications", basename(root));
23
+ return { root, dist, webApp };
24
+ }
25
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/nx-plugin/executors/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAQ1D,MAAM,UAAU,kBAAkB,CAAC,OAAwB;IAC1D,uCAAuC;IACvC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,4BAA4B;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,WAAW,6BAA6B,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,wCAAwC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type ExecutorContext } from "@nx/devkit";
2
+ import type { WatchPatchesExecutorOptions } from "./schema";
3
+ /**
4
+ * Result of the executor
5
+ */
6
+ export interface WatchPatchesExecutorResult {
7
+ success: boolean;
8
+ }
9
+ /**
10
+ * Nx executor for watching template patches
11
+ *
12
+ * This executor wraps the apply-patches CLI command in watch mode and automatically
13
+ * determines paths based on the Nx project configuration.
14
+ *
15
+ * @param options - Executor options
16
+ * @param context - Nx executor context
17
+ * @returns Async generator yielding executor results
18
+ */
19
+ export default function runExecutor(options: WatchPatchesExecutorOptions, context: ExecutorContext): AsyncGenerator<WatchPatchesExecutorResult>;
20
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/watch-patches/executor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,eAAe,EAAU,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAA+B,WAAW,CACzC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,GACtB,cAAc,CAAC,0BAA0B,CAAC,CA4D5C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { spawn } from "child_process";
7
+ import { logger } from "@nx/devkit";
8
+ import { createProjectPaths } from "../utils";
9
+ /**
10
+ * Nx executor for watching template patches
11
+ *
12
+ * This executor wraps the apply-patches CLI command in watch mode and automatically
13
+ * determines paths based on the Nx project configuration.
14
+ *
15
+ * @param options - Executor options
16
+ * @param context - Nx executor context
17
+ * @returns Async generator yielding executor results
18
+ */
19
+ export default async function* runExecutor(options, context) {
20
+ try {
21
+ const projectPaths = createProjectPaths(context);
22
+ if (!projectPaths) {
23
+ yield { success: false };
24
+ return;
25
+ }
26
+ // Get workspace root (absolute path)
27
+ const workspaceRoot = context.root;
28
+ // Build paths for CLI command
29
+ const featurePath = projectPaths.root;
30
+ const baseAppPath = options.baseAppPath || "packages/template/base-app/base-react-app";
31
+ const outputPath = projectPaths.dist;
32
+ logger.info(`Watching patches for ${context.projectName}...`);
33
+ logger.info(` Feature path: ${featurePath}`);
34
+ logger.info(` Base app: ${baseAppPath}`);
35
+ logger.info(` Output: ${outputPath}`);
36
+ // Execute the CLI command via npx tsx
37
+ const cliPath = "packages/template/cli/src/index.ts";
38
+ /*
39
+ * Just in case watchPatchesCommand has issues like applyPatchesCommand (see `apply` executor)
40
+ */
41
+ // Build command with arguments
42
+ const command = `npx tsx ${cliPath} watch-patches ${featurePath} ${baseAppPath} ${outputPath}`;
43
+ logger.info(` Executing: ${command}`);
44
+ const watchProcess = spawn(command, {
45
+ cwd: workspaceRoot,
46
+ stdio: "inherit",
47
+ shell: true,
48
+ env: process.env,
49
+ });
50
+ yield { success: true };
51
+ // Keep running until process exits
52
+ await new Promise((resolve, reject) => {
53
+ watchProcess.on("exit", (code) => {
54
+ if (code === 0) {
55
+ resolve();
56
+ }
57
+ else {
58
+ reject(new Error(`Watch process exited with code ${code}`));
59
+ }
60
+ });
61
+ watchProcess.on("error", reject);
62
+ });
63
+ yield { success: true };
64
+ }
65
+ catch (error) {
66
+ const errorMessage = error instanceof Error ? error.message : String(error);
67
+ logger.error(`Failed to watch patches: ${errorMessage}`);
68
+ yield { success: false };
69
+ }
70
+ }
71
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/nx-plugin/executors/watch-patches/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAwB,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAS9C;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,CACzC,OAAoC,EACpC,OAAwB;IAExB,IAAI,CAAC;QACJ,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACzB,OAAO;QACR,CAAC;QAED,qCAAqC;QACrC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;QAEnC,8BAA8B;QAC9B,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,2CAA2C,CAAC;QACvF,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC;QAErC,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,WAAW,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,eAAe,WAAW,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;QAEvC,sCAAsC;QACtC,MAAM,OAAO,GAAG,oCAAoC,CAAC;QAErD;;WAEG;QAEH,+BAA+B;QAC/B,MAAM,OAAO,GAAG,WAAW,OAAO,kBAAkB,WAAW,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;QAE/F,MAAM,CAAC,IAAI,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QAEvC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE;YACnC,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAExB,mCAAmC;QACnC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBAChB,OAAO,EAAE,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACP,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC7D,CAAC;YACF,CAAC,CAAC,CAAC;YACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC;QACzD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;AACF,CAAC"}
package/executors.json CHANGED
@@ -5,10 +5,20 @@
5
5
  "schema": "./src/nx-plugin/executors/apply-patches/schema.json",
6
6
  "description": "Applies template patches to create feature apps"
7
7
  },
8
+ "watch-patches": {
9
+ "implementation": "./src/nx-plugin/executors/watch-patches/executor.ts",
10
+ "schema": "./src/nx-plugin/executors/watch-patches/schema.json",
11
+ "description": "Watches template patches to create feature apps"
12
+ },
8
13
  "build-dist-app": {
9
14
  "implementation": "./src/nx-plugin/executors/build-dist-app/executor.ts",
10
15
  "schema": "./src/nx-plugin/executors/build-dist-app/schema.json",
11
- "description": "Builds the application in the dist folder by running npm ci and npm run build"
16
+ "description": "Builds the application in the dist folder by running npm ci (or npm install when no package-lock.json) and npm run build"
17
+ },
18
+ "dev-server": {
19
+ "implementation": "./src/nx-plugin/executors/dev-server/executor.ts",
20
+ "schema": "./src/nx-plugin/executors/dev-server/schema.json",
21
+ "description": "Runs the dev server for the application in the dist folder"
12
22
  }
13
23
  }
14
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-template-cli-experimental",
3
- "version": "1.42.0",
3
+ "version": "1.43.1",
4
4
  "description": "CLI tool for applying feature patches to base apps",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "type": "module",
@@ -45,5 +45,5 @@
45
45
  "typescript": "~5.9.3",
46
46
  "vitest": "^4.0.17"
47
47
  },
48
- "gitHead": "5bb3d5e71e337e5eacad83240b8e344fdfd1d6c7"
48
+ "gitHead": "639c5bac6d7004d13246a86c9db4b33667da7c30"
49
49
  }