feat(misc): introduce a way to set the project name/root format for all generators (#18971)
This commit is contained in:
parent
0cc6ba996f
commit
bd1b0b70fd
@ -191,7 +191,8 @@ Where new apps + libs should be placed
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type |
|
||||
| :-------- | :------- |
|
||||
| `appsDir` | `string` |
|
||||
| `libsDir` | `string` |
|
||||
| Name | Type |
|
||||
| :-------------------------- | :----------------------------- |
|
||||
| `appsDir?` | `string` |
|
||||
| `libsDir?` | `string` |
|
||||
| `projectNameAndRootFormat?` | `"as-provided"` \| `"derived"` |
|
||||
|
||||
@ -267,10 +267,11 @@ Where new apps + libs should be placed
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type |
|
||||
| :-------- | :------- |
|
||||
| `appsDir` | `string` |
|
||||
| `libsDir` | `string` |
|
||||
| Name | Type |
|
||||
| :-------------------------- | :----------------------------- |
|
||||
| `appsDir?` | `string` |
|
||||
| `libsDir?` | `string` |
|
||||
| `projectNameAndRootFormat?` | `"as-provided"` \| `"derived"` |
|
||||
|
||||
#### Inherited from
|
||||
|
||||
|
||||
@ -558,7 +558,7 @@ describe('Linter', () => {
|
||||
bundler: 'vite',
|
||||
e2eTestRunner: 'none',
|
||||
});
|
||||
runCLI(`generate @nx/js:lib ${mylib}`);
|
||||
runCLI(`generate @nx/js:lib ${mylib} --directory libs/${mylib}`);
|
||||
|
||||
// migrate to flat structure
|
||||
runCLI(`generate @nx/linter:convert-to-flat-config`);
|
||||
|
||||
@ -28,7 +28,7 @@ import {
|
||||
RunCmdOpts,
|
||||
runCommand,
|
||||
} from './command-utils';
|
||||
import { output } from '@nx/devkit';
|
||||
import { NxJsonConfiguration, output } from '@nx/devkit';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
@ -41,6 +41,7 @@ let projName: string;
|
||||
export function newProject({
|
||||
name = uniq('proj'),
|
||||
packageManager = getSelectedPackageManager(),
|
||||
unsetProjectNameAndRootFormat = true,
|
||||
} = {}): string {
|
||||
try {
|
||||
const projScope = 'proj';
|
||||
@ -51,6 +52,13 @@ export function newProject({
|
||||
packageManager,
|
||||
});
|
||||
|
||||
if (unsetProjectNameAndRootFormat) {
|
||||
updateJson<NxJsonConfiguration>('nx.json', (nxJson) => {
|
||||
delete nxJson.workspaceLayout;
|
||||
return nxJson;
|
||||
});
|
||||
}
|
||||
|
||||
// Temporary hack to prevent installing with `--frozen-lockfile`
|
||||
if (isCI && packageManager === 'pnpm') {
|
||||
updateFile(
|
||||
|
||||
@ -348,10 +348,21 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
|
||||
expect(promptSpy).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(readNxJson(tree).generators['@nx/some-plugin:app']).toEqual({
|
||||
expect(readNxJson(tree).workspaceLayout).toEqual({
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
});
|
||||
|
||||
promptSpy.mockReset();
|
||||
|
||||
await determineProjectNameAndRootOptions(tree, {
|
||||
name: 'libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '@nx/some-plugin:app',
|
||||
});
|
||||
|
||||
expect(promptSpy).not.toHaveBeenCalled();
|
||||
|
||||
// restore original interactive mode
|
||||
restoreOriginalInteractiveMode();
|
||||
});
|
||||
|
||||
@ -75,7 +75,9 @@ export async function determineProjectNameAndRootOptions(
|
||||
const formats = getProjectNameAndRootFormats(tree, options);
|
||||
const format =
|
||||
options.projectNameAndRootFormat ??
|
||||
(await determineFormat(tree, formats, options.callingGenerator));
|
||||
(getDefaultProjectNameAndRootFormat(tree) === 'as-provided'
|
||||
? 'as-provided'
|
||||
: await determineFormat(tree, formats, options.callingGenerator));
|
||||
|
||||
return {
|
||||
...formats[format],
|
||||
@ -167,11 +169,7 @@ async function determineFormat(
|
||||
initial: true,
|
||||
});
|
||||
if (saveDefault) {
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.generators ??= {};
|
||||
nxJson.generators[callingGenerator] ??= {};
|
||||
nxJson.generators[callingGenerator].projectNameAndRootFormat = result;
|
||||
updateNxJson(tree, nxJson);
|
||||
setProjectNameAndRootFormatDefault(tree);
|
||||
} else {
|
||||
logger.warn(deprecationWarning);
|
||||
}
|
||||
@ -183,6 +181,18 @@ async function determineFormat(
|
||||
return result;
|
||||
}
|
||||
|
||||
function setProjectNameAndRootFormatDefault(tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.workspaceLayout ??= {};
|
||||
nxJson.workspaceLayout.projectNameAndRootFormat = 'as-provided';
|
||||
updateNxJson(tree, nxJson);
|
||||
}
|
||||
|
||||
function getDefaultProjectNameAndRootFormat(tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
return nxJson.workspaceLayout?.projectNameAndRootFormat ?? 'derived';
|
||||
}
|
||||
|
||||
function getProjectNameAndRootFormats(
|
||||
tree: Tree,
|
||||
options: ProjectGenerationOptions
|
||||
|
||||
@ -41,6 +41,7 @@ export function toNodeApplicationGeneratorOptions(
|
||||
name: options.name,
|
||||
directory: options.directory,
|
||||
frontendProject: options.frontendProject,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
linter: options.linter,
|
||||
skipFormat: true,
|
||||
skipPackageJson: options.skipPackageJson,
|
||||
|
||||
@ -56,6 +56,11 @@
|
||||
"appsDir": {
|
||||
"type": "string",
|
||||
"description": "Default folder name for apps."
|
||||
},
|
||||
"projectNameAndRootFormat": {
|
||||
"type": "string",
|
||||
"description": "Default method of handling arguments for generating projects",
|
||||
"enum": ["as-provided", "derived"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@ -86,8 +86,9 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
|
||||
* Where new apps + libs should be placed
|
||||
*/
|
||||
workspaceLayout?: {
|
||||
libsDir: string;
|
||||
appsDir: string;
|
||||
libsDir?: string;
|
||||
appsDir?: string;
|
||||
projectNameAndRootFormat?: 'as-provided' | 'derived';
|
||||
};
|
||||
/**
|
||||
* Available Task Runners
|
||||
|
||||
@ -53,5 +53,8 @@ exports[`new should generate an empty nx.json 1`] = `
|
||||
"runner": "nx/tasks-runners/default",
|
||||
},
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"projectNameAndRootFormat": "as-provided",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
@ -122,6 +122,9 @@ describe('@nx/workspace:generateWorkspaceFiles', () => {
|
||||
"runner": "nx/tasks-runners/default",
|
||||
},
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"projectNameAndRootFormat": "as-provided",
|
||||
},
|
||||
}
|
||||
`);
|
||||
const validateNxJson = ajv.compile(nxSchema);
|
||||
@ -174,6 +177,9 @@ describe('@nx/workspace:generateWorkspaceFiles', () => {
|
||||
"runner": "nx/tasks-runners/default",
|
||||
},
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"projectNameAndRootFormat": "as-provided",
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
@ -98,6 +98,9 @@ function createNxJson(
|
||||
},
|
||||
},
|
||||
},
|
||||
workspaceLayout: {
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
},
|
||||
};
|
||||
|
||||
nxJson.targetDefaults = {
|
||||
|
||||
@ -41,27 +41,28 @@ export interface NormalizedSchema extends Schema {
|
||||
isCustomPreset: boolean;
|
||||
}
|
||||
|
||||
export async function newGenerator(host: Tree, opts: Schema) {
|
||||
export async function newGenerator(tree: Tree, opts: Schema) {
|
||||
const options = normalizeOptions(opts);
|
||||
validateOptions(options, host);
|
||||
validateOptions(options, tree);
|
||||
|
||||
await generateWorkspaceFiles(host, { ...options, nxCloud: undefined } as any);
|
||||
await generateWorkspaceFiles(tree, { ...options, nxCloud: undefined } as any);
|
||||
|
||||
addPresetDependencies(host, options);
|
||||
addCloudDependencies(host, options);
|
||||
addPresetDependencies(tree, options);
|
||||
|
||||
addCloudDependencies(tree, options);
|
||||
|
||||
return async () => {
|
||||
const pmc = getPackageManagerCommand(options.packageManager);
|
||||
if (pmc.preInstall) {
|
||||
execSync(pmc.preInstall, {
|
||||
cwd: joinPathFragments(host.root, options.directory),
|
||||
cwd: joinPathFragments(tree.root, options.directory),
|
||||
stdio: process.env.NX_GENERATE_QUIET === 'true' ? 'ignore' : 'inherit',
|
||||
});
|
||||
}
|
||||
installPackagesTask(host, false, options.directory, options.packageManager);
|
||||
installPackagesTask(tree, false, options.directory, options.packageManager);
|
||||
// TODO: move all of these into create-nx-workspace
|
||||
if (options.preset !== Preset.NPM && !options.isCustomPreset) {
|
||||
await generatePreset(host, options);
|
||||
await generatePreset(tree, options);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
} from '@nx/devkit';
|
||||
import { Schema } from './schema';
|
||||
import { Preset } from '../utils/presets';
|
||||
import { join } from 'path';
|
||||
|
||||
export async function presetGenerator(tree: Tree, options: Schema) {
|
||||
options = normalizeOptions(options);
|
||||
@ -29,6 +30,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return angularApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
standalone: options.standaloneApi,
|
||||
@ -42,6 +45,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return angularApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
routing: options.routing,
|
||||
@ -55,6 +60,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return reactApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
bundler: options.bundler ?? 'webpack',
|
||||
@ -66,6 +73,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return reactApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
rootProject: true,
|
||||
@ -79,6 +88,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return nextApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
appDir: options.nextAppDir,
|
||||
@ -89,6 +100,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
'/next');
|
||||
return nextApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
appDir: options.nextAppDir,
|
||||
@ -101,6 +114,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return webApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
style: options.style,
|
||||
linter: options.linter,
|
||||
bundler: 'vite',
|
||||
@ -112,6 +127,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
|
||||
return nestApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'jest',
|
||||
});
|
||||
@ -121,6 +138,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
} = require('@nx' + '/express');
|
||||
return expressApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'jest',
|
||||
});
|
||||
@ -129,6 +148,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
'/react-native');
|
||||
return reactNativeApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'detox',
|
||||
});
|
||||
@ -136,24 +157,20 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
const { expoApplicationGenerator } = require('@nx' + '/expo');
|
||||
return expoApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'detox',
|
||||
});
|
||||
} else if (options.preset === Preset.TS) {
|
||||
const c = readNxJson(tree);
|
||||
const { initGenerator } = require('@nx' + '/js');
|
||||
c.workspaceLayout = {
|
||||
appsDir: 'packages',
|
||||
libsDir: 'packages',
|
||||
};
|
||||
updateNxJson(tree, c);
|
||||
return initGenerator(tree, {});
|
||||
} else if (options.preset === Preset.TsStandalone) {
|
||||
const c = readNxJson(tree);
|
||||
const { libraryGenerator } = require('@nx' + '/js');
|
||||
updateNxJson(tree, c);
|
||||
return libraryGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('packages', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
bundler: 'tsc',
|
||||
unitTestRunner: 'vitest',
|
||||
testEnvironment: 'node',
|
||||
@ -167,6 +184,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
return nodeApplicationGenerator(tree, {
|
||||
bundler,
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
standaloneConfig: options.standaloneConfig,
|
||||
framework: options.framework,
|
||||
@ -181,6 +200,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
return nodeApplicationGenerator(tree, {
|
||||
bundler,
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
framework: options.framework,
|
||||
docker: options.docker,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user