feat(misc): add --useProjectJson flag to CNW (#30475)

## Current Behavior

Creating new workspaces since Nx 20.6.0 will generate the Nx
configuration in `package.json` files. This is intended, given that it
is part of the new setup using TypeScript Project References and Package
Manager Workspaces, but there's no way to choose to generate the Nx
configuration in `project.json` files. Project generators do allow to
choose but there's no way to do it when creating a new workspace. This
forces users who want to use `project.json` files to generate an empty
workspace and then use a project generator.

## Expected Behavior

When creating a new Nx workspace, users can provide an option
(`--use-project-json`) to generate the Nx configuration in
`project.json` files.

## Related Issue(s)

Fixes #30464
This commit is contained in:
Leosvel Pérez Espinosa 2025-03-24 13:42:18 +01:00 committed by GitHub
parent 3d710ce923
commit cfe32c2560
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 36 additions and 9 deletions

View File

@ -46,6 +46,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
| `--style` | string | Stylesheet type to be used with certain stacks. |
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
| `--useProjectJson` | boolean | Use a 'project.json' file for the Nx configuration instead of a 'package.json' file. This defaults to 'true' when '--no-workspaces' is used. Otherwise, it defaults to 'false'. |
| `--useReactRouter` | boolean | Generate a Server-Side Rendered (SSR) React app using React Router. |
| `--version` | boolean | Show version number. |
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |

View File

@ -46,6 +46,7 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
| `--style` | string | Stylesheet type to be used with certain stacks. |
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
| `--useProjectJson` | boolean | Use a 'project.json' file for the Nx configuration instead of a 'package.json' file. This defaults to 'true' when '--no-workspaces' is used. Otherwise, it defaults to 'false'. |
| `--useReactRouter` | boolean | Generate a Server-Side Rendered (SSR) React app using React Router. |
| `--version` | boolean | Show version number. |
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |

View File

@ -108,6 +108,10 @@
"description": "Whether to use package manager workspaces.",
"type": "boolean",
"default": true
},
"useProjectJson": {
"type": "boolean",
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
}
},
"additionalProperties": true,

View File

@ -125,6 +125,10 @@
"description": "Whether to use package manager workspaces.",
"type": "boolean",
"default": true
},
"useProjectJson": {
"type": "boolean",
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
}
},
"required": ["preset", "name"],

View File

@ -35,6 +35,7 @@ interface BaseArguments extends CreateWorkspaceOptions {
linter?: 'none' | 'eslint';
formatter?: 'none' | 'prettier';
workspaces?: boolean;
useProjectJson?: boolean;
}
interface NoneArguments extends BaseArguments {
@ -175,6 +176,10 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
type: 'boolean',
default: true,
})
.option('useProjectJson', {
describe: chalk.dim`Use a 'project.json' file for the Nx configuration instead of a 'package.json' file. This defaults to 'true' when '--no-workspaces' is used. Otherwise, it defaults to 'false'.`,
type: 'boolean',
})
.option('formatter', {
describe: chalk.dim`Code formatter to use.`,
type: 'string',
@ -288,6 +293,7 @@ async function normalizeArgsMiddleware(
});
argv.workspaces ??= true;
argv.useProjectJson ??= !argv.workspaces;
try {
argv.name = await determineFolder(argv);

View File

@ -103,6 +103,7 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
opts.formatter ? `--formatter=${opts.formatter}` : null,
opts.workspaces !== false ? `--workspaces` : `--no-workspaces`,
opts.useProjectJson ? `--useProjectJson` : null,
].filter((e) => !!e);
}
}

View File

@ -43,6 +43,7 @@ interface Schema {
formatter?: 'none' | 'prettier';
workspaces?: boolean;
workspaceGlobs?: string | string[];
useProjectJson?: boolean;
}
export interface NormalizedSchema extends Schema {

View File

@ -111,6 +111,10 @@
"description": "Whether to use package manager workspaces.",
"type": "boolean",
"default": true
},
"useProjectJson": {
"type": "boolean",
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
}
},
"additionalProperties": true

View File

@ -82,7 +82,7 @@ async function createPreset(tree: Tree, options: Schema) {
nxCloudToken: options.nxCloudToken,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.ReactStandalone) {
const { applicationGenerator: reactApplicationGenerator } = require('@nx' +
@ -121,7 +121,7 @@ async function createPreset(tree: Tree, options: Schema) {
nxCloudToken: options.nxCloudToken,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.VueStandalone) {
const { applicationGenerator: vueApplicationGenerator } = require('@nx' +
@ -153,7 +153,7 @@ async function createPreset(tree: Tree, options: Schema) {
nxCloudToken: options.nxCloudToken,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.NuxtStandalone) {
const { applicationGenerator: nuxtApplicationGenerator } = require('@nx' +
@ -186,7 +186,7 @@ async function createPreset(tree: Tree, options: Schema) {
addPlugin,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.NextJsStandalone) {
const { applicationGenerator: nextApplicationGenerator } = require('@nx' +
@ -231,7 +231,7 @@ async function createPreset(tree: Tree, options: Schema) {
addPlugin,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.Express) {
const {
@ -246,7 +246,7 @@ async function createPreset(tree: Tree, options: Schema) {
addPlugin,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.ReactNative) {
const { reactNativeApplicationGenerator } = require('@nx' +
@ -262,7 +262,7 @@ async function createPreset(tree: Tree, options: Schema) {
bundler: options.bundler ?? 'webpack',
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.Expo) {
const { expoApplicationGenerator } = require('@nx' + '/expo');
@ -276,7 +276,7 @@ async function createPreset(tree: Tree, options: Schema) {
nxCloudToken: options.nxCloudToken,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else if (options.preset === Preset.TS) {
const { initGenerator } = require('@nx' + '/js');
@ -330,7 +330,7 @@ async function createPreset(tree: Tree, options: Schema) {
addPlugin,
useTsSolution: options.workspaces,
formatter: options.formatter,
useProjectJson: !options.workspaces,
useProjectJson: options.useProjectJson,
});
} else {
throw new Error(`Invalid preset ${options.preset}`);

View File

@ -25,4 +25,5 @@ export interface Schema {
serverRouting?: boolean;
prefix?: string;
nxCloudToken?: string;
useProjectJson?: boolean;
}

View File

@ -128,6 +128,10 @@
"description": "Whether to use package manager workspaces.",
"type": "boolean",
"default": true
},
"useProjectJson": {
"type": "boolean",
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
}
},
"required": ["preset", "name"]