Skip to content

Commit

Permalink
fix(angular): fix path handling and validate standalone option in pip…
Browse files Browse the repository at this point in the history
…e generator (#16080)
  • Loading branch information
leosvelperez authored Apr 4, 2023
1 parent 29f5326 commit 74633f5
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 62 deletions.
2 changes: 1 addition & 1 deletion docs/generated/packages/angular/generators/pipe.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down
2 changes: 2 additions & 0 deletions packages/angular/src/generators/pipe/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './normalize-options';
export * from './validate-options';
27 changes: 27 additions & 0 deletions packages/angular/src/generators/pipe/lib/normalize-options.ts
Original file line number Diff line number Diff line change
@@ -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 };
}
13 changes: 13 additions & 0 deletions packages/angular/src/generators/pipe/lib/validate-options.ts
Original file line number Diff line number Diff line change
@@ -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);
}
61 changes: 35 additions & 26 deletions packages/angular/src/generators/pipe/pipe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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();
});
});

Expand Down
53 changes: 19 additions & 34 deletions packages/angular/src/generators/pipe/pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,62 @@ 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`
);

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);
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/angular/src/generators/pipe/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export interface Schema {
export?: boolean;
skipFormat?: boolean;
}

export interface NormalizedSchema extends Schema {
path: string;
}
2 changes: 1 addition & 1 deletion packages/angular/src/generators/pipe/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down

1 comment on commit 74633f5

@vercel
Copy link

@vercel vercel bot commented on 74633f5 Apr 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx.dev
nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx-five.vercel.app

Please sign in to comment.