@nx/react 17.0.3 → 17.0.4

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 (154) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/generators.json +1 -1
  4. package/index.d.ts +1 -0
  5. package/index.js +3 -1
  6. package/mf/dynamic-federation.d.ts +4 -0
  7. package/mf/dynamic-federation.js +75 -0
  8. package/mf/index.d.ts +1 -0
  9. package/mf/index.js +7 -0
  10. package/migrations.json +21 -0
  11. package/package.json +7 -7
  12. package/plugins/component-testing/index.js +52 -24
  13. package/plugins/component-testing/webpack-fallback.js +1 -1
  14. package/plugins/nx-react-webpack-plugin/lib/apply-react-config.d.ts +4 -0
  15. package/plugins/nx-react-webpack-plugin/lib/apply-react-config.js +86 -0
  16. package/plugins/nx-react-webpack-plugin/nx-react-webpack-plugin.d.ts +8 -0
  17. package/plugins/nx-react-webpack-plugin/nx-react-webpack-plugin.js +13 -0
  18. package/plugins/storybook/index.js +6 -2
  19. package/plugins/storybook/merge-plugins.d.ts +1 -1
  20. package/plugins/webpack.d.ts +1 -3
  21. package/plugins/webpack.js +3 -11
  22. package/plugins/with-react.d.ts +2 -4
  23. package/plugins/with-react.js +2 -58
  24. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.d.ts +12 -0
  25. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.js +149 -51
  26. package/src/executors/module-federation-dev-server/schema.json +9 -1
  27. package/src/generators/application/application.js +41 -18
  28. package/src/generators/application/files/base-vite/index.html__tmpl__ +1 -1
  29. package/src/generators/application/files/base-webpack/src/index.html +0 -2
  30. package/src/generators/application/files/base-webpack/webpack.config.js__tmpl__ +46 -5
  31. package/src/generators/application/files/nx-welcome/src/app/nx-welcome.tsx +54 -13
  32. package/src/generators/application/files/style-tailwind/src/app/__fileName__.tsx__tmpl__ +33 -0
  33. package/src/generators/application/files/style-tailwind/src/styles.css +1 -0
  34. package/src/generators/application/lib/add-e2e.js +25 -7
  35. package/src/generators/application/lib/add-jest.js +2 -2
  36. package/src/generators/application/lib/add-project.d.ts +2 -2
  37. package/src/generators/application/lib/add-project.js +12 -15
  38. package/src/generators/application/lib/add-routing.d.ts +1 -1
  39. package/src/generators/application/lib/add-routing.js +4 -8
  40. package/src/generators/application/lib/create-application-files.js +30 -1
  41. package/src/generators/application/lib/install-common-dependencies.js +15 -1
  42. package/src/generators/application/lib/normalize-options.js +35 -1
  43. package/src/generators/application/lib/set-defaults.js +1 -0
  44. package/src/generators/application/lib/update-jest-config.js +8 -8
  45. package/src/generators/application/schema.d.ts +5 -0
  46. package/src/generators/application/schema.json +7 -3
  47. package/src/generators/component/files/__fileName__.tsx__tmpl__ +39 -22
  48. package/src/generators/component/lib/normalize-options.js +4 -2
  49. package/src/generators/component/schema.d.ts +6 -4
  50. package/src/generators/component/schema.json +7 -7
  51. package/src/generators/component-cypress-spec/schema.json +1 -1
  52. package/src/generators/component-story/schema.json +1 -1
  53. package/src/generators/component-test/schema.json +1 -1
  54. package/src/generators/cypress-component-configuration/cypress-component-configuration.d.ts +2 -1
  55. package/src/generators/cypress-component-configuration/cypress-component-configuration.js +18 -7
  56. package/src/generators/cypress-component-configuration/lib/add-files.js +1 -6
  57. package/src/generators/cypress-component-configuration/schema.d.ts +1 -0
  58. package/src/generators/federate-module/federate-module.js +2 -2
  59. package/src/generators/federate-module/schema.d.ts +1 -1
  60. package/src/generators/federate-module/schema.json +4 -3
  61. package/src/generators/hook/files/__fileName__.ts__tmpl__ +15 -15
  62. package/src/generators/hook/schema.d.ts +4 -4
  63. package/src/generators/hook/schema.json +5 -5
  64. package/src/generators/host/files/common/src/main.js__tmpl__ +10 -0
  65. package/src/generators/host/files/common/tsconfig.lint.json__tmpl__ +19 -0
  66. package/src/generators/host/files/common-ts/src/app/__fileName__.tsx__tmpl__ +41 -0
  67. package/src/generators/host/files/common-ts/src/main.ts__tmpl__ +10 -0
  68. package/src/generators/host/files/module-federation/module-federation.config.js__tmpl__ +17 -2
  69. package/src/generators/host/files/module-federation-ssr/module-federation.server.config.js__tmpl__ +5 -2
  70. package/src/generators/host/files/module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +5 -2
  71. package/src/generators/host/files/module-federation-ts/module-federation.config.ts__tmpl__ +17 -2
  72. package/src/generators/host/files/module-federation-ts/webpack.config.prod.ts__tmpl__ +2 -1
  73. package/src/generators/host/files/module-federation-ts/webpack.config.ts__tmpl__ +2 -2
  74. package/src/generators/host/host.js +15 -1
  75. package/src/generators/host/lib/add-module-federation-files.d.ts +2 -1
  76. package/src/generators/host/lib/add-module-federation-files.js +24 -11
  77. package/src/generators/host/lib/setup-ssr-for-host.js +1 -0
  78. package/src/generators/host/lib/update-module-federation-e2e-project.js +7 -5
  79. package/src/generators/host/schema.d.ts +5 -2
  80. package/src/generators/host/schema.json +16 -6
  81. package/src/generators/init/init.d.ts +1 -1
  82. package/src/generators/init/init.js +10 -49
  83. package/src/generators/init/schema.d.ts +1 -6
  84. package/src/generators/init/schema.json +5 -22
  85. package/src/generators/library/lib/add-linting.js +2 -2
  86. package/src/generators/library/lib/add-rollup-build-target.d.ts +2 -1
  87. package/src/generators/library/lib/add-rollup-build-target.js +16 -8
  88. package/src/generators/library/lib/install-common-dependencies.js +13 -5
  89. package/src/generators/library/lib/normalize-options.js +34 -5
  90. package/src/generators/library/lib/update-app-routes.js +1 -1
  91. package/src/generators/library/library.js +17 -6
  92. package/src/generators/library/schema.d.ts +1 -0
  93. package/src/generators/library/schema.json +3 -3
  94. package/src/generators/redux/schema.d.ts +1 -1
  95. package/src/generators/redux/schema.json +2 -2
  96. package/src/generators/remote/files/module-federation/module-federation.config.js__tmpl__ +4 -1
  97. package/src/generators/remote/files/module-federation-ssr/module-federation.server.config.js__tmpl__ +1 -1
  98. package/src/generators/remote/files/module-federation-ssr-ts/module-federation.server.config.ts__tmpl__ +1 -1
  99. package/src/generators/remote/files/module-federation-ssr-ts/tsconfig.lint.json__tmpl__ +19 -0
  100. package/src/generators/remote/files/module-federation-ts/module-federation.config.ts__tmpl__ +4 -1
  101. package/src/generators/remote/files/module-federation-ts/tsconfig.lint.json__tmpl__ +19 -0
  102. package/src/generators/remote/lib/add-remote-to-dynamic-host.d.ts +2 -0
  103. package/src/generators/remote/lib/add-remote-to-dynamic-host.js +11 -0
  104. package/src/generators/remote/lib/setup-ssr-for-remote.js +5 -1
  105. package/src/generators/remote/lib/setup-tspath-for-remote.js +2 -1
  106. package/src/generators/remote/lib/update-host-with-remote.js +10 -1
  107. package/src/generators/remote/remote.js +22 -2
  108. package/src/generators/remote/schema.d.ts +3 -2
  109. package/src/generators/remote/schema.json +17 -6
  110. package/src/generators/setup-ssr/schema.json +1 -1
  111. package/src/generators/setup-ssr/setup-ssr.js +23 -7
  112. package/src/generators/setup-tailwind/schema.json +1 -1
  113. package/src/generators/stories/schema.json +1 -1
  114. package/src/generators/stories/stories.js +17 -5
  115. package/src/generators/storybook-configuration/configuration.d.ts +2 -0
  116. package/src/generators/storybook-configuration/configuration.js +37 -15
  117. package/src/generators/storybook-configuration/schema.d.ts +2 -1
  118. package/src/generators/storybook-configuration/schema.json +7 -7
  119. package/src/migrations/update-18-0-0/add-mf-env-var-to-target-defaults.d.ts +2 -0
  120. package/src/migrations/update-18-0-0/add-mf-env-var-to-target-defaults.js +26 -0
  121. package/src/migrations/update-18-1-1/fix-target-defaults-inputs.d.ts +2 -0
  122. package/src/migrations/update-18-1-1/fix-target-defaults-inputs.js +53 -0
  123. package/src/module-federation/ast-utils.js +1 -1
  124. package/src/module-federation/utils.js +8 -1
  125. package/src/module-federation/with-module-federation-ssr.js +3 -0
  126. package/src/module-federation/with-module-federation.d.ts +3 -3
  127. package/src/module-federation/with-module-federation.js +14 -4
  128. package/src/rules/update-module-federation-project.d.ts +2 -0
  129. package/src/rules/update-module-federation-project.js +12 -3
  130. package/src/utils/add-mf-env-to-inputs.d.ts +2 -0
  131. package/src/utils/add-mf-env-to-inputs.js +27 -0
  132. package/src/utils/assertion.js +1 -0
  133. package/src/utils/ct-utils.d.ts +6 -1
  134. package/src/utils/ct-utils.js +39 -9
  135. package/src/utils/get-in-source-vitest-tests-template.js +1 -1
  136. package/src/utils/has-vite-plugin.d.ts +2 -0
  137. package/src/utils/has-vite-plugin.js +11 -0
  138. package/src/utils/has-webpack-plugin.d.ts +2 -0
  139. package/src/utils/has-webpack-plugin.js +11 -0
  140. package/src/utils/maybe-js.d.ts +3 -0
  141. package/src/utils/versions.d.ts +1 -1
  142. package/src/utils/versions.js +1 -1
  143. package/typings/style.d.ts +1 -0
  144. package/src/generators/application/files/base-webpack/src/environments/environment.prod.ts__tmpl__ +0 -3
  145. package/src/generators/application/files/base-webpack/src/environments/environment.ts__tmpl__ +0 -6
  146. package/src/generators/host/files/module-federation/src/main.ts__tmpl__ +0 -1
  147. package/src/generators/host/files/module-federation-ts/src/main.ts__tmpl__ +0 -1
  148. package/src/generators/library/lib/maybe-js.d.ts +0 -2
  149. /package/src/generators/host/files/common/src/app/{__fileName__.tsx__tmpl__ → __fileName__.js__tmpl__} +0 -0
  150. /package/src/generators/remote/files/{module-federation/src/main.ts__tmpl__ → common/src/main.js__tmpl__} +0 -0
  151. /package/src/generators/remote/files/{module-federation/src/remote-entry.ts__tmpl__ → common/src/remote-entry.js__tmpl__} +0 -0
  152. /package/src/generators/remote/files/{module-federation-ts → common-ts}/src/main.ts__tmpl__ +0 -0
  153. /package/src/generators/remote/files/{module-federation-ts → common-ts}/src/remote-entry.ts__tmpl__ +0 -0
  154. /package/src/{generators/library/lib → utils}/maybe-js.js +0 -0
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "types": [
6
+ "node",
7
+ "@nx/react/typings/cssmodule.d.ts",
8
+ "@nx/react/typings/image.d.ts"
9
+ ]
10
+ },
11
+ "include": [
12
+ "src/**/*.js",
13
+ "src/**/*.jsx",
14
+ "src/**/*.ts",
15
+ "src/**/*.tsx",
16
+ "webpack.config.ts",
17
+ "webpack.prod.config.ts"
18
+ ]
19
+ }
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function addRemoteToDynamicHost(tree: Tree, remoteName: string, remotePort: number, pathToMfManifest: string): void;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addRemoteToDynamicHost = void 0;
4
+ function addRemoteToDynamicHost(tree, remoteName, remotePort, pathToMfManifest) {
5
+ const current = tree.read(pathToMfManifest, 'utf8');
6
+ tree.write(pathToMfManifest, JSON.stringify({
7
+ ...JSON.parse(current),
8
+ [remoteName]: `http://localhost:${remotePort}`,
9
+ }));
10
+ }
11
+ exports.addRemoteToDynamicHost = addRemoteToDynamicHost;
@@ -18,12 +18,16 @@ async function setupSsrForRemote(tree, options, appName) {
18
18
  });
19
19
  // For hosts to use when running remotes in static mode.
20
20
  const originalOutputPath = project.targets.build?.options?.outputPath;
21
+ const serverOptions = project.targets.server?.options;
22
+ const serverOutputPath = serverOptions?.outputPath ??
23
+ (0, devkit_1.joinPathFragments)(originalOutputPath, 'server');
24
+ const serverOutputName = serverOptions?.outputFileName ?? 'main.js';
21
25
  project.targets['serve-static'] = {
22
26
  dependsOn: ['build', 'server'],
23
27
  executor: 'nx:run-commands',
24
28
  defaultConfiguration: 'development',
25
29
  options: {
26
- command: `PORT=${options.devServerPort ?? 4200} node ${(0, devkit_1.joinPathFragments)(originalOutputPath, 'server', 'main.js')}`,
30
+ command: `PORT=${options.devServerPort ?? 4200} node ${(0, devkit_1.joinPathFragments)(serverOutputPath, serverOutputName)}`,
27
31
  },
28
32
  };
29
33
  (0, devkit_1.updateProjectConfiguration)(tree, appName, project);
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupTspathForRemote = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const js_1 = require("@nx/js");
6
+ const maybe_js_1 = require("../../../utils/maybe-js");
6
7
  function setupTspathForRemote(tree, options) {
7
8
  const project = (0, devkit_1.readProjectConfiguration)(tree, options.name);
8
- const exportPath = `./src/remote-entry.ts`;
9
+ const exportPath = (0, maybe_js_1.maybeJs)(options, './src/remote-entry.ts');
9
10
  const exportName = 'Module';
10
11
  (0, js_1.addTsConfigPath)(tree, `${options.name}/${exportName}`, [
11
12
  (0, devkit_1.joinPathFragments)(project.root, exportPath),
@@ -46,7 +46,16 @@ function updateHostWithRemote(host, hostName, remoteName) {
46
46
  }
47
47
  exports.updateHostWithRemote = updateHostWithRemote;
48
48
  function findAppComponentPath(host, sourceRoot) {
49
- const locations = ['app/app.tsx', 'app/App.tsx', 'app.tsx', 'App.tsx'];
49
+ const locations = [
50
+ 'app/app.tsx',
51
+ 'app/App.tsx',
52
+ 'app/app.js',
53
+ 'app/App.js',
54
+ 'app.tsx',
55
+ 'App.tsx',
56
+ 'app.js',
57
+ 'App.js',
58
+ ];
50
59
  for (const loc of locations) {
51
60
  if (host.exists((0, devkit_1.joinPathFragments)(sourceRoot, loc))) {
52
61
  return (0, devkit_1.joinPathFragments)(sourceRoot, loc);
@@ -10,12 +10,16 @@ const update_module_federation_project_1 = require("../../rules/update-module-fe
10
10
  const setup_ssr_1 = require("../setup-ssr/setup-ssr");
11
11
  const setup_ssr_for_remote_1 = require("./lib/setup-ssr-for-remote");
12
12
  const setup_tspath_for_remote_1 = require("./lib/setup-tspath-for-remote");
13
+ const add_remote_to_dynamic_host_1 = require("./lib/add-remote-to-dynamic-host");
14
+ const add_mf_env_to_inputs_1 = require("../../utils/add-mf-env-to-inputs");
15
+ const maybe_js_1 = require("../../utils/maybe-js");
13
16
  function addModuleFederationFiles(host, options) {
14
17
  const templateVariables = {
15
18
  ...(0, devkit_1.names)(options.name),
16
19
  ...options,
17
20
  tmpl: '',
18
21
  };
22
+ (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `./files/${options.js ? 'common' : 'common-ts'}`), options.appProjectRoot, templateVariables);
19
23
  const pathToModuleFederationFiles = options.typescriptConfiguration
20
24
  ? 'module-federation-ts'
21
25
  : 'module-federation';
@@ -43,7 +47,14 @@ async function remoteGeneratorInternal(host, schema) {
43
47
  const tasks = [];
44
48
  const options = {
45
49
  ...(await (0, normalize_options_1.normalizeOptions)(host, schema, '@nx/react:remote')),
46
- typescriptConfiguration: schema.typescriptConfiguration ?? false,
50
+ // when js is set to true, we want to use the js configuration
51
+ js: schema.js ?? false,
52
+ typescriptConfiguration: schema.js
53
+ ? false
54
+ : schema.typescriptConfiguration ?? true,
55
+ dynamic: schema.dynamic ?? false,
56
+ // TODO(colum): remove when MF works with Crystal
57
+ addPlugin: false,
47
58
  };
48
59
  const initAppTask = await (0, application_1.default)(host, {
49
60
  ...options,
@@ -58,7 +69,7 @@ async function remoteGeneratorInternal(host, schema) {
58
69
  // Module federation requires bootstrap code to be dynamically imported.
59
70
  // Renaming original entry file so we can use `import(./bootstrap)` in
60
71
  // new entry file.
61
- host.rename((0, path_1.join)(options.appProjectRoot, 'src/main.tsx'), (0, path_1.join)(options.appProjectRoot, 'src/bootstrap.tsx'));
72
+ host.rename((0, path_1.join)(options.appProjectRoot, (0, maybe_js_1.maybeJs)(options, 'src/main.tsx')), (0, path_1.join)(options.appProjectRoot, (0, maybe_js_1.maybeJs)(options, 'src/bootstrap.tsx')));
62
73
  addModuleFederationFiles(host, options);
63
74
  (0, update_module_federation_project_1.updateModuleFederationProject)(host, options);
64
75
  (0, setup_tspath_for_remote_1.setupTspathForRemote)(host, options);
@@ -75,6 +86,15 @@ async function remoteGeneratorInternal(host, schema) {
75
86
  projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, `webpack.server.config.${options.typescriptConfiguration ? 'ts' : 'js'}`);
76
87
  (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfig);
77
88
  }
89
+ if (!options.setParserOptionsProject) {
90
+ host.delete((0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.lint.json'));
91
+ }
92
+ if (options.host && options.dynamic) {
93
+ const hostConfig = (0, devkit_1.readProjectConfiguration)(host, schema.host);
94
+ const pathToMFManifest = (0, devkit_1.joinPathFragments)(hostConfig.sourceRoot, 'assets/module-federation.manifest.json');
95
+ (0, add_remote_to_dynamic_host_1.addRemoteToDynamicHost)(host, options.name, options.devServerPort, pathToMFManifest);
96
+ }
97
+ (0, add_mf_env_to_inputs_1.addMfEnvToTargetDefaultInputs)(host);
78
98
  if (!options.skipFormat) {
79
99
  await (0, devkit_1.formatFiles)(host);
80
100
  }
@@ -1,6 +1,6 @@
1
1
  import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
2
2
  import type { Linter } from '@nx/eslint';
3
- import type { SupportedStyles } from '../../../typings';
3
+ import type { SupportedStyles } from '../../../typings/style';
4
4
  import type { NormalizedSchema as ApplicationNormalizedSchema } from '../application/schema';
5
5
 
6
6
  export interface Schema {
@@ -9,7 +9,7 @@ export interface Schema {
9
9
  devServerPort?: number;
10
10
  directory?: string;
11
11
  projectNameAndRootFormat?: ProjectNameAndRootFormat;
12
- e2eTestRunner: 'cypress' | 'none';
12
+ e2eTestRunner: 'cypress' | 'playwright' | 'none';
13
13
  globalCss?: boolean;
14
14
  host?: string;
15
15
  js?: boolean;
@@ -26,6 +26,7 @@ export interface Schema {
26
26
  tags?: string;
27
27
  unitTestRunner: 'jest' | 'vitest' | 'none';
28
28
  typescriptConfiguration?: boolean;
29
+ dynamic?: boolean;
29
30
  }
30
31
 
31
32
  export interface NormalizedSchema extends ApplicationNormalizedSchema {
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "GeneratorReactRemote",
4
4
  "cli": "nx",
5
5
  "title": "Generate Module Federation Setup for React Remote App",
@@ -28,6 +28,12 @@
28
28
  "type": "string",
29
29
  "enum": ["as-provided", "derived"]
30
30
  },
31
+ "dynamic": {
32
+ "type": "boolean",
33
+ "description": "Should the host application use dynamic federation?",
34
+ "default": false,
35
+ "x-priority": "internal"
36
+ },
31
37
  "style": {
32
38
  "description": "The file extension to be used for style files.",
33
39
  "type": "string",
@@ -43,11 +49,15 @@
43
49
  },
44
50
  {
45
51
  "value": "scss",
46
- "label": "SASS(.scss) [ http://sass-lang.com ]"
52
+ "label": "SASS(.scss) [ https://sass-lang.com ]"
47
53
  },
48
54
  {
49
55
  "value": "less",
50
- "label": "LESS [ http://lesscss.org ]"
56
+ "label": "LESS [ https://lesscss.org ]"
57
+ },
58
+ {
59
+ "value": "tailwind",
60
+ "label": "tailwind [ https://tailwindcss.com/ ]"
51
61
  },
52
62
  {
53
63
  "value": "styled-components",
@@ -99,8 +109,9 @@
99
109
  },
100
110
  "e2eTestRunner": {
101
111
  "type": "string",
102
- "enum": ["cypress", "none"],
103
- "description": "Test runner to use for end to end (e2e) tests.",
112
+ "enum": ["cypress", "playwright", "none"],
113
+ "description": "Test runner to use for end to end (E2E) tests.",
114
+ "x-prompt": "Which E2E test runner would you like to use?",
104
115
  "default": "cypress"
105
116
  },
106
117
  "tags": {
@@ -163,7 +174,7 @@
163
174
  },
164
175
  "typescriptConfiguration": {
165
176
  "type": "boolean",
166
- "description": "Whether the module federation configuration and webpack configuration files should use TS.",
177
+ "description": "Whether the module federation configuration and webpack configuration files should use TS. When --js is used, this flag is ignored.",
167
178
  "default": true
168
179
  }
169
180
  },
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "GeneratorReactSSRSetup",
4
4
  "cli": "nx",
5
5
  "title": "Generate SSR setup for a React app",
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupSsrGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
- const init_1 = require("../init/init");
6
5
  const versions_1 = require("../../utils/versions");
7
6
  const ast_utils_1 = require("../../utils/ast-utils");
8
7
  const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
@@ -18,9 +17,22 @@ function readEntryFile(host, path) {
18
17
  source: tsModule.createSourceFile(path, content, tsModule.ScriptTarget.Latest, true),
19
18
  };
20
19
  }
20
+ async function getProjectConfig(tree, projectName) {
21
+ let maybeProjectConfig = (0, devkit_1.readProjectConfiguration)(tree, projectName);
22
+ if (!maybeProjectConfig.targets?.build) {
23
+ let projectGraph;
24
+ try {
25
+ projectGraph = (0, devkit_1.readCachedProjectGraph)();
26
+ }
27
+ catch {
28
+ projectGraph = await (0, devkit_1.createProjectGraphAsync)();
29
+ }
30
+ maybeProjectConfig = projectGraph.nodes[projectName].data;
31
+ }
32
+ return maybeProjectConfig;
33
+ }
21
34
  async function setupSsrGenerator(tree, options) {
22
- await (0, init_1.default)(tree, { skipFormat: true });
23
- const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
35
+ const projectConfig = await getProjectConfig(tree, options.project);
24
36
  const projectRoot = projectConfig.root;
25
37
  const appImportCandidates = [
26
38
  options.appComponentImportPath ?? 'app/app',
@@ -44,11 +56,15 @@ async function setupSsrGenerator(tree, options) {
44
56
  if (projectConfig.targets.server) {
45
57
  throw new Error(`Project ${options.project} already has a server target.`);
46
58
  }
47
- const originalOutputPath = projectConfig.targets.build?.options?.outputPath;
59
+ const originalOutputPath = projectConfig.targets.build?.options?.outputPath ??
60
+ projectConfig.targets.build?.outputs[0];
48
61
  if (!originalOutputPath) {
49
62
  throw new Error(`Project ${options.project} does not contain a outputPath for the build target.`);
50
63
  }
51
- projectConfig.targets.build.options.outputPath = (0, devkit_1.joinPathFragments)(originalOutputPath, 'browser');
64
+ // TODO(colum): We need to figure out how to handle this for Crystal
65
+ if (projectConfig.targets.build.options?.outputPath) {
66
+ projectConfig.targets.build.options.outputPath = (0, devkit_1.joinPathFragments)(originalOutputPath, 'browser');
67
+ }
52
68
  projectConfig.targets = {
53
69
  ...projectConfig.targets,
54
70
  server: {
@@ -65,7 +81,6 @@ async function setupSsrGenerator(tree, options) {
65
81
  compiler: 'babel',
66
82
  externalDependencies: 'all',
67
83
  outputHashing: 'none',
68
- isolatedConfig: true,
69
84
  webpackConfig: (0, devkit_1.joinPathFragments)(projectRoot, 'webpack.config.js'),
70
85
  },
71
86
  configurations: {
@@ -139,7 +154,8 @@ async function setupSsrGenerator(tree, options) {
139
154
  ? `"${options.extraInclude.join('", "')}",`
140
155
  : '',
141
156
  appComponentImport: appComponentInfo.importPath,
142
- browserBuildOutputPath: projectConfig.targets.build.options.outputPath,
157
+ browserBuildOutputPath: projectConfig.targets.build?.options?.outputPath ??
158
+ projectConfig.targets.build?.outputs[0],
143
159
  });
144
160
  // Add <StaticRouter> to server main if needed.
145
161
  // TODO: need to read main.server.tsx not main.tsx.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "cli": "nx",
4
4
  "$id": "NxReactTailwindSetupGenerator",
5
5
  "title": "Configures Tailwind CSS for an application or a buildable/publishable library.",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "cli": "nx",
4
4
  "$id": "NxReactStorybookStories",
5
5
  "title": "Generate React Storybook stories",
@@ -6,16 +6,15 @@ const component_cypress_spec_1 = require("../component-cypress-spec/component-cy
6
6
  const ast_utils_1 = require("../../utils/ast-utils");
7
7
  const devkit_1 = require("@nx/devkit");
8
8
  const path_1 = require("path");
9
- const minimatch = require("minimatch");
9
+ const minimatch_1 = require("minimatch");
10
10
  const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
11
11
  const versions_1 = require("../../utils/versions");
12
12
  let tsModule;
13
13
  async function projectRootPath(tree, config) {
14
- const { findStorybookAndBuildTargetsAndCompiler } = await Promise.resolve().then(() => require('@nx/storybook/src/utils/utilities'));
15
14
  let projectDir;
16
15
  if (config.projectType === 'application') {
17
- const { nextBuildTarget } = findStorybookAndBuildTargetsAndCompiler(config.targets);
18
- if (!!nextBuildTarget) {
16
+ const isNextJs = await isNextJsProject(tree, config);
17
+ if (isNextJs) {
19
18
  // Next.js apps
20
19
  projectDir = 'components';
21
20
  }
@@ -53,7 +52,7 @@ async function createAllStories(tree, projectName, interactionTests, js, project
53
52
  // Ignore private files starting with "_".
54
53
  if ((0, path_1.basename)(path).startsWith('_'))
55
54
  return;
56
- if (ignorePaths?.some((pattern) => minimatch(path, pattern)))
55
+ if (ignorePaths?.some((pattern) => (0, minimatch_1.minimatch)(path, pattern)))
57
56
  return;
58
57
  if ((path.endsWith('.tsx') && !path.endsWith('.spec.tsx')) ||
59
58
  (path.endsWith('.js') && !path.endsWith('.spec.js')) ||
@@ -115,4 +114,17 @@ async function storiesGenerator(host, schema) {
115
114
  return (0, devkit_1.runTasksInSerial)(...tasks);
116
115
  }
117
116
  exports.storiesGenerator = storiesGenerator;
117
+ async function isNextJsProject(tree, config) {
118
+ const { findStorybookAndBuildTargetsAndCompiler } = await Promise.resolve().then(() => require('@nx/storybook/src/utils/utilities'));
119
+ const { nextBuildTarget } = findStorybookAndBuildTargetsAndCompiler(config.targets);
120
+ if (nextBuildTarget) {
121
+ return true;
122
+ }
123
+ for (const configFile of ['next.config.js', 'next.config.ts']) {
124
+ if (tree.exists((0, path_1.join)(config.root, configFile))) {
125
+ return true;
126
+ }
127
+ }
128
+ return false;
129
+ }
118
130
  exports.default = storiesGenerator;
@@ -1,4 +1,6 @@
1
1
  import { StorybookConfigureSchema } from './schema';
2
2
  import { Tree } from '@nx/devkit';
3
3
  export declare function storybookConfigurationGenerator(host: Tree, schema: StorybookConfigureSchema): Promise<import("@nx/devkit").GeneratorCallback>;
4
+ export declare function storybookConfigurationGeneratorInternal(host: Tree, schema: StorybookConfigureSchema): Promise<import("@nx/devkit").GeneratorCallback>;
4
5
  export default storybookConfigurationGenerator;
6
+ export declare function findWebpackConfig(tree: Tree, projectRoot: string): string | undefined;
@@ -1,17 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.storybookConfigurationGenerator = void 0;
3
+ exports.findWebpackConfig = exports.storybookConfigurationGeneratorInternal = exports.storybookConfigurationGenerator = void 0;
4
4
  const stories_1 = require("../stories/stories");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const versions_1 = require("../../utils/versions");
7
7
  async function generateStories(host, schema) {
8
- // TODO(katerina): Nx 18 -> remove Cypress
8
+ // TODO(katerina): Nx 19 -> remove Cypress
9
9
  (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
10
10
  const { getE2eProjectName } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/project-name'));
11
- const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.name);
12
- const cypressProject = getE2eProjectName(schema.name, projectConfig.root, schema.cypressDirectory);
11
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.project);
12
+ const cypressProject = getE2eProjectName(schema.project, projectConfig.root, schema.cypressDirectory);
13
13
  await (0, stories_1.default)(host, {
14
- project: schema.name,
14
+ project: schema.project,
15
15
  generateCypressSpecs: schema.configureCypress && schema.generateCypressSpecs,
16
16
  js: schema.js,
17
17
  cypressProject,
@@ -20,27 +20,39 @@ async function generateStories(host, schema) {
20
20
  interactionTests: schema.interactionTests ?? true,
21
21
  });
22
22
  }
23
- async function storybookConfigurationGenerator(host, schema) {
23
+ function storybookConfigurationGenerator(host, schema) {
24
+ return storybookConfigurationGeneratorInternal(host, {
25
+ addPlugin: false,
26
+ ...schema,
27
+ });
28
+ }
29
+ exports.storybookConfigurationGenerator = storybookConfigurationGenerator;
30
+ async function storybookConfigurationGeneratorInternal(host, schema) {
31
+ const nxJson = (0, devkit_1.readNxJson)(host);
32
+ const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
33
+ nxJson.useInferencePlugins !== false;
34
+ schema.addPlugin ??= addPluginDefault;
24
35
  const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/storybook', versions_1.nxVersion);
25
36
  let uiFramework = '@storybook/react-vite';
26
- const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.name);
27
- if (projectConfig.targets['build']?.executor === '@nx/webpack:webpack' ||
28
- projectConfig.targets['build']?.executor === '@nrwl/webpack:webpack' ||
37
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.project);
38
+ if (findWebpackConfig(host, projectConfig.root) ||
29
39
  projectConfig.targets['build']?.executor === '@nx/rollup:rollup' ||
30
- projectConfig.targets['build']?.executor === '@nrwl/rollup:rollup') {
40
+ projectConfig.targets['build']?.executor === '@nrwl/rollup:rollup' ||
41
+ projectConfig.targets['build']?.executor === '@nx/expo:build') {
31
42
  uiFramework = '@storybook/react-webpack5';
32
43
  }
33
44
  const installTask = await configurationGenerator(host, {
34
- name: schema.name,
45
+ project: schema.project,
35
46
  configureCypress: schema.configureCypress,
36
47
  js: schema.js,
37
48
  linter: schema.linter,
38
49
  cypressDirectory: schema.cypressDirectory,
39
- tsConfiguration: schema.tsConfiguration ?? true,
40
- interactionTests: schema.interactionTests ?? true,
50
+ tsConfiguration: schema.tsConfiguration ?? true, // default is true
51
+ interactionTests: schema.interactionTests ?? true, // default is true
41
52
  configureStaticServe: schema.configureStaticServe,
42
- uiFramework: uiFramework,
53
+ uiFramework: uiFramework, // cannot import UiFramework type dynamically
43
54
  skipFormat: true,
55
+ addPlugin: schema.addPlugin,
44
56
  });
45
57
  if (schema.generateStories) {
46
58
  await generateStories(host, schema);
@@ -48,5 +60,15 @@ async function storybookConfigurationGenerator(host, schema) {
48
60
  await (0, devkit_1.formatFiles)(host);
49
61
  return installTask;
50
62
  }
51
- exports.storybookConfigurationGenerator = storybookConfigurationGenerator;
63
+ exports.storybookConfigurationGeneratorInternal = storybookConfigurationGeneratorInternal;
52
64
  exports.default = storybookConfigurationGenerator;
65
+ function findWebpackConfig(tree, projectRoot) {
66
+ const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
67
+ for (const ext of allowsExt) {
68
+ const webpackConfigPath = (0, devkit_1.joinPathFragments)(projectRoot, `webpack.config.${ext}`);
69
+ if (tree.exists(webpackConfigPath)) {
70
+ return webpackConfigPath;
71
+ }
72
+ }
73
+ }
74
+ exports.findWebpackConfig = findWebpackConfig;
@@ -1,7 +1,7 @@
1
1
  import { Linter } from '@nx/eslint';
2
2
 
3
3
  export interface StorybookConfigureSchema {
4
- name: string;
4
+ project: string;
5
5
  interactionTests?: boolean;
6
6
  generateStories?: boolean;
7
7
  js?: boolean;
@@ -12,4 +12,5 @@ export interface StorybookConfigureSchema {
12
12
  configureCypress?: boolean;
13
13
  generateCypressSpecs?: boolean;
14
14
  cypressDirectory?: string;
15
+ addPlugin?: boolean;
15
16
  }
@@ -1,14 +1,14 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "cli": "nx",
4
4
  "$id": "NxReactStorybookConfigure",
5
5
  "title": "React Storybook Configure",
6
6
  "description": "Set up Storybook for a React app or library.",
7
7
  "type": "object",
8
8
  "properties": {
9
- "name": {
9
+ "project": {
10
10
  "type": "string",
11
- "aliases": ["project", "projectName"],
11
+ "aliases": ["name", "projectName"],
12
12
  "description": "Project for which to generate Storybook configuration.",
13
13
  "$default": {
14
14
  "$source": "argv",
@@ -29,7 +29,7 @@
29
29
  "configureCypress": {
30
30
  "type": "boolean",
31
31
  "description": "Run the cypress-configure generator.",
32
- "x-deprecated": "Use interactionTests instead. This option will be removed in v18."
32
+ "x-deprecated": "Use interactionTests instead. This option will be removed in v19."
33
33
  },
34
34
  "generateStories": {
35
35
  "type": "boolean",
@@ -41,7 +41,7 @@
41
41
  "generateCypressSpecs": {
42
42
  "type": "boolean",
43
43
  "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
44
- "x-deprecated": "Use interactionTests instead. This option will be removed in v18."
44
+ "x-deprecated": "Use interactionTests instead. This option will be removed in v19."
45
45
  },
46
46
  "configureStaticServe": {
47
47
  "type": "boolean",
@@ -53,7 +53,7 @@
53
53
  "cypressDirectory": {
54
54
  "type": "string",
55
55
  "description": "A directory where the Cypress project will be placed. Placed at the root by default.",
56
- "x-deprecated": "Use interactionTests instead. This option will be removed in v18."
56
+ "x-deprecated": "Use interactionTests instead. This option will be removed in v19."
57
57
  },
58
58
  "js": {
59
59
  "type": "boolean",
@@ -90,6 +90,6 @@
90
90
  ]
91
91
  }
92
92
  },
93
- "required": ["name"],
93
+ "required": ["project"],
94
94
  "examplesFile": "../../../docs/storybook-configuration-examples.md"
95
95
  }
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function (tree: Tree): Promise<void>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const add_mf_env_to_inputs_1 = require("../../utils/add-mf-env-to-inputs");
5
+ async function default_1(tree) {
6
+ if (!hasModuleFederationProject(tree)) {
7
+ return;
8
+ }
9
+ (0, add_mf_env_to_inputs_1.addMfEnvToTargetDefaultInputs)(tree);
10
+ await (0, devkit_1.formatFiles)(tree);
11
+ }
12
+ exports.default = default_1;
13
+ function hasModuleFederationProject(tree) {
14
+ const projects = (0, devkit_1.getProjects)(tree);
15
+ for (const project of projects.values()) {
16
+ const targets = project.targets || {};
17
+ for (const [_, target] of Object.entries(targets)) {
18
+ if (target.executor === '@nx/webpack:webpack' &&
19
+ (tree.exists((0, devkit_1.joinPathFragments)(project.root, 'module-federation.config.ts')) ||
20
+ tree.exists((0, devkit_1.joinPathFragments)(project.root, 'module-federation.config.js')))) {
21
+ return true;
22
+ }
23
+ }
24
+ }
25
+ return false;
26
+ }
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function (tree: Tree): Promise<void>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ async function default_1(tree) {
5
+ if (!hasModuleFederationProject(tree)) {
6
+ return;
7
+ }
8
+ ensureTargetDefaultsContainProductionInputs(tree);
9
+ await (0, devkit_1.formatFiles)(tree);
10
+ }
11
+ exports.default = default_1;
12
+ function ensureTargetDefaultsContainProductionInputs(tree) {
13
+ const nxJson = (0, devkit_1.readNxJson)(tree);
14
+ const webpackExecutor = '@nx/webpack:webpack';
15
+ const mfEnvVar = 'NX_MF_DEV_SERVER_STATIC_REMOTES';
16
+ nxJson.targetDefaults[webpackExecutor] ??= {};
17
+ nxJson.targetDefaults[webpackExecutor].inputs ??= [
18
+ 'production',
19
+ '^production',
20
+ { env: mfEnvVar },
21
+ ];
22
+ if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('production')) {
23
+ nxJson.targetDefaults[webpackExecutor].inputs.push('production');
24
+ }
25
+ if (!nxJson.targetDefaults[webpackExecutor].inputs.includes('^production')) {
26
+ nxJson.targetDefaults[webpackExecutor].inputs.push('^production');
27
+ }
28
+ let mfEnvVarExists = false;
29
+ for (const input of nxJson.targetDefaults[webpackExecutor].inputs) {
30
+ if (typeof input === 'object' && input['env'] === mfEnvVar) {
31
+ mfEnvVarExists = true;
32
+ break;
33
+ }
34
+ }
35
+ if (!mfEnvVarExists) {
36
+ nxJson.targetDefaults[webpackExecutor].inputs.push({ env: mfEnvVar });
37
+ }
38
+ (0, devkit_1.updateNxJson)(tree, nxJson);
39
+ }
40
+ function hasModuleFederationProject(tree) {
41
+ const projects = (0, devkit_1.getProjects)(tree);
42
+ for (const project of projects.values()) {
43
+ const targets = project.targets || {};
44
+ for (const [_, target] of Object.entries(targets)) {
45
+ if (target.executor === '@nx/webpack:webpack' &&
46
+ (tree.exists((0, devkit_1.joinPathFragments)(project.root, 'module-federation.config.ts')) ||
47
+ tree.exists((0, devkit_1.joinPathFragments)(project.root, 'module-federation.config.js')))) {
48
+ return true;
49
+ }
50
+ }
51
+ }
52
+ return false;
53
+ }
@@ -18,7 +18,7 @@ function addRemoteToConfig(source, app) {
18
18
  return [];
19
19
  const lastElement = arrayExpression.elements[arrayExpression.elements.length - 1];
20
20
  return [
21
- lastElement
21
+ lastElement && !arrayExpression.elements.hasTrailingComma
22
22
  ? {
23
23
  type: devkit_1.ChangeType.Insert,
24
24
  index: lastElement.end,