Skip to content

Commit 3fe7cdb

Browse files
feature(plugin) don't introspect type if user provide it's own
closes #1643
1 parent 5d59b38 commit 3fe7cdb

File tree

2 files changed

+99
-32
lines changed

2 files changed

+99
-32
lines changed

lib/plugin/visitors/model-class.visitor.ts

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ObjectType,
66
InterfaceType,
77
InputType,
8+
Field,
89
} from '../../decorators';
910
import { PluginOptions } from '../merge-options';
1011
import { METADATA_FACTORY_NAME } from '../plugin-constants';
@@ -374,6 +375,30 @@ export class ModelClassVisitor {
374375
});
375376
}
376377

378+
private getInlineStringEnumTypeOrUndefined(
379+
member: ts.PropertyDeclaration,
380+
): string {
381+
let inlineEnumName: string;
382+
383+
const membersStringEnumValues = this.isMemberHasInlineStringEnum(member);
384+
385+
if (membersStringEnumValues) {
386+
const memberName = member.name.getText();
387+
388+
inlineEnumName =
389+
member.parent.name.getText() +
390+
capitalizeFirstLetter(memberName) +
391+
'Enum';
392+
393+
this.inlineEnumsMap.push({
394+
name: inlineEnumName,
395+
values: membersStringEnumValues,
396+
});
397+
}
398+
399+
return inlineEnumName;
400+
}
401+
377402
private collectMetadataFromClassMembers(
378403
f: ts.NodeFactory,
379404
members: ts.NodeArray<ts.ClassElement>,
@@ -392,37 +417,18 @@ export class ModelClassVisitor {
392417
]) &&
393418
!hasDecorators(member.decorators, [HideField.name])
394419
) {
395-
let inlineEnumName: string;
396-
const memberName = member.name.getText();
397-
398-
const membersStringEnumValues =
399-
this.isMemberHasInlineStringEnum(member);
400-
401-
if (membersStringEnumValues) {
402-
inlineEnumName =
403-
member.parent.name.getText() +
404-
capitalizeFirstLetter(memberName) +
405-
'Enum';
406-
407-
this.inlineEnumsMap.push({
408-
name: inlineEnumName,
409-
values: membersStringEnumValues,
410-
});
411-
}
412-
413420
try {
414421
const objectLiteralExpr = this.createDecoratorObjectLiteralExpr(
415422
f,
416423
member,
417424
typeChecker,
418-
inlineEnumName,
419425
hostFilename,
420426
pluginOptions,
421427
);
422428

423429
properties.push(
424430
f.createPropertyAssignment(
425-
f.createIdentifier(memberName),
431+
f.createIdentifier(member.name.getText()),
426432
objectLiteralExpr,
427433
),
428434
);
@@ -468,28 +474,55 @@ export class ModelClassVisitor {
468474
);
469475
}
470476

477+
private hasExplicitTypeInDecorator(member: ts.PropertyDeclaration) {
478+
const fieldDecorator = member.decorators?.find(
479+
(decorator) => getDecoratorName(decorator) === Field.name,
480+
);
481+
482+
if (!fieldDecorator) {
483+
return false;
484+
}
485+
486+
const expression = fieldDecorator.expression as ts.CallExpression;
487+
return (
488+
expression.arguments.length > 0 &&
489+
ts.isArrowFunction(expression.arguments[0])
490+
);
491+
}
492+
471493
private createDecoratorObjectLiteralExpr(
472494
f: ts.NodeFactory,
473-
node: ts.PropertyDeclaration | ts.PropertySignature,
495+
node: ts.PropertyDeclaration,
474496
typeChecker: ts.TypeChecker,
475-
overrideType?: string,
476497
hostFilename = '',
477498
pluginOptions?: PluginOptions,
478499
): ts.ObjectLiteralExpression {
479500
const type = typeChecker.getTypeAtLocation(node);
480501
const isNullable =
481502
!!node.questionToken || isNull(type) || isUndefined(type);
482503

483-
const typeArrowFunction = f.createArrowFunction(
484-
undefined,
485-
undefined,
486-
[],
487-
undefined,
488-
undefined,
489-
overrideType
490-
? f.createIdentifier(overrideType)
491-
: this.getTypeUsingTypeChecker(f, node.type, typeChecker, hostFilename),
492-
);
504+
let typeArrowFunction: ts.ArrowFunction;
505+
const t = this.hasExplicitTypeInDecorator(node);
506+
if (!t) {
507+
const inlineStringEnumTypeName =
508+
this.getInlineStringEnumTypeOrUndefined(node);
509+
510+
typeArrowFunction = f.createArrowFunction(
511+
undefined,
512+
undefined,
513+
[],
514+
undefined,
515+
undefined,
516+
inlineStringEnumTypeName
517+
? f.createIdentifier(inlineStringEnumTypeName)
518+
: this.getTypeUsingTypeChecker(
519+
f,
520+
node.type,
521+
typeChecker,
522+
hostFilename,
523+
),
524+
);
525+
}
493526

494527
const description = pluginOptions.introspectComments
495528
? getJSDocDescription(node)

tests/plugin/model-class-visitor.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,38 @@ var Status2;
584584
`);
585585
});
586586
});
587+
588+
it('Should not introspect type for field if user explicitly wrote a type', () => {
589+
const source = `
590+
import { ID } from '@nestjs/graphql';
591+
592+
@ObjectType()
593+
class Model {
594+
/**
595+
* Description
596+
*/
597+
@Field(() => ID)
598+
field: string;
599+
600+
name: string;
601+
}
602+
`;
603+
604+
const actual = transpile(source, {});
605+
expect(actual).toMatchInlineSnapshot(`
606+
"import { ID } from '@nestjs/graphql';
607+
let Model = class Model {
608+
static _GRAPHQL_METADATA_FACTORY() {
609+
return { field: {}, name: { type: () => String } };
610+
}
611+
};
612+
__decorate([
613+
Field(() => ID)
614+
], Model.prototype, \\"field\\", void 0);
615+
Model = __decorate([
616+
ObjectType()
617+
], Model);
618+
"
619+
`);
620+
});
587621
});

0 commit comments

Comments
 (0)