diff --git a/docs/generated/packages/angular/generators/pipe.json b/docs/generated/packages/angular/generators/pipe.json index 30d4f91d1136d..1c543a9de5775 100644 --- a/docs/generated/packages/angular/generators/pipe.json +++ b/docs/generated/packages/angular/generators/pipe.json @@ -45,7 +45,7 @@ "description": "Do not import this pipe into the owning NgModule." }, "standalone": { - "description": "Whether the generated pipe is standalone.", + "description": "Whether the generated pipe is standalone. _Note: This is only supported in Angular versions >= 14.1.0_.", "type": "boolean", "default": false }, diff --git a/packages/angular/src/generators/pipe/lib/index.ts b/packages/angular/src/generators/pipe/lib/index.ts new file mode 100644 index 0000000000000..da94c6f89ca24 --- /dev/null +++ b/packages/angular/src/generators/pipe/lib/index.ts @@ -0,0 +1,2 @@ +export * from './normalize-options'; +export * from './validate-options'; diff --git a/packages/angular/src/generators/pipe/lib/normalize-options.ts b/packages/angular/src/generators/pipe/lib/normalize-options.ts new file mode 100644 index 0000000000000..4b82efa55c4f6 --- /dev/null +++ b/packages/angular/src/generators/pipe/lib/normalize-options.ts @@ -0,0 +1,27 @@ +import type { Tree } from '@nrwl/devkit'; +import { joinPathFragments, readProjectConfiguration } from '@nrwl/devkit'; +import { parseNameWithPath } from '../../utils/names'; +import type { NormalizedSchema, Schema } from '../schema'; + +export function normalizeOptions( + tree: Tree, + options: Schema +): NormalizedSchema { + const { projectType, root, sourceRoot } = readProjectConfiguration( + tree, + options.project + ); + + const projectSourceRoot = sourceRoot ?? joinPathFragments(root, 'src'); + const { name, path: namePath } = parseNameWithPath(options.name); + + const path = + options.path ?? + joinPathFragments( + projectSourceRoot, + projectType === 'application' ? 'app' : 'lib', + namePath + ); + + return { ...options, name, path }; +} diff --git a/packages/angular/src/generators/pipe/lib/validate-options.ts b/packages/angular/src/generators/pipe/lib/validate-options.ts new file mode 100644 index 0000000000000..55cfe46bfa69c --- /dev/null +++ b/packages/angular/src/generators/pipe/lib/validate-options.ts @@ -0,0 +1,13 @@ +import type { Tree } from '@nrwl/devkit'; +import { checkPathUnderProjectRoot } from '../../utils/path'; +import { + validateProject, + validateStandaloneOption, +} from '../../utils/validations'; +import type { Schema } from '../schema'; + +export function validateOptions(tree: Tree, options: Schema): void { + validateProject(tree, options.project); + checkPathUnderProjectRoot(tree, options.project, options.path); + validateStandaloneOption(tree, options.standalone); +} diff --git a/packages/angular/src/generators/pipe/pipe.spec.ts b/packages/angular/src/generators/pipe/pipe.spec.ts index 557d1ddb3a5c2..c4be8a7a5d98e 100644 --- a/packages/angular/src/generators/pipe/pipe.spec.ts +++ b/packages/angular/src/generators/pipe/pipe.spec.ts @@ -12,10 +12,11 @@ describe('pipe generator', () => { addProjectConfiguration(tree, 'test', { root: 'test', sourceRoot: 'test/src', + projectType: 'application', }); tree.write( - 'test/src/test.module.ts', + 'test/src/app/test.module.ts', `import {NgModule} from "@angular/core"; @NgModule({ imports: [], @@ -33,9 +34,11 @@ describe('pipe generator', () => { await generatePipeWithDefaultOptions(tree); // ASSERT - expect(tree.read('test/src/test.pipe.ts', 'utf-8')).toMatchSnapshot(); - expect(tree.read('test/src/test.pipe.spec.ts', 'utf-8')).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot(); + expect( + tree.read('test/src/app/test.pipe.spec.ts', 'utf-8') + ).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should import the pipe correctly when flat=false', async () => { @@ -45,11 +48,13 @@ describe('pipe generator', () => { await generatePipeWithDefaultOptions(tree, { flat: false }); // ASSERT - expect(tree.read('test/src/test/test.pipe.ts', 'utf-8')).toMatchSnapshot(); expect( - tree.read('test/src/test/test.pipe.spec.ts', 'utf-8') + tree.read('test/src/app/test/test.pipe.ts', 'utf-8') + ).toMatchSnapshot(); + expect( + tree.read('test/src/app/test/test.pipe.spec.ts', 'utf-8') ).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should not import the pipe when standalone=true', async () => { @@ -59,9 +64,11 @@ describe('pipe generator', () => { await generatePipeWithDefaultOptions(tree, { standalone: true }); // ASSERT - expect(tree.read('test/src/test.pipe.ts', 'utf-8')).toMatchSnapshot(); - expect(tree.read('test/src/test.pipe.spec.ts', 'utf-8')).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot(); + expect( + tree.read('test/src/app/test.pipe.spec.ts', 'utf-8') + ).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should import the pipe correctly when flat=false and path is nested deeper', async () => { @@ -70,17 +77,17 @@ describe('pipe generator', () => { // ACT await generatePipeWithDefaultOptions(tree, { flat: false, - path: 'test/src/my-pipes', + path: 'test/src/app/my-pipes', }); // ASSERT expect( - tree.read('test/src/my-pipes/test/test.pipe.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.ts', 'utf-8') ).toMatchSnapshot(); expect( - tree.read('test/src/my-pipes/test/test.pipe.spec.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.spec.ts', 'utf-8') ).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should export the pipe correctly when flat=false and path is nested deeper', async () => { @@ -89,18 +96,18 @@ describe('pipe generator', () => { // ACT await generatePipeWithDefaultOptions(tree, { flat: false, - path: 'test/src/my-pipes', + path: 'test/src/app/my-pipes', export: true, }); // ASSERT expect( - tree.read('test/src/my-pipes/test/test.pipe.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.ts', 'utf-8') ).toMatchSnapshot(); expect( - tree.read('test/src/my-pipes/test/test.pipe.spec.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.spec.ts', 'utf-8') ).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should not import the pipe when skipImport=true', async () => { @@ -109,18 +116,18 @@ describe('pipe generator', () => { // ACT await generatePipeWithDefaultOptions(tree, { flat: false, - path: 'test/src/my-pipes', + path: 'test/src/app/my-pipes', skipImport: true, }); // ASSERT expect( - tree.read('test/src/my-pipes/test/test.pipe.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.ts', 'utf-8') ).toMatchSnapshot(); expect( - tree.read('test/src/my-pipes/test/test.pipe.spec.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.spec.ts', 'utf-8') ).toMatchSnapshot(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); it('should not generate test file when skipTests=true', async () => { @@ -129,16 +136,18 @@ describe('pipe generator', () => { // ACT await generatePipeWithDefaultOptions(tree, { flat: false, - path: 'test/src/my-pipes', + path: 'test/src/app/my-pipes', skipTests: true, }); // ASSERT expect( - tree.read('test/src/my-pipes/test/test.pipe.ts', 'utf-8') + tree.read('test/src/app/my-pipes/test/test.pipe.ts', 'utf-8') ).toMatchSnapshot(); - expect(tree.exists('test/src/my-pipes/test/test.pipe.spec.ts')).toBeFalsy(); - expect(tree.read('test/src/test.module.ts', 'utf-8')).toMatchSnapshot(); + expect( + tree.exists('test/src/app/my-pipes/test/test.pipe.spec.ts') + ).toBeFalsy(); + expect(tree.read('test/src/app/test.module.ts', 'utf-8')).toMatchSnapshot(); }); }); diff --git a/packages/angular/src/generators/pipe/pipe.ts b/packages/angular/src/generators/pipe/pipe.ts index e20c293e7fca6..7037b0bcd877b 100644 --- a/packages/angular/src/generators/pipe/pipe.ts +++ b/packages/angular/src/generators/pipe/pipe.ts @@ -2,54 +2,39 @@ import type { Tree } from '@nrwl/devkit'; import { formatFiles, generateFiles, - getProjects, joinPathFragments, names, - readProjectConfiguration, } from '@nrwl/devkit'; -import type { AngularProjectConfiguration } from '../../utils/types'; import { addToNgModule, findModule } from '../utils'; -import { checkPathUnderProjectRoot } from '../utils/path'; +import { normalizeOptions, validateOptions } from './lib'; import type { Schema } from './schema'; -let tsModule: typeof import('typescript'); +export async function pipeGenerator(tree: Tree, rawOptions: Schema) { + validateOptions(tree, rawOptions); + const options = normalizeOptions(tree, rawOptions); -export async function pipeGenerator(tree: Tree, schema: Schema) { - const projects = getProjects(tree); - if (!projects.has(schema.project)) { - throw new Error(`Project "${schema.project}" does not exist!`); - } - - checkPathUnderProjectRoot(tree, schema.project, schema.path); - - const project = readProjectConfiguration( - tree, - schema.project - ) as AngularProjectConfiguration; - - const path = schema.path ?? `${project.sourceRoot}`; - const pipeNames = names(schema.name); - - const pathToGenerateFiles = schema.flat + const pathToGenerateFiles = options.flat ? './files/__pipeFileName__' : './files'; - await generateFiles( + const pipeNames = names(options.name); + + generateFiles( tree, joinPathFragments(__dirname, pathToGenerateFiles), - path, + options.path, { pipeClassName: pipeNames.className, pipeFileName: pipeNames.fileName, pipePropertyName: pipeNames.propertyName, - standalone: schema.standalone, + standalone: options.standalone, tpl: '', } ); - if (schema.skipTests) { + if (options.skipTests) { const pathToSpecFile = joinPathFragments( - path, - `${!schema.flat ? `${pipeNames.fileName}/` : ``}${ + options.path, + `${!options.flat ? `${pipeNames.fileName}/` : ``}${ pipeNames.fileName }.pipe.spec.ts` ); @@ -57,22 +42,22 @@ export async function pipeGenerator(tree: Tree, schema: Schema) { tree.delete(pathToSpecFile); } - if (!schema.skipImport && !schema.standalone) { - const modulePath = findModule(tree, path, schema.module); + if (!options.skipImport && !options.standalone) { + const modulePath = findModule(tree, options.path, options.module); addToNgModule( tree, - path, + options.path, modulePath, pipeNames.fileName, `${pipeNames.className}Pipe`, `${pipeNames.fileName}.pipe`, 'declarations', - schema.flat, - schema.export + options.flat, + options.export ); } - if (!schema.skipFormat) { + if (!options.skipFormat) { await formatFiles(tree); } } diff --git a/packages/angular/src/generators/pipe/schema.d.ts b/packages/angular/src/generators/pipe/schema.d.ts index 1c2dfa4354e18..8eeb84e5bd66c 100644 --- a/packages/angular/src/generators/pipe/schema.d.ts +++ b/packages/angular/src/generators/pipe/schema.d.ts @@ -10,3 +10,7 @@ export interface Schema { export?: boolean; skipFormat?: boolean; } + +export interface NormalizedSchema extends Schema { + path: string; +} diff --git a/packages/angular/src/generators/pipe/schema.json b/packages/angular/src/generators/pipe/schema.json index c3fa0b1ca9f5f..32775a8aecc14 100644 --- a/packages/angular/src/generators/pipe/schema.json +++ b/packages/angular/src/generators/pipe/schema.json @@ -49,7 +49,7 @@ "description": "Do not import this pipe into the owning NgModule." }, "standalone": { - "description": "Whether the generated pipe is standalone.", + "description": "Whether the generated pipe is standalone. _Note: This is only supported in Angular versions >= 14.1.0_.", "type": "boolean", "default": false },