feat(misc): save directory and name format to nx json defaults (#18683)
This commit is contained in:
parent
61d73fc907
commit
e2ff519db2
@ -21,6 +21,7 @@ export async function normalizeOptions(
|
||||
directory: options.directory,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
rootProject: options.rootProject,
|
||||
callingGenerator: '@nx/angular:application',
|
||||
});
|
||||
options.rootProject = appProjectRoot === '.';
|
||||
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
||||
@ -34,6 +35,7 @@ export async function normalizeOptions(
|
||||
directory: options.directory,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
rootProject: options.rootProject,
|
||||
callingGenerator: '@nx/angular:application',
|
||||
});
|
||||
e2eProjectName = projectNameAndRoot.projectName;
|
||||
e2eProjectRoot = projectNameAndRoot.projectRoot;
|
||||
|
||||
@ -51,6 +51,7 @@ export async function hostInternal(tree: Tree, options: Schema) {
|
||||
projectType: 'application',
|
||||
directory: options.directory,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
callingGenerator: '@nx/angular:host',
|
||||
});
|
||||
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ export async function normalizeOptions(
|
||||
directory: options.directory,
|
||||
importPath: options.importPath,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
callingGenerator: '@nx/angular:library',
|
||||
});
|
||||
|
||||
const fileName = options.simpleName
|
||||
|
||||
@ -42,6 +42,7 @@ export async function remoteInternal(tree: Tree, options: Schema) {
|
||||
projectType: 'application',
|
||||
directory: options.directory,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
callingGenerator: '@nx/angular:remote',
|
||||
});
|
||||
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
||||
|
||||
|
||||
@ -250,6 +250,7 @@ async function normalizeOptions(
|
||||
projectNameAndRootFormat: isRootProject
|
||||
? 'as-provided'
|
||||
: options.projectNameAndRootFormat,
|
||||
callingGenerator: '@nx/cypress:cypress-project',
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import * as enquirer from 'enquirer';
|
||||
import { createTreeWithEmptyWorkspace } from 'nx/src/generators/testing-utils/create-tree-with-empty-workspace';
|
||||
import type { Tree } from 'nx/src/generators/tree';
|
||||
import { updateJson } from 'nx/src/generators/utils/json';
|
||||
import { readNxJson } from 'nx/src/generators/utils/nx-json';
|
||||
import { determineProjectNameAndRootOptions } from './project-name-and-root-utils';
|
||||
|
||||
describe('determineProjectNameAndRootOptions', () => {
|
||||
@ -40,6 +41,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
@ -60,6 +62,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -81,6 +84,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
importPath: '@custom-scope/lib-name',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -104,6 +108,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: '@scope/libName',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -129,6 +134,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -154,6 +160,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result.importPath).toBe('@proj/lib-name');
|
||||
@ -166,6 +173,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
})
|
||||
).rejects.toThrowError();
|
||||
});
|
||||
@ -176,6 +184,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -197,6 +206,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
callingGenerator: '',
|
||||
})
|
||||
).rejects.toThrowError();
|
||||
});
|
||||
@ -211,6 +221,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -236,6 +247,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result.importPath).toBe('@proj/lib-name');
|
||||
@ -252,6 +264,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: 'libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(promptSpy).toHaveBeenCalled();
|
||||
@ -275,6 +288,32 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
restoreOriginalInteractiveMode();
|
||||
});
|
||||
|
||||
it('should prompt to save default when as-provided is choosen', async () => {
|
||||
// simulate interactive mode
|
||||
ensureInteractiveMode();
|
||||
const promptSpy = jest
|
||||
.spyOn(enquirer, 'prompt')
|
||||
.mockImplementation(() =>
|
||||
Promise.resolve({ format: 'lib-name @ shared', saveDefault: true })
|
||||
);
|
||||
|
||||
await determineProjectNameAndRootOptions(tree, {
|
||||
name: 'libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '@nx/some-plugin:app',
|
||||
});
|
||||
|
||||
expect(promptSpy).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(readNxJson(tree).generators['@nx/some-plugin:app']).toEqual({
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
});
|
||||
|
||||
// restore original interactive mode
|
||||
restoreOriginalInteractiveMode();
|
||||
});
|
||||
|
||||
it('should directly use format as-provided and not prompt when the name is a scoped package name', async () => {
|
||||
// simulate interactive mode
|
||||
ensureInteractiveMode();
|
||||
@ -284,6 +323,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: '@scope/libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(promptSpy).not.toHaveBeenCalled();
|
||||
@ -315,6 +355,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -335,6 +376,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -356,6 +398,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
importPath: '@custom-scope/lib-name',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -380,6 +423,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: '@scope/libName',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -405,6 +449,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -430,6 +475,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result.importPath).toBe('@proj/lib-name');
|
||||
@ -442,6 +488,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
callingGenerator: '',
|
||||
})
|
||||
).rejects.toThrowError();
|
||||
});
|
||||
@ -452,6 +499,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -473,6 +521,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
directory: 'shared',
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
callingGenerator: '',
|
||||
})
|
||||
).rejects.toThrowError();
|
||||
});
|
||||
@ -488,6 +537,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'derived',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@ -513,6 +563,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
projectType: 'library',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
rootProject: true,
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(result.importPath).toBe('@proj/lib-name');
|
||||
@ -529,6 +580,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: 'libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(promptSpy).toHaveBeenCalled();
|
||||
@ -561,6 +613,7 @@ describe('determineProjectNameAndRootOptions', () => {
|
||||
name: '@scope/libName',
|
||||
projectType: 'library',
|
||||
directory: 'shared',
|
||||
callingGenerator: '',
|
||||
});
|
||||
|
||||
expect(promptSpy).not.toHaveBeenCalled();
|
||||
|
||||
@ -8,12 +8,13 @@ import {
|
||||
} from '../utils/get-workspace-layout';
|
||||
import { names } from '../utils/names';
|
||||
|
||||
const { joinPathFragments, readJson, readNxJson } = requireNx();
|
||||
const { joinPathFragments, readJson, readNxJson, updateNxJson } = requireNx();
|
||||
|
||||
export type ProjectNameAndRootFormat = 'as-provided' | 'derived';
|
||||
export type ProjectGenerationOptions = {
|
||||
name: string;
|
||||
projectType: ProjectType;
|
||||
callingGenerator: string;
|
||||
directory?: string;
|
||||
importPath?: string;
|
||||
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
||||
@ -65,7 +66,8 @@ export async function determineProjectNameAndRootOptions(
|
||||
validateName(options.name, options.projectNameAndRootFormat);
|
||||
const formats = getProjectNameAndRootFormats(tree, options);
|
||||
const format =
|
||||
options.projectNameAndRootFormat ?? (await determineFormat(formats));
|
||||
options.projectNameAndRootFormat ??
|
||||
(await determineFormat(tree, formats, options.callingGenerator));
|
||||
|
||||
return {
|
||||
...formats[format],
|
||||
@ -104,7 +106,9 @@ function validateName(
|
||||
}
|
||||
|
||||
async function determineFormat(
|
||||
formats: ProjectNameAndRootFormats
|
||||
tree: Tree,
|
||||
formats: ProjectNameAndRootFormats,
|
||||
callingGenerator: string
|
||||
): Promise<ProjectNameAndRootFormat> {
|
||||
if (!formats.derived) {
|
||||
return 'as-provided';
|
||||
@ -123,7 +127,7 @@ async function determineFormat(
|
||||
Root: ${formats['derived'].projectRoot}`;
|
||||
const derivedSelectedValue = `${formats['derived'].projectName} @ ${formats['derived'].projectRoot} (This was derived from the folder structure. Please provide the exact name and directory in the future)`;
|
||||
|
||||
return await prompt<{ format: ProjectNameAndRootFormat }>({
|
||||
const result = await prompt<{ format: ProjectNameAndRootFormat }>({
|
||||
type: 'select',
|
||||
name: 'format',
|
||||
message:
|
||||
@ -142,6 +146,22 @@ async function determineFormat(
|
||||
}).then(({ format }) =>
|
||||
format === asProvidedSelectedValue ? 'as-provided' : 'derived'
|
||||
);
|
||||
if (result === 'as-provided' && callingGenerator) {
|
||||
const { saveDefault } = await prompt<{ saveDefault: boolean }>({
|
||||
type: 'confirm',
|
||||
message: 'Would you like to save this layout as a default?',
|
||||
name: 'saveDefault',
|
||||
});
|
||||
if (saveDefault) {
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.generators ??= {};
|
||||
nxJson.generators[callingGenerator] ??= {};
|
||||
nxJson.generators[callingGenerator].projectNameAndRootFormat = result;
|
||||
updateNxJson(tree, nxJson);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getProjectNameAndRootFormats(
|
||||
|
||||
@ -550,6 +550,7 @@ async function normalizeOptions(
|
||||
importPath: options.importPath,
|
||||
projectNameAndRootFormat: options.projectNameAndRootFormat,
|
||||
rootProject: options.rootProject,
|
||||
callingGenerator: '@nx/js:library',
|
||||
});
|
||||
options.rootProject = projectRoot === '.';
|
||||
const fileName = getCaseAwareFileName({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user