@nx/workspace 21.0.0-beta.1 → 21.0.0-beta.2

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 (31) hide show
  1. package/package.json +5 -3
  2. package/src/generators/ci-workflow/ci-workflow.js +3 -0
  3. package/src/generators/ci-workflow/files/azure/azure-pipelines.yml__tmpl__ +2 -1
  4. package/src/generators/ci-workflow/files/bitbucket-pipelines/bitbucket-pipelines.yml__tmpl__ +2 -2
  5. package/src/generators/ci-workflow/files/circleci/.circleci/config.yml__tmpl__ +1 -1
  6. package/src/generators/ci-workflow/files/github/.github/workflows/__workflowFileName__.yml__tmpl__ +3 -1
  7. package/src/generators/ci-workflow/files/gitlab/.gitlab-ci.yml__tmpl__ +1 -1
  8. package/src/generators/move/lib/create-project-configuration-in-new-destination.js +8 -2
  9. package/src/generators/move/lib/normalize-schema.js +32 -38
  10. package/src/generators/move/move.d.ts +2 -2
  11. package/src/generators/move/move.js +19 -1
  12. package/src/generators/move/schema.d.ts +1 -0
  13. package/src/generators/new/files-integrated-repo/__dot__gitignore +1 -1
  14. package/src/generators/new/files-package-based-repo/__dot__gitignore +1 -1
  15. package/src/generators/new/files-root-app/__dot__gitignore +1 -1
  16. package/src/generators/new/generate-preset.js +5 -4
  17. package/src/generators/new/generate-workspace-files.js +5 -18
  18. package/src/generators/new/new.d.ts +2 -0
  19. package/src/generators/new/schema.json +10 -1
  20. package/src/generators/npm-package/npm-package.js +4 -4
  21. package/src/generators/preset/preset.js +14 -32
  22. package/src/generators/preset/schema.d.ts +2 -0
  23. package/src/generators/preset/schema.json +10 -1
  24. package/src/generators/utils/presets.d.ts +0 -2
  25. package/src/generators/utils/presets.js +0 -2
  26. package/src/utilities/package-manager-workspaces.d.ts +5 -0
  27. package/src/utilities/package-manager-workspaces.js +39 -0
  28. package/src/utilities/typescript/ts-solution-setup.d.ts +1 -0
  29. package/src/utilities/typescript/ts-solution-setup.js +48 -0
  30. package/src/utils/versions.d.ts +1 -1
  31. package/src/utils/versions.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/workspace",
3
- "version": "21.0.0-beta.1",
3
+ "version": "21.0.0-beta.2",
4
4
  "private": false,
5
5
  "description": "The Workspace plugin contains executors and generators that are useful for any Nx workspace. It should be present in every Nx workspace and other plugins build on it.",
6
6
  "repository": {
@@ -38,12 +38,14 @@
38
38
  }
39
39
  },
40
40
  "dependencies": {
41
- "@nx/devkit": "21.0.0-beta.1",
41
+ "@nx/devkit": "21.0.0-beta.2",
42
+ "@zkochan/js-yaml": "0.0.7",
42
43
  "chalk": "^4.1.0",
43
44
  "enquirer": "~2.3.6",
45
+ "picomatch": "4.0.2",
44
46
  "tslib": "^2.3.0",
45
47
  "yargs-parser": "21.1.1",
46
- "nx": "21.0.0-beta.1"
48
+ "nx": "21.0.0-beta.2"
47
49
  },
48
50
  "publishConfig": {
49
51
  "access": "public"
@@ -5,6 +5,7 @@ const devkit_1 = require("@nx/devkit");
5
5
  const default_base_1 = require("../../utilities/default-base");
6
6
  const path_1 = require("path");
7
7
  const nx_cloud_utils_1 = require("nx/src/utils/nx-cloud-utils");
8
+ const ts_solution_setup_1 = require("../../utilities/typescript/ts-solution-setup");
8
9
  async function ciWorkflowGenerator(tree, schema) {
9
10
  const ci = schema.ci;
10
11
  const options = normalizeOptions(schema, tree);
@@ -35,6 +36,7 @@ function normalizeOptions(options, tree) {
35
36
  const hasCypress = allDependencies['@nx/cypress'];
36
37
  const hasPlaywright = allDependencies['@nx/playwright'];
37
38
  const hasE2E = hasCypress || hasPlaywright;
39
+ const hasTypecheck = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
38
40
  const connectedToCloud = (0, nx_cloud_utils_1.isNxCloudUsed)((0, devkit_1.readJson)(tree, 'nx.json'));
39
41
  return {
40
42
  workflowName,
@@ -47,6 +49,7 @@ function normalizeOptions(options, tree) {
47
49
  hasCypress,
48
50
  hasE2E,
49
51
  hasPlaywright,
52
+ hasTypecheck,
50
53
  nxCloudHost,
51
54
  tmpl: '',
52
55
  connectedToCloud,
@@ -23,6 +23,7 @@ jobs:
23
23
  steps:
24
24
  - checkout: self
25
25
  fetchDepth: 0
26
+ fetchFilter: tree:0
26
27
  # Set Azure Devops CLI default settings
27
28
  - bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject)
28
29
  displayName: 'Set default Azure DevOps organization and project'
@@ -68,4 +69,4 @@ jobs:
68
69
  # - script: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
69
70
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %>
70
71
  # When you enable task distribution, run the e2e-ci task instead of e2e<% } %>
71
- - script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) lint test build<% if(hasE2E){ %> e2e<% } %>
72
+ - script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>
@@ -33,7 +33,7 @@ pipelines:
33
33
  # <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
34
34
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %>
35
35
  # When you enable task distribution, run the e2e-ci task instead of e2e<% } %>
36
- - <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> -t lint test build<% if(hasE2E){ %> e2e<% } %>
36
+ - <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>
37
37
 
38
38
  branches:
39
39
  main:
@@ -59,4 +59,4 @@ pipelines:
59
59
  # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
60
60
  # - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
61
61
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
62
- - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e-ci<% } %> --base=HEAD~1
62
+ - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e-ci<% } %> --base=HEAD~1
@@ -37,7 +37,7 @@ jobs:
37
37
  # - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
38
38
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %>
39
39
  # When you enable task distribution, run the e2e-ci task instead of e2e<% } %>
40
- - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %>
40
+ - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>
41
41
 
42
42
  workflows:
43
43
  version: 2
@@ -16,7 +16,9 @@ jobs:
16
16
  steps:
17
17
  - uses: actions/checkout@v4
18
18
  with:
19
+ filter: tree:0
19
20
  fetch-depth: 0
21
+
20
22
  <% if(packageManager == 'pnpm'){ %>
21
23
  - uses: pnpm/action-setup@v4
22
24
  with:
@@ -50,4 +52,4 @@ jobs:
50
52
  # - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
51
53
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %>
52
54
  # When you enable task distribution, run the e2e-ci task instead of e2e<% } %>
53
- - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %>
55
+ - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>
@@ -31,4 +31,4 @@ variables:
31
31
  # - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
32
32
  # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %>
33
33
  # When you enable task distribution, run the e2e-ci task instead of e2e<% } %>
34
- - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %>
34
+ - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>
@@ -48,6 +48,12 @@ function createProjectConfigurationInNewDestination(tree, schema, projectConfig)
48
48
  if (isRootProject && projectConfig.sourceRoot) {
49
49
  newProject.sourceRoot = (0, devkit_1.joinPathFragments)(schema.relativeToRootDestination, projectConfig.sourceRoot);
50
50
  }
51
- // Create a new project with the root replaced
52
- (0, devkit_1.addProjectConfiguration)(tree, schema.newProjectName, newProject);
51
+ if (schema.isNxConfiguredInPackageJson) {
52
+ // Update the existing project configuration in the package.json
53
+ (0, devkit_1.updateProjectConfiguration)(tree, schema.newProjectName, newProject);
54
+ }
55
+ else {
56
+ // Create a new project with the root replaced
57
+ (0, devkit_1.addProjectConfiguration)(tree, schema.newProjectName, newProject);
58
+ }
53
59
  }
@@ -1,23 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeSchema = normalizeSchema;
4
+ const devkit_1 = require("@nx/devkit");
4
5
  const get_import_path_1 = require("../../../utilities/get-import-path");
5
6
  const utils_1 = require("./utils");
6
7
  const ts_solution_setup_1 = require("../../../utils/ts-solution-setup");
7
8
  async function normalizeSchema(tree, schema, projectConfiguration) {
8
9
  const { destination, newProjectName, importPath } = await determineProjectNameAndRootOptions(tree, schema, projectConfiguration);
10
+ const isNxConfiguredInPackageJson = !tree.exists((0, devkit_1.joinPathFragments)(projectConfiguration.root, 'project.json'));
9
11
  return {
10
12
  ...schema,
11
13
  destination: (0, utils_1.normalizePathSlashes)(schema.destination),
12
14
  importPath,
13
15
  newProjectName,
14
16
  relativeToRootDestination: destination,
17
+ isNxConfiguredInPackageJson,
15
18
  };
16
19
  }
17
20
  async function determineProjectNameAndRootOptions(tree, options, projectConfiguration) {
18
21
  validateName(tree, options.newProjectName, projectConfiguration);
19
- const projectNameAndRootOptions = getProjectNameAndRootOptions(tree, options, projectConfiguration);
20
- return projectNameAndRootOptions;
22
+ let destination = (0, utils_1.normalizePathSlashes)(options.destination);
23
+ if (options.newProjectName &&
24
+ options.newProjectName.includes('/') &&
25
+ !options.newProjectName.startsWith('@')) {
26
+ throw new Error(`You can't specify a new project name with a directory path (${options.newProjectName}). ` +
27
+ `Please provide a valid name without path segments and the full destination with the "--destination" option.`);
28
+ }
29
+ const newProjectName = options.newProjectName ?? options.projectName;
30
+ if (projectConfiguration.projectType !== 'library') {
31
+ return { destination, newProjectName };
32
+ }
33
+ let importPath = options.importPath;
34
+ if (importPath) {
35
+ return { destination, newProjectName, importPath };
36
+ }
37
+ if (options.newProjectName?.startsWith('@')) {
38
+ // keep the existing import path if the name didn't change
39
+ importPath =
40
+ options.newProjectName && options.projectName !== options.newProjectName
41
+ ? newProjectName
42
+ : undefined;
43
+ }
44
+ else if (options.newProjectName) {
45
+ const npmScope = (0, get_import_path_1.getNpmScope)(tree);
46
+ importPath = npmScope
47
+ ? `${npmScope === '@' ? '' : '@'}${npmScope}/${newProjectName}`
48
+ : newProjectName;
49
+ }
50
+ return { destination, newProjectName, importPath };
21
51
  }
22
52
  function validateName(tree, name, projectConfiguration) {
23
53
  if (!name) {
@@ -49,39 +79,3 @@ function validateName(tree, name, projectConfiguration) {
49
79
  }
50
80
  }
51
81
  }
52
- function getProjectNameAndRootOptions(tree, options, projectConfiguration) {
53
- let destination = (0, utils_1.normalizePathSlashes)(options.destination);
54
- if (options.newProjectName &&
55
- options.newProjectName.includes('/') &&
56
- !options.newProjectName.startsWith('@')) {
57
- throw new Error(`You can't specify a new project name with a directory path (${options.newProjectName}). ` +
58
- `Please provide a valid name without path segments and the full destination with the "--destination" option.`);
59
- }
60
- const asProvidedOptions = getAsProvidedOptions(tree, { ...options, destination }, projectConfiguration);
61
- return asProvidedOptions;
62
- }
63
- function getAsProvidedOptions(tree, options, projectConfiguration) {
64
- const newProjectName = options.newProjectName ?? options.projectName;
65
- const destination = options.destination;
66
- if (projectConfiguration.projectType !== 'library') {
67
- return { destination, newProjectName };
68
- }
69
- let importPath = options.importPath;
70
- if (importPath) {
71
- return { destination, newProjectName, importPath };
72
- }
73
- if (options.newProjectName?.startsWith('@')) {
74
- // keep the existing import path if the name didn't change
75
- importPath =
76
- options.newProjectName && options.projectName !== options.newProjectName
77
- ? newProjectName
78
- : undefined;
79
- }
80
- else if (options.newProjectName) {
81
- const npmScope = (0, get_import_path_1.getNpmScope)(tree);
82
- importPath = npmScope
83
- ? `${npmScope === '@' ? '' : '@'}${npmScope}/${newProjectName}`
84
- : newProjectName;
85
- }
86
- return { destination, newProjectName, importPath };
87
- }
@@ -1,4 +1,4 @@
1
- import { Tree } from '@nx/devkit';
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
2
  import { Schema } from './schema';
3
- export declare function moveGenerator(tree: Tree, rawSchema: Schema): Promise<void>;
3
+ export declare function moveGenerator(tree: Tree, rawSchema: Schema): Promise<GeneratorCallback>;
4
4
  export default moveGenerator;
@@ -2,8 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.moveGenerator = moveGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
+ const package_manager_workspaces_1 = require("../../utilities/package-manager-workspaces");
6
+ const ts_solution_setup_1 = require("../../utilities/typescript/ts-solution-setup");
5
7
  const check_destination_1 = require("./lib/check-destination");
6
8
  const create_project_configuration_in_new_destination_1 = require("./lib/create-project-configuration-in-new-destination");
9
+ const extract_base_configs_1 = require("./lib/extract-base-configs");
7
10
  const move_project_files_1 = require("./lib/move-project-files");
8
11
  const normalize_schema_1 = require("./lib/normalize-schema");
9
12
  const run_angular_plugin_1 = require("./lib/run-angular-plugin");
@@ -18,9 +21,9 @@ const update_package_json_1 = require("./lib/update-package-json");
18
21
  const update_project_root_files_1 = require("./lib/update-project-root-files");
19
22
  const update_readme_1 = require("./lib/update-readme");
20
23
  const update_storybook_config_1 = require("./lib/update-storybook-config");
21
- const extract_base_configs_1 = require("./lib/extract-base-configs");
22
24
  async function moveGenerator(tree, rawSchema) {
23
25
  let projectConfig = (0, devkit_1.readProjectConfiguration)(tree, rawSchema.projectName);
26
+ const wasIncludedInWorkspaces = (0, package_manager_workspaces_1.isProjectIncludedInPackageManagerWorkspaces)(tree, projectConfig.root);
24
27
  const schema = await (0, normalize_schema_1.normalizeSchema)(tree, rawSchema, projectConfig);
25
28
  (0, check_destination_1.checkDestination)(tree, schema, rawSchema.destination);
26
29
  if (projectConfig.root === '.') {
@@ -48,8 +51,23 @@ async function moveGenerator(tree, rawSchema) {
48
51
  (0, extract_base_configs_1.maybeMigrateEslintConfigIfRootProject)(tree, projectConfig);
49
52
  }
50
53
  await (0, run_angular_plugin_1.runAngularPlugin)(tree, schema);
54
+ let task;
55
+ if (wasIncludedInWorkspaces) {
56
+ // check if the new destination is included in the package manager workspaces
57
+ const isIncludedInWorkspaces = (0, package_manager_workspaces_1.isProjectIncludedInPackageManagerWorkspaces)(tree, schema.destination);
58
+ if (!isIncludedInWorkspaces) {
59
+ // the new destination is not included in the package manager workspaces
60
+ // so we need to add it and run a package install to ensure the symlink
61
+ // is created
62
+ await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, schema.destination);
63
+ task = () => (0, devkit_1.installPackagesTask)(tree, true);
64
+ }
65
+ }
51
66
  if (!schema.skipFormat) {
52
67
  await (0, devkit_1.formatFiles)(tree);
53
68
  }
69
+ if (task) {
70
+ return task;
71
+ }
54
72
  }
55
73
  exports.default = moveGenerator;
@@ -9,4 +9,5 @@ export interface Schema {
9
9
 
10
10
  export interface NormalizedSchema extends Schema {
11
11
  relativeToRootDestination: string;
12
+ isNxConfiguredInPackageJson?: boolean;
12
13
  }
@@ -1,4 +1,4 @@
1
- # See http://help.github.com/ignore-files/ for more about ignoring files.
1
+ # See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2
2
 
3
3
  # compiled output
4
4
  dist
@@ -1,4 +1,4 @@
1
- # See http://help.github.com/ignore-files/ for more about ignoring files.
1
+ # See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2
2
 
3
3
  # compiled output
4
4
  dist
@@ -1,4 +1,4 @@
1
- # See http://help.github.com/ignore-files/ for more about ignoring files.
1
+ # See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2
2
 
3
3
  # compiled output
4
4
  dist
@@ -70,6 +70,9 @@ function generatePreset(host, opts) {
70
70
  : null,
71
71
  parsedArgs.interactive ? '--interactive=true' : '--interactive=false',
72
72
  opts.routing !== undefined ? `--routing=${opts.routing}` : null,
73
+ opts.useReactRouter !== undefined
74
+ ? `--useReactRouter=${opts.useReactRouter}`
75
+ : null,
73
76
  opts.unitTestRunner !== undefined
74
77
  ? `--unitTestRunner=${opts.unitTestRunner}`
75
78
  : null,
@@ -81,7 +84,8 @@ function generatePreset(host, opts) {
81
84
  opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
82
85
  opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
83
86
  opts.formatter ? `--formatter=${opts.formatter}` : null,
84
- opts.workspaces ? `--workspaces` : null,
87
+ opts.workspaces !== false ? `--workspaces` : `--no-workspaces`,
88
+ opts.useProjectJson ? `--useProjectJson` : null,
85
89
  ].filter((e) => !!e);
86
90
  }
87
91
  }
@@ -112,9 +116,6 @@ function getPresetDependencies({ preset, presetVersion, bundler, e2eTestRunner,
112
116
  case presets_1.Preset.NextJs:
113
117
  case presets_1.Preset.NextJsStandalone:
114
118
  return { dependencies: { '@nx/next': versions_1.nxVersion }, dev: {} };
115
- case presets_1.Preset.RemixStandalone:
116
- case presets_1.Preset.RemixMonorepo:
117
- return { dependencies: { '@nx/remix': versions_1.nxVersion }, dev: {} };
118
119
  case presets_1.Preset.VueMonorepo:
119
120
  case presets_1.Preset.VueStandalone:
120
121
  return {
@@ -52,16 +52,6 @@ const presetToPluginMap = {
52
52
  generateLibCmd: '@nx/react',
53
53
  learnMoreLink: 'https://nx.dev/nx-api/next?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
54
54
  },
55
- [presets_1.Preset.RemixMonorepo]: {
56
- generateAppCmd: '@nx/remix',
57
- generateLibCmd: '@nx/react',
58
- learnMoreLink: 'https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
59
- },
60
- [presets_1.Preset.RemixStandalone]: {
61
- generateAppCmd: '@nx/remix',
62
- generateLibCmd: '@nx/react',
63
- learnMoreLink: 'https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
64
- },
65
55
  [presets_1.Preset.ReactNative]: {
66
56
  generateAppCmd: '@nx/react-native',
67
57
  generateLibCmd: '@nx/react',
@@ -207,12 +197,11 @@ function createFiles(tree, options) {
207
197
  options.preset === presets_1.Preset.NuxtStandalone ||
208
198
  options.preset === presets_1.Preset.NodeStandalone ||
209
199
  options.preset === presets_1.Preset.NextJsStandalone ||
210
- options.preset === presets_1.Preset.RemixStandalone ||
211
200
  options.preset === presets_1.Preset.TsStandalone
212
201
  ? './files-root-app'
213
202
  : (options.preset === presets_1.Preset.TS &&
214
- process.env.NX_ADD_PLUGINS !== 'false' &&
215
- process.env.NX_ADD_TS_PLUGIN !== 'false') ||
203
+ options.workspaces &&
204
+ process.env.NX_ADD_PLUGINS !== 'false') ||
216
205
  options.preset === presets_1.Preset.NPM
217
206
  ? './files-package-based-repo'
218
207
  : './files-integrated-repo';
@@ -227,7 +216,7 @@ function createFiles(tree, options) {
227
216
  packageManager: options.packageManager,
228
217
  });
229
218
  }
230
- async function createReadme(tree, { name, appName, directory, preset, nxCloud }, nxCloudToken) {
219
+ async function createReadme(tree, { name, appName, directory, preset, nxCloud, workspaces }, nxCloudToken) {
231
220
  const formattedNames = (0, devkit_1.names)(name);
232
221
  // default to an empty one for custom presets
233
222
  const presetInfo = presetToPluginMap[preset] ?? {
@@ -241,8 +230,7 @@ async function createReadme(tree, { name, appName, directory, preset, nxCloud },
241
230
  formattedNames,
242
231
  isJsStandalone: preset === presets_1.Preset.TsStandalone,
243
232
  isTsPreset: preset === presets_1.Preset.TS,
244
- isUsingNewTsSolutionSetup: process.env.NX_ADD_PLUGINS !== 'false' &&
245
- process.env.NX_ADD_TS_PLUGIN !== 'false',
233
+ isUsingNewTsSolutionSetup: process.env.NX_ADD_PLUGINS !== 'false' && workspaces,
246
234
  isEmptyRepo: !appName,
247
235
  appName,
248
236
  generateAppCmd: presetInfo.generateAppCmd,
@@ -325,12 +313,11 @@ function setUpWorkspacesInPackageJson(tree, options) {
325
313
  if (options.preset === presets_1.Preset.NPM ||
326
314
  (options.preset === presets_1.Preset.TS &&
327
315
  process.env.NX_ADD_PLUGINS !== 'false' &&
328
- process.env.NX_ADD_TS_PLUGIN !== 'false') ||
316
+ options.workspaces) ||
329
317
  ((options.preset === presets_1.Preset.Expo ||
330
318
  options.preset === presets_1.Preset.NextJs ||
331
319
  options.preset === presets_1.Preset.ReactMonorepo ||
332
320
  options.preset === presets_1.Preset.ReactNative ||
333
- options.preset === presets_1.Preset.RemixMonorepo ||
334
321
  options.preset === presets_1.Preset.VueMonorepo ||
335
322
  options.preset === presets_1.Preset.Nuxt ||
336
323
  options.preset === presets_1.Preset.NodeMonorepo ||
@@ -17,6 +17,7 @@ interface Schema {
17
17
  bundler?: 'vite' | 'webpack';
18
18
  standaloneApi?: boolean;
19
19
  routing?: boolean;
20
+ useReactRouter?: boolean;
20
21
  packageManager?: PackageManager;
21
22
  unitTestRunner?: 'jest' | 'vitest' | 'none';
22
23
  e2eTestRunner?: 'cypress' | 'playwright' | 'detox' | 'jest' | 'none';
@@ -28,6 +29,7 @@ interface Schema {
28
29
  formatter?: 'none' | 'prettier';
29
30
  workspaces?: boolean;
30
31
  workspaceGlobs?: string | string[];
32
+ useProjectJson?: boolean;
31
33
  }
32
34
  export interface NormalizedSchema extends Schema {
33
35
  presetVersion?: string;
@@ -25,6 +25,11 @@
25
25
  "type": "boolean",
26
26
  "default": true
27
27
  },
28
+ "useReactRouter": {
29
+ "description": "Use React Router for routing.",
30
+ "type": "boolean",
31
+ "default": false
32
+ },
28
33
  "standaloneApi": {
29
34
  "description": "Use Standalone Components if generating an Angular application.",
30
35
  "type": "boolean",
@@ -105,7 +110,11 @@
105
110
  "workspaces": {
106
111
  "description": "Whether to use package manager workspaces.",
107
112
  "type": "boolean",
108
- "default": false
113
+ "default": true
114
+ },
115
+ "useProjectJson": {
116
+ "type": "boolean",
117
+ "description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
109
118
  }
110
119
  },
111
120
  "additionalProperties": true
@@ -4,10 +4,9 @@ exports.npmPackageGenerator = npmPackageGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
6
6
  const path_1 = require("path");
7
- const get_import_path_1 = require("../../utilities/get-import-path");
8
7
  async function normalizeOptions(tree, options) {
9
- await (0, project_name_and_root_utils_1.ensureProjectName)(tree, options, 'library');
10
- const { projectName, projectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
8
+ await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'library');
9
+ const { projectName, projectRoot, importPath } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
11
10
  name: options.name,
12
11
  projectType: 'library',
13
12
  directory: options.directory,
@@ -16,12 +15,13 @@ async function normalizeOptions(tree, options) {
16
15
  ...options,
17
16
  name: projectName,
18
17
  projectRoot,
18
+ importPath,
19
19
  };
20
20
  }
21
21
  function addFiles(projectRoot, tree, options) {
22
22
  const packageJsonPath = (0, path_1.join)(projectRoot, 'package.json');
23
23
  (0, devkit_1.writeJson)(tree, packageJsonPath, {
24
- name: (0, get_import_path_1.getImportPath)(tree, options.name),
24
+ name: options.importPath,
25
25
  version: '0.0.0',
26
26
  scripts: {
27
27
  test: 'node index.js',
@@ -70,9 +70,12 @@ async function createPreset(tree, options) {
70
70
  unitTestRunner: options.unitTestRunner ??
71
71
  (options.bundler === 'vite' ? 'vitest' : 'jest'),
72
72
  addPlugin,
73
+ routing: options.routing,
74
+ useReactRouter: options.useReactRouter,
73
75
  nxCloudToken: options.nxCloudToken,
74
76
  useTsSolution: options.workspaces,
75
77
  formatter: options.formatter,
78
+ useProjectJson: options.useProjectJson,
76
79
  });
77
80
  }
78
81
  else if (options.preset === presets_1.Preset.ReactStandalone) {
@@ -86,6 +89,8 @@ async function createPreset(tree, options) {
86
89
  linter: options.linter,
87
90
  rootProject: true,
88
91
  bundler,
92
+ routing: options.routing,
93
+ useReactRouter: options.useReactRouter,
89
94
  e2eTestRunner: options.e2eTestRunner ?? 'playwright',
90
95
  unitTestRunner: options.unitTestRunner ?? (bundler === 'vite' ? 'vitest' : 'jest'),
91
96
  addPlugin,
@@ -93,36 +98,6 @@ async function createPreset(tree, options) {
93
98
  formatter: options.formatter,
94
99
  });
95
100
  }
96
- else if (options.preset === presets_1.Preset.RemixMonorepo) {
97
- const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
98
- '/remix/generators');
99
- return remixApplicationGenerator(tree, {
100
- name: options.name,
101
- directory: (0, path_1.join)('apps', options.name),
102
- linter: options.linter,
103
- e2eTestRunner: options.e2eTestRunner ?? 'playwright',
104
- unitTestRunner: options.unitTestRunner ?? 'vitest',
105
- addPlugin,
106
- nxCloudToken: options.nxCloudToken,
107
- useTsSolution: options.workspaces,
108
- formatter: options.formatter,
109
- });
110
- }
111
- else if (options.preset === presets_1.Preset.RemixStandalone) {
112
- const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
113
- '/remix/generators');
114
- return remixApplicationGenerator(tree, {
115
- name: options.name,
116
- directory: '.',
117
- linter: options.linter,
118
- e2eTestRunner: options.e2eTestRunner ?? 'playwright',
119
- rootProject: true,
120
- unitTestRunner: options.unitTestRunner ?? 'vitest',
121
- addPlugin,
122
- nxCloudToken: options.nxCloudToken,
123
- formatter: options.formatter,
124
- });
125
- }
126
101
  else if (options.preset === presets_1.Preset.VueMonorepo) {
127
102
  const { applicationGenerator: vueApplicationGenerator } = require('@nx' +
128
103
  '/vue');
@@ -137,6 +112,7 @@ async function createPreset(tree, options) {
137
112
  nxCloudToken: options.nxCloudToken,
138
113
  useTsSolution: options.workspaces,
139
114
  formatter: options.formatter,
115
+ useProjectJson: options.useProjectJson,
140
116
  });
141
117
  }
142
118
  else if (options.preset === presets_1.Preset.VueStandalone) {
@@ -168,6 +144,7 @@ async function createPreset(tree, options) {
168
144
  nxCloudToken: options.nxCloudToken,
169
145
  useTsSolution: options.workspaces,
170
146
  formatter: options.formatter,
147
+ useProjectJson: options.useProjectJson,
171
148
  });
172
149
  }
173
150
  else if (options.preset === presets_1.Preset.NuxtStandalone) {
@@ -200,6 +177,7 @@ async function createPreset(tree, options) {
200
177
  addPlugin,
201
178
  useTsSolution: options.workspaces,
202
179
  formatter: options.formatter,
180
+ useProjectJson: options.useProjectJson,
203
181
  });
204
182
  }
205
183
  else if (options.preset === presets_1.Preset.NextJsStandalone) {
@@ -245,6 +223,7 @@ async function createPreset(tree, options) {
245
223
  addPlugin,
246
224
  useTsSolution: options.workspaces,
247
225
  formatter: options.formatter,
226
+ useProjectJson: options.useProjectJson,
248
227
  });
249
228
  }
250
229
  else if (options.preset === presets_1.Preset.Express) {
@@ -258,6 +237,7 @@ async function createPreset(tree, options) {
258
237
  addPlugin,
259
238
  useTsSolution: options.workspaces,
260
239
  formatter: options.formatter,
240
+ useProjectJson: options.useProjectJson,
261
241
  });
262
242
  }
263
243
  else if (options.preset === presets_1.Preset.ReactNative) {
@@ -274,6 +254,7 @@ async function createPreset(tree, options) {
274
254
  bundler: options.bundler ?? 'webpack',
275
255
  useTsSolution: options.workspaces,
276
256
  formatter: options.formatter,
257
+ useProjectJson: options.useProjectJson,
277
258
  });
278
259
  }
279
260
  else if (options.preset === presets_1.Preset.Expo) {
@@ -288,14 +269,14 @@ async function createPreset(tree, options) {
288
269
  nxCloudToken: options.nxCloudToken,
289
270
  useTsSolution: options.workspaces,
290
271
  formatter: options.formatter,
272
+ useProjectJson: options.useProjectJson,
291
273
  });
292
274
  }
293
275
  else if (options.preset === presets_1.Preset.TS) {
294
276
  const { initGenerator } = require('@nx' + '/js');
295
277
  return initGenerator(tree, {
296
278
  formatter: options.formatter,
297
- addTsPlugin: process.env.NX_ADD_PLUGINS !== 'false' &&
298
- process.env.NX_ADD_TS_PLUGIN !== 'false',
279
+ addTsPlugin: process.env.NX_ADD_PLUGINS !== 'false' && options.workspaces,
299
280
  });
300
281
  }
301
282
  else if (options.preset === presets_1.Preset.TsStandalone) {
@@ -346,6 +327,7 @@ async function createPreset(tree, options) {
346
327
  addPlugin,
347
328
  useTsSolution: options.workspaces,
348
329
  formatter: options.formatter,
330
+ useProjectJson: options.useProjectJson,
349
331
  });
350
332
  }
351
333
  else {
@@ -16,6 +16,7 @@ export interface Schema {
16
16
  nextAppDir?: boolean;
17
17
  nextSrcDir?: boolean;
18
18
  routing?: boolean;
19
+ useReactRouter?: boolean;
19
20
  standaloneApi?: boolean;
20
21
  unitTestRunner?: 'jest' | 'vitest' | 'none';
21
22
  e2eTestRunner?: 'cypress' | 'playwright' | 'jest' | 'detox' | 'none';
@@ -24,4 +25,5 @@ export interface Schema {
24
25
  serverRouting?: boolean;
25
26
  prefix?: string;
26
27
  nxCloudToken?: string;
28
+ useProjectJson?: boolean;
27
29
  }
@@ -25,6 +25,11 @@
25
25
  "type": "boolean",
26
26
  "default": true
27
27
  },
28
+ "useReactRouter": {
29
+ "description": "Use React Router for routing.",
30
+ "type": "boolean",
31
+ "default": false
32
+ },
28
33
  "style": {
29
34
  "description": "The file extension to be used for style files.",
30
35
  "type": "string",
@@ -122,7 +127,11 @@
122
127
  "workspaces": {
123
128
  "description": "Whether to use package manager workspaces.",
124
129
  "type": "boolean",
125
- "default": false
130
+ "default": true
131
+ },
132
+ "useProjectJson": {
133
+ "type": "boolean",
134
+ "description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
126
135
  }
127
136
  },
128
137
  "required": ["preset", "name"]
@@ -8,8 +8,6 @@ export declare enum Preset {
8
8
  ReactMonorepo = "react-monorepo",
9
9
  ReactStandalone = "react-standalone",
10
10
  NextJsStandalone = "nextjs-standalone",
11
- RemixMonorepo = "remix-monorepo",
12
- RemixStandalone = "remix-standalone",
13
11
  ReactNative = "react-native",
14
12
  VueMonorepo = "vue-monorepo",
15
13
  VueStandalone = "vue-standalone",
@@ -12,8 +12,6 @@ var Preset;
12
12
  Preset["ReactMonorepo"] = "react-monorepo";
13
13
  Preset["ReactStandalone"] = "react-standalone";
14
14
  Preset["NextJsStandalone"] = "nextjs-standalone";
15
- Preset["RemixMonorepo"] = "remix-monorepo";
16
- Preset["RemixStandalone"] = "remix-standalone";
17
15
  Preset["ReactNative"] = "react-native";
18
16
  Preset["VueMonorepo"] = "vue-monorepo";
19
17
  Preset["VueStandalone"] = "vue-standalone";
@@ -0,0 +1,5 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export declare function isProjectIncludedInPackageManagerWorkspaces(tree: Tree, projectRoot: string): boolean;
3
+ export declare function getPackageManagerWorkspacesPatterns(tree: Tree): string[];
4
+ export declare function isUsingPackageManagerWorkspaces(tree: Tree): boolean;
5
+ export declare function isWorkspacesEnabled(tree: Tree): boolean;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isProjectIncludedInPackageManagerWorkspaces = isProjectIncludedInPackageManagerWorkspaces;
4
+ exports.getPackageManagerWorkspacesPatterns = getPackageManagerWorkspacesPatterns;
5
+ exports.isUsingPackageManagerWorkspaces = isUsingPackageManagerWorkspaces;
6
+ exports.isWorkspacesEnabled = isWorkspacesEnabled;
7
+ const devkit_1 = require("@nx/devkit");
8
+ const posix_1 = require("node:path/posix");
9
+ const package_json_1 = require("nx/src/plugins/package-json");
10
+ const picomatch = require("picomatch");
11
+ function isProjectIncludedInPackageManagerWorkspaces(tree, projectRoot) {
12
+ if (!isUsingPackageManagerWorkspaces(tree)) {
13
+ return false;
14
+ }
15
+ const patterns = getPackageManagerWorkspacesPatterns(tree);
16
+ return patterns.some((p) => picomatch(p)((0, posix_1.join)(projectRoot, 'package.json')));
17
+ }
18
+ function getPackageManagerWorkspacesPatterns(tree) {
19
+ return (0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(tree.root, (path) => (0, devkit_1.readJson)(tree, path, { expectComments: true }), (path) => {
20
+ const content = tree.read(path, 'utf-8');
21
+ const { load } = require('@zkochan/js-yaml');
22
+ return load(content, { filename: path });
23
+ }, (path) => tree.exists(path));
24
+ }
25
+ function isUsingPackageManagerWorkspaces(tree) {
26
+ return isWorkspacesEnabled(tree);
27
+ }
28
+ function isWorkspacesEnabled(tree) {
29
+ const packageManager = (0, devkit_1.detectPackageManager)(tree.root);
30
+ if (packageManager === 'pnpm') {
31
+ return tree.exists('pnpm-workspace.yaml');
32
+ }
33
+ // yarn and npm both use the same 'workspaces' property in package.json
34
+ if (tree.exists('package.json')) {
35
+ const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
36
+ return !!packageJson?.workspaces;
37
+ }
38
+ return false;
39
+ }
@@ -1,2 +1,3 @@
1
1
  import { type Tree } from '@nx/devkit';
2
2
  export declare function isUsingTsSolutionSetup(tree?: Tree): boolean;
3
+ export declare function addProjectToTsSolutionWorkspace(tree: Tree, projectDir: string): Promise<void>;
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isUsingTsSolutionSetup = isUsingTsSolutionSetup;
4
+ exports.addProjectToTsSolutionWorkspace = addProjectToTsSolutionWorkspace;
4
5
  const devkit_1 = require("@nx/devkit");
6
+ const posix_1 = require("node:path/posix");
5
7
  const tree_1 = require("nx/src/generators/tree");
8
+ const package_manager_workspaces_1 = require("../package-manager-workspaces");
6
9
  function isUsingPackageManagerWorkspaces(tree) {
7
10
  return isWorkspacesEnabled(tree);
8
11
  }
@@ -55,3 +58,48 @@ function isUsingTsSolutionSetup(tree) {
55
58
  return (isUsingPackageManagerWorkspaces(tree) &&
56
59
  isWorkspaceSetupWithTsSolution(tree));
57
60
  }
61
+ async function addProjectToTsSolutionWorkspace(tree, projectDir) {
62
+ const isIncluded = (0, package_manager_workspaces_1.isProjectIncludedInPackageManagerWorkspaces)(tree, projectDir);
63
+ if (isIncluded) {
64
+ return;
65
+ }
66
+ // If dir is "libs/foo", we try to use "libs/*" but we only do it if it's
67
+ // safe to do so. So, we first check if adding that pattern doesn't result
68
+ // in extra projects being matched. If extra projects are matched, or the
69
+ // dir is just "foo" then we add it as is.
70
+ const baseDir = (0, posix_1.dirname)(projectDir);
71
+ let pattern = projectDir;
72
+ if (baseDir !== '.') {
73
+ const patterns = (0, package_manager_workspaces_1.getPackageManagerWorkspacesPatterns)(tree);
74
+ const projectsBefore = await (0, devkit_1.globAsync)(tree, patterns);
75
+ patterns.push(`${baseDir}/*/package.json`);
76
+ const projectsAfter = await (0, devkit_1.globAsync)(tree, patterns);
77
+ if (projectsBefore.length + 1 === projectsAfter.length) {
78
+ // Adding the pattern to the parent directory only results in one extra
79
+ // project being matched, which is the project we're adding. It's safe
80
+ // to add the pattern to the parent directory.
81
+ pattern = `${baseDir}/*`;
82
+ }
83
+ }
84
+ if (tree.exists('pnpm-workspace.yaml')) {
85
+ const { load, dump } = require('@zkochan/js-yaml');
86
+ const workspaceFile = tree.read('pnpm-workspace.yaml', 'utf-8');
87
+ const yamlData = load(workspaceFile) ?? {};
88
+ yamlData.packages ??= [];
89
+ if (!yamlData.packages.includes(pattern)) {
90
+ yamlData.packages.push(pattern);
91
+ tree.write('pnpm-workspace.yaml', dump(yamlData, { indent: 2, quotingType: '"', forceQuotes: true }));
92
+ }
93
+ }
94
+ else {
95
+ // Update package.json
96
+ const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
97
+ if (!packageJson.workspaces) {
98
+ packageJson.workspaces = [];
99
+ }
100
+ if (!packageJson.workspaces.includes(pattern)) {
101
+ packageJson.workspaces.push(pattern);
102
+ tree.write('package.json', JSON.stringify(packageJson, null, 2));
103
+ }
104
+ }
105
+ }
@@ -1,3 +1,3 @@
1
1
  export declare const nxVersion: any;
2
2
  export declare const typescriptVersion = "~5.7.2";
3
- export declare const angularCliVersion = "~19.1.0";
3
+ export declare const angularCliVersion = "~19.2.0";
@@ -5,4 +5,4 @@ exports.nxVersion = require('../../package.json').version;
5
5
  exports.typescriptVersion = '~5.7.2';
6
6
  // TODO: remove when preset generation is reworked and
7
7
  // deps are not installed from workspace
8
- exports.angularCliVersion = '~19.1.0';
8
+ exports.angularCliVersion = '~19.2.0';