Skip to content

Commit

Permalink
Merge branch 'artemsmirnov-fix-watched-dto-updates'
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Aug 20, 2020
2 parents 266dc31 + ba75282 commit 1f5be6b
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 30 deletions.
64 changes: 34 additions & 30 deletions lib/plugin/visitors/model-class.visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '../utils/plugin-utils';
import { AbstractFileVisitor } from './abstract.visitor';

const metadataHostMap = new Map();
type ClassMetadata = Record<string, ts.ObjectLiteralExpression>;

export class ModelClassVisitor extends AbstractFileVisitor {
visit(
Expand All @@ -27,11 +27,10 @@ export class ModelClassVisitor extends AbstractFileVisitor {
const typeChecker = program.getTypeChecker();
sourceFile = this.updateImports(sourceFile);

const visitNode = (node: ts.Node): ts.Node => {
if (ts.isClassDeclaration(node)) {
node = ts.visitEachChild(node, visitNode, ctx);
return this.addMetadataFactory(node as ts.ClassDeclaration);
} else if (ts.isPropertyDeclaration(node)) {
const propertyNodeVisitorFactory = (metadata: ClassMetadata) => (
node: ts.Node
): ts.Node => {
if (ts.isPropertyDeclaration(node)) {
const decorators = node.decorators;
const hidePropertyDecorator = getDecoratorOrUndefinedByNames(
[ApiHideProperty.name],
Expand All @@ -52,23 +51,32 @@ export class ModelClassVisitor extends AbstractFileVisitor {
typeChecker,
options,
sourceFile.fileName,
sourceFile
sourceFile,
metadata
);
} catch (err) {
return node;
}
return node;
}
return ts.visitEachChild(node, visitNode, ctx);
return node;
};
return ts.visitNode(sourceFile, visitNode);

const visitClassNode = (node: ts.Node): ts.Node => {
if (ts.isClassDeclaration(node)) {
const metadata: ClassMetadata = {};
node = ts.visitEachChild(
node,
propertyNodeVisitorFactory(metadata),
ctx
);
return this.addMetadataFactory(node as ts.ClassDeclaration, metadata);
}
return ts.visitEachChild(node, visitClassNode, ctx);
};
return ts.visitNode(sourceFile, visitClassNode);
}

addMetadataFactory(node: ts.ClassDeclaration) {
const classMetadata = this.getClassMetadata(node as ts.ClassDeclaration);
if (!classMetadata) {
return node;
}
addMetadataFactory(node: ts.ClassDeclaration, classMetadata: ClassMetadata) {
const classMutableNode = ts.getMutableClone(node);
const returnValue = ts.createObjectLiteral(
Object.keys(classMetadata).map((key) =>
Expand Down Expand Up @@ -101,7 +109,8 @@ export class ModelClassVisitor extends AbstractFileVisitor {
typeChecker: ts.TypeChecker,
options: PluginOptions,
hostFilename: string,
sourceFile: ts.SourceFile
sourceFile: ts.SourceFile,
metadata: ClassMetadata
) {
const objectLiteralExpr = this.createDecoratorObjectLiteralExpr(
compilerNode,
Expand All @@ -110,7 +119,12 @@ export class ModelClassVisitor extends AbstractFileVisitor {
options,
hostFilename
);
this.addClassMetadata(compilerNode, objectLiteralExpr, sourceFile);
this.addClassMetadata(
compilerNode,
objectLiteralExpr,
sourceFile,
metadata
);
}

createDecoratorObjectLiteralExpr(
Expand Down Expand Up @@ -386,31 +400,21 @@ export class ModelClassVisitor extends AbstractFileVisitor {
addClassMetadata(
node: ts.PropertyDeclaration,
objectLiteral: ts.ObjectLiteralExpression,
sourceFile: ts.SourceFile
sourceFile: ts.SourceFile,
metadata: ClassMetadata
) {
const hostClass = node.parent;
const className = hostClass.name && hostClass.name.getText();
if (!className) {
return;
}
const existingMetadata = metadataHostMap.get(className) || {};
const propertyName = node.name && node.name.getText(sourceFile);
if (
!propertyName ||
(node.name && node.name.kind === ts.SyntaxKind.ComputedPropertyName)
) {
return;
}
metadataHostMap.set(className, {
...existingMetadata,
[propertyName]: objectLiteral
});
}

getClassMetadata(node: ts.ClassDeclaration) {
if (!node.name) {
return;
}
return metadataHostMap.get(node.name.getText());
metadata[propertyName] = objectLiteral;
}
}
27 changes: 27 additions & 0 deletions test/plugin/fixtures/changed-class.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const originalCatDtoText = `
export class ChangedCatDto {
name: string;
status: string;
}
`;

export const changedCatDtoText = `
export class ChangedCatDto {
name: string;
}
`;

export const changedCatDtoTextTranspiled = `\"use strict\";
Object.defineProperty(exports, \"__esModule\", { value: true });
exports.ChangedCatDto = void 0;
var openapi = require(\"@nestjs/swagger\");
var ChangedCatDto = /** @class */ (function () {
function ChangedCatDto() {
}
ChangedCatDto._OPENAPI_METADATA_FACTORY = function () {
return { name: { required: true, type: function () { return String; } } };
};
return ChangedCatDto;
}());
exports.ChangedCatDto = ChangedCatDto;
`;
35 changes: 35 additions & 0 deletions test/plugin/model-class-visitor.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as ts from 'typescript';
import { before } from '../../lib/plugin/compiler-plugin';
import {
changedCatDtoText,
changedCatDtoTextTranspiled,
originalCatDtoText
} from './fixtures/changed-class.dto';
import {
createCatDtoAltText,
createCatDtoTextAltTranspiled
Expand Down Expand Up @@ -126,4 +131,34 @@ describe('API model properties', () => {
});
expect(result.outputText).toEqual(nullableDtoTextTranspiled);
});

it('should remove properties from metadata when properties removed from dto', () => {
const options: ts.CompilerOptions = {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES5,
newLine: ts.NewLineKind.LineFeed,
noEmitHelpers: true,
strict: true
};
const filename = 'changed-class.dto.ts';
const fakeProgram = ts.createProgram([filename], options);

ts.transpileModule(originalCatDtoText, {
compilerOptions: options,
fileName: filename,
transformers: {
before: [before({ classValidatorShim: true }, fakeProgram)]
}
});

const changedResult = ts.transpileModule(changedCatDtoText, {
compilerOptions: options,
fileName: filename,
transformers: {
before: [before({ classValidatorShim: true }, fakeProgram)]
}
});

expect(changedResult.outputText).toEqual(changedCatDtoTextTranspiled);
});
});

0 comments on commit 1f5be6b

Please sign in to comment.