diff --git a/docs/generated/packages/nest/generators/application.json b/docs/generated/packages/nest/generators/application.json index b14777ae8e8e0..9bb9beb8f354a 100644 --- a/docs/generated/packages/nest/generators/application.json +++ b/docs/generated/packages/nest/generators/application.json @@ -1,6 +1,6 @@ { "name": "application", - "factory": "./src/generators/application/application", + "factory": "./src/generators/application/application#applicationGeneratorInternal", "schema": { "$schema": "http://json-schema.org/schema", "$id": "NxNestApplicationGenerator", @@ -13,12 +13,18 @@ "description": "The name of the application.", "type": "string", "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the node application?" + "x-prompt": "What name would you like to use for the node application?", + "pattern": "^[a-zA-Z][^:]*$" }, "directory": { "description": "The directory of the new application.", "type": "string" }, + "projectNameAndRootFormat": { + "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", + "type": "string", + "enum": ["as-provided", "derived"] + }, "skipFormat": { "description": "Skip formatting files.", "type": "boolean", @@ -82,7 +88,7 @@ "aliases": ["app"], "x-type": "application", "description": "Create a NestJS application.", - "implementation": "/packages/nest/src/generators/application/application.ts", + "implementation": "/packages/nest/src/generators/application/application#applicationGeneratorInternal.ts", "hidden": false, "path": "/packages/nest/src/generators/application/schema.json", "type": "generator" diff --git a/docs/generated/packages/nest/generators/library.json b/docs/generated/packages/nest/generators/library.json index d2132961017dc..5d9efb2f94bd5 100644 --- a/docs/generated/packages/nest/generators/library.json +++ b/docs/generated/packages/nest/generators/library.json @@ -1,6 +1,6 @@ { "name": "library", - "factory": "./src/generators/library/library", + "factory": "./src/generators/library/library#libraryGeneratorInternal", "schema": { "$schema": "http://json-schema.org/schema", "$id": "NxNestLibraryGenerator", @@ -19,13 +19,19 @@ "description": "Library name.", "type": "string", "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the library?" + "x-prompt": "What name would you like to use for the library?", + "pattern": "(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$" }, "directory": { "description": "A directory where the library is placed.", "type": "string", "alias": "dir" }, + "projectNameAndRootFormat": { + "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", + "type": "string", + "enum": ["as-provided", "derived"] + }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", @@ -143,7 +149,7 @@ "aliases": ["lib"], "x-type": "library", "description": "Create a new NestJS library.", - "implementation": "/packages/nest/src/generators/library/library.ts", + "implementation": "/packages/nest/src/generators/library/library#libraryGeneratorInternal.ts", "hidden": false, "path": "/packages/nest/src/generators/library/schema.json", "type": "generator" diff --git a/packages/nest/generators.json b/packages/nest/generators.json index 4993de48ceef6..7b3a61cc5a45a 100644 --- a/packages/nest/generators.json +++ b/packages/nest/generators.json @@ -108,7 +108,7 @@ }, "generators": { "application": { - "factory": "./src/generators/application/application", + "factory": "./src/generators/application/application#applicationGeneratorInternal", "schema": "./src/generators/application/schema.json", "aliases": ["app"], "x-type": "application", @@ -128,7 +128,7 @@ "hidden": true }, "library": { - "factory": "./src/generators/library/library", + "factory": "./src/generators/library/library#libraryGeneratorInternal", "schema": "./src/generators/library/schema.json", "aliases": ["lib"], "x-type": "library", diff --git a/packages/nest/src/generators/application/application.ts b/packages/nest/src/generators/application/application.ts index 18e8ea3bbf646..caf90e1b6577f 100644 --- a/packages/nest/src/generators/application/application.ts +++ b/packages/nest/src/generators/application/application.ts @@ -15,7 +15,17 @@ export async function applicationGenerator( tree: Tree, rawOptions: ApplicationGeneratorOptions ): Promise { - const options = normalizeOptions(tree, rawOptions); + return await applicationGeneratorInternal(tree, { + projectNameAndRootFormat: 'derived', + ...rawOptions, + }); +} + +export async function applicationGeneratorInternal( + tree: Tree, + rawOptions: ApplicationGeneratorOptions +): Promise { + const options = await normalizeOptions(tree, rawOptions); const initTask = await initGenerator(tree, { skipPackageJson: options.skipPackageJson, unitTestRunner: options.unitTestRunner, diff --git a/packages/nest/src/generators/application/lib/create-files.ts b/packages/nest/src/generators/application/lib/create-files.ts index 4ee1d6e9deefa..cec49874e5b3c 100644 --- a/packages/nest/src/generators/application/lib/create-files.ts +++ b/packages/nest/src/generators/application/lib/create-files.ts @@ -9,7 +9,7 @@ export function createFiles(tree: Tree, options: NormalizedOptions): void { joinPathFragments(options.appProjectRoot, 'src'), { tmpl: '', - name: options.name, + name: options.appProjectName, root: options.appProjectRoot, } ); diff --git a/packages/nest/src/generators/application/lib/normalize-options.ts b/packages/nest/src/generators/application/lib/normalize-options.ts index 4e358a0c2f9f5..3c2d402439da1 100644 --- a/packages/nest/src/generators/application/lib/normalize-options.ts +++ b/packages/nest/src/generators/application/lib/normalize-options.ts @@ -1,31 +1,32 @@ -import { extractLayoutDirectory, Tree } from '@nx/devkit'; -import { getWorkspaceLayout, joinPathFragments, names } from '@nx/devkit'; +import { Tree } from '@nx/devkit'; +import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { Linter } from '@nx/linter'; import type { Schema as NodeApplicationGeneratorOptions } from '@nx/node/src/generators/application/schema'; import type { ApplicationGeneratorOptions, NormalizedOptions } from '../schema'; -export function normalizeOptions( +export async function normalizeOptions( tree: Tree, options: ApplicationGeneratorOptions -): NormalizedOptions { - const { layoutDirectory, projectDirectory } = extractLayoutDirectory( - options.directory - ); - - const appDirectory = projectDirectory - ? `${names(projectDirectory).fileName}/${names(options.name).fileName}` - : names(options.name).fileName; - - const appProjectRoot = options.rootProject - ? '.' - : joinPathFragments( - layoutDirectory ?? getWorkspaceLayout(tree).appsDir, - appDirectory - ); +): Promise { + const { + projectName: appProjectName, + projectRoot: appProjectRoot, + projectNameAndRootFormat, + } = await determineProjectNameAndRootOptions(tree, { + name: options.name, + projectType: 'application', + directory: options.directory, + projectNameAndRootFormat: options.projectNameAndRootFormat, + rootProject: options.rootProject, + callingGenerator: '@nx/nest:application', + }); + options.rootProject = appProjectRoot === '.'; + options.projectNameAndRootFormat = projectNameAndRootFormat; return { ...options, strict: options.strict ?? false, + appProjectName, appProjectRoot, linter: options.linter ?? Linter.EsLint, unitTestRunner: options.unitTestRunner ?? 'jest', diff --git a/packages/nest/src/generators/application/schema.d.ts b/packages/nest/src/generators/application/schema.d.ts index 42a2b6ad3bd2e..a0a18e5b19704 100644 --- a/packages/nest/src/generators/application/schema.d.ts +++ b/packages/nest/src/generators/application/schema.d.ts @@ -1,8 +1,10 @@ -import { Linter } from '@nx/linter'; +import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils'; +import type { Linter } from '@nx/linter'; export interface ApplicationGeneratorOptions { name: string; directory?: string; + projectNameAndRootFormat?: ProjectNameAndRootFormat; frontendProject?: string; linter?: Linter; skipFormat?: boolean; @@ -17,5 +19,6 @@ export interface ApplicationGeneratorOptions { } interface NormalizedOptions extends ApplicationGeneratorOptions { + appProjectName: string; appProjectRoot: Path; } diff --git a/packages/nest/src/generators/application/schema.json b/packages/nest/src/generators/application/schema.json index 55c69037e4a10..24e04c88f9d41 100644 --- a/packages/nest/src/generators/application/schema.json +++ b/packages/nest/src/generators/application/schema.json @@ -13,12 +13,18 @@ "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the node application?" + "x-prompt": "What name would you like to use for the node application?", + "pattern": "^[a-zA-Z][^:]*$" }, "directory": { "description": "The directory of the new application.", "type": "string" }, + "projectNameAndRootFormat": { + "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", + "type": "string", + "enum": ["as-provided", "derived"] + }, "skipFormat": { "description": "Skip formatting files.", "type": "boolean", diff --git a/packages/nest/src/generators/library/lib/add-project.ts b/packages/nest/src/generators/library/lib/add-project.ts index dac4adc3b6d6d..d33950f958813 100644 --- a/packages/nest/src/generators/library/lib/add-project.ts +++ b/packages/nest/src/generators/library/lib/add-project.ts @@ -15,10 +15,7 @@ export function addProject(tree: Tree, options: NormalizedOptions): void { executor: '@nx/js:tsc', outputs: ['{options.outputPath}'], options: { - outputPath: - options.libsDir && options.libsDir !== '.' - ? `dist/${options.libsDir}/${options.projectDirectory}` - : `dist/${options.projectDirectory}`, + outputPath: `dist/${options.projectRoot}`, tsConfig: `${options.projectRoot}/tsconfig.lib.json`, packageJson: `${options.projectRoot}/package.json`, main: `${options.projectRoot}/src/index.ts`, diff --git a/packages/nest/src/generators/library/lib/normalize-options.ts b/packages/nest/src/generators/library/lib/normalize-options.ts index f3319494ff9ff..032a54c2a5d36 100644 --- a/packages/nest/src/generators/library/lib/normalize-options.ts +++ b/packages/nest/src/generators/library/lib/normalize-options.ts @@ -1,33 +1,31 @@ +import { Tree } from '@nx/devkit'; +import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; +import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope'; import type { LibraryGeneratorSchema as JsLibraryGeneratorSchema } from '@nx/js/src/utils/schema'; import { Linter } from '@nx/linter'; -import { - extractLayoutDirectory, - getWorkspaceLayout, - joinPathFragments, - names, - Tree, -} from '@nx/devkit'; import type { LibraryGeneratorOptions, NormalizedOptions } from '../schema'; -import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope'; -export function normalizeOptions( +export async function normalizeOptions( tree: Tree, options: LibraryGeneratorOptions -): NormalizedOptions { - const { layoutDirectory, projectDirectory } = extractLayoutDirectory( - options.directory - ); - const { libsDir: defaultLibsDir } = getWorkspaceLayout(tree); - const libsDir = layoutDirectory ?? defaultLibsDir; - const name = names(options.name).fileName; - const fullProjectDirectory = projectDirectory - ? `${names(projectDirectory).fileName}/${name}` - : name; - - const projectName = fullProjectDirectory.replace(new RegExp('/', 'g'), '-'); - const fileName = options.simpleName ? name : projectName; - const projectRoot = joinPathFragments(libsDir, fullProjectDirectory); +): Promise { + const { + projectName, + names: projectNames, + projectRoot, + importPath, + } = await determineProjectNameAndRootOptions(tree, { + name: options.name, + projectType: 'library', + directory: options.directory, + importPath: options.importPath, + projectNameAndRootFormat: options.projectNameAndRootFormat, + callingGenerator: '@nx/nest:library', + }); + const fileName = options.simpleName + ? projectNames.projectSimpleName + : projectNames.projectFileName; const parsedTags = options.tags ? options.tags.split(',').map((s) => s.trim()) : []; @@ -41,14 +39,13 @@ export function normalizeOptions( linter: options.linter ?? Linter.EsLint, parsedTags, prefix: getNpmScope(tree), // we could also allow customizing this - projectDirectory: fullProjectDirectory, projectName, projectRoot, + importPath, service: options.service ?? false, target: options.target ?? 'es6', testEnvironment: options.testEnvironment ?? 'node', unitTestRunner: options.unitTestRunner ?? 'jest', - libsDir, }; return normalized; diff --git a/packages/nest/src/generators/library/library.ts b/packages/nest/src/generators/library/library.ts index 0ad139b35baec..09e93fa4553bb 100644 --- a/packages/nest/src/generators/library/library.ts +++ b/packages/nest/src/generators/library/library.ts @@ -17,7 +17,17 @@ export async function libraryGenerator( tree: Tree, rawOptions: LibraryGeneratorOptions ): Promise { - const options = normalizeOptions(tree, rawOptions); + return await libraryGeneratorInternal(tree, { + projectNameAndRootFormat: 'derived', + ...rawOptions, + }); +} + +export async function libraryGeneratorInternal( + tree: Tree, + rawOptions: LibraryGeneratorOptions +): Promise { + const options = await normalizeOptions(tree, rawOptions); await jsLibraryGenerator(tree, toJsLibraryGeneratorOptions(options)); const installDepsTask = addDependencies(tree); deleteFiles(tree, options); diff --git a/packages/nest/src/generators/library/schema.d.ts b/packages/nest/src/generators/library/schema.d.ts index 85e076df98b26..0588a2bc93817 100644 --- a/packages/nest/src/generators/library/schema.d.ts +++ b/packages/nest/src/generators/library/schema.d.ts @@ -1,11 +1,13 @@ -import { Linter } from '@nx/linter'; -import { UnitTestRunner } from '../utils'; +import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils'; +import type { Linter } from '@nx/linter'; +import type { UnitTestRunner } from '../utils'; export interface LibraryGeneratorOptions { name: string; buildable?: boolean; controller?: boolean; directory?: string; + projectNameAndRootFormat?: ProjectNameAndRootFormat; global?: boolean; importPath?: string; linter?: Linter; @@ -38,8 +40,6 @@ export interface NormalizedOptions extends LibraryGeneratorOptions { fileName: string; parsedTags: string[]; prefix: string; - projectDirectory: string; projectName: string; projectRoot: Path; - libsDir: string; } diff --git a/packages/nest/src/generators/library/schema.json b/packages/nest/src/generators/library/schema.json index 70b465046cf6e..05b4bad001af9 100644 --- a/packages/nest/src/generators/library/schema.json +++ b/packages/nest/src/generators/library/schema.json @@ -19,13 +19,19 @@ "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the library?" + "x-prompt": "What name would you like to use for the library?", + "pattern": "(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$" }, "directory": { "description": "A directory where the library is placed.", "type": "string", "alias": "dir" }, + "projectNameAndRootFormat": { + "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", + "type": "string", + "enum": ["as-provided", "derived"] + }, "linter": { "description": "The tool to use for running lint checks.", "type": "string",