Skip to content

Commit

Permalink
fix(code-first): Use base model field options with ResolveField()
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleff committed Aug 16, 2022
1 parent 03899f5 commit 7ddef62
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 26 deletions.
15 changes: 15 additions & 0 deletions packages/apollo/tests/code-first/recipes/ingredients.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ResolveField, Resolver, Parent } from '@nestjs/graphql';
import { Ingredient } from './models/ingredient';

@Resolver((of) => Ingredient)
export class IngredientsResolver {
@ResolveField()
name(@Parent() { name }: Ingredient): string {
return name;
}

@ResolveField()
baseName(@Parent() { name }: Ingredient): string {
return name;
}
}
15 changes: 14 additions & 1 deletion packages/apollo/tests/code-first/recipes/models/ingredient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { Field, ID, ObjectType } from '@nestjs/graphql';

@ObjectType({ isAbstract: true })
class IngredientBase {
@Field({
defaultValue: 'default',
deprecationReason: 'is deprecated',
description: 'ingredient base name',
nullable: true,
})
baseName: string;
}

@ObjectType()
export class Ingredient {
export class Ingredient extends IngredientBase {
@Field((type) => ID)
id: string;

Expand All @@ -13,6 +25,7 @@ export class Ingredient {
name: string;

constructor(ingredient: Partial<Ingredient>) {
super();
Object.assign(this, ingredient);
}
}
2 changes: 2 additions & 0 deletions packages/apollo/tests/code-first/recipes/recipes.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { UnauthorizedFilter } from '../common/filters/unauthorized.filter';
import { DateScalar } from '../common/scalars/date.scalar';
import { IngredientsResolver } from './ingredients.resolver';
import { IRecipesResolver } from './irecipes.resolver';
import { RecipesResolver } from './recipes.resolver';
import { RecipesService } from './recipes.service';

@Module({
providers: [
IngredientsResolver,
RecipesResolver,
IRecipesResolver,
RecipesService,
Expand Down
14 changes: 14 additions & 0 deletions packages/apollo/tests/e2e/code-first-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DirectionsResolver } from '../code-first/directions/directions.resolver
import { SampleOrphanedEnum } from '../code-first/enums/sample-orphaned.enum';
import { AbstractResolver } from '../code-first/other/abstract.resolver';
import { SampleOrphanedType } from '../code-first/other/sample-orphaned.type';
import { IngredientsResolver } from '../code-first/recipes/ingredients.resolver';
import { IRecipesResolver } from '../code-first/recipes/irecipes.resolver';
import { Recipe } from '../code-first/recipes/models/recipe';
import { RecipesResolver } from '../code-first/recipes/recipes.resolver';
Expand Down Expand Up @@ -48,6 +49,7 @@ describe('Code-first - schema factory', () => {
beforeAll(async () => {
schema = await schemaFactory.create(
[
IngredientsResolver,
RecipesResolver,
DirectionsResolver,
AbstractResolver,
Expand Down Expand Up @@ -212,6 +214,18 @@ describe('Code-first - schema factory', () => {
ofType: null,
},
},
{
args: [],
deprecationReason: 'is deprecated',
description: 'ingredient base name',
isDeprecated: true,
name: 'baseName',
type: {
kind: TypeKind.SCALAR,
name: 'String',
ofType: null,
},
},
]),
}),
);
Expand Down
16 changes: 10 additions & 6 deletions packages/apollo/tests/utils/printed-schema.snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,21 @@ type SampleOrphanedType {
averageRating: Float!
}
type Category {
name: String!
description: String!
tags: [String!]!
}
type Ingredient {
"""ingredient base name"""
baseName: String @deprecated(reason: "is deprecated")
id: ID!
"""ingredient name"""
name: String @deprecated(reason: "is deprecated")
}
type Category {
name: String!
description: String!
tags: [String!]!
}
"""orphaned enum"""
enum SampleOrphanedEnum {
Red
Expand Down Expand Up @@ -141,6 +143,8 @@ interface IRecipe {
}
type Ingredient {
"""ingredient base name"""
baseName: String @deprecated(reason: "is deprecated")
id: ID!
"""ingredient name"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,24 +338,8 @@ export class TypeMetadataStorageHost {
}

private compileExternalFieldResolverMetadata(item: FieldResolverMetadata) {
const objectTypeRef = this.metadataByTargetCollection
.get(item.target)
.resolver.typeFn();

const objectOrInterfaceTypeMetadata =
this.metadataByTargetCollection.get(objectTypeRef).objectType ||
this.metadataByTargetCollection.get(objectTypeRef).interface;

if (!objectOrInterfaceTypeMetadata) {
throw new CannotDetermineHostTypeError(
item.schemaName,
objectTypeRef?.name,
);
}
const objectOrInterfaceTypeField =
objectOrInterfaceTypeMetadata.properties.find(
(fieldDef) => fieldDef.name === item.methodName,
);
const [target, objectOrInterfaceTypeMetadata, objectOrInterfaceTypeField] =
this.findModelFieldMetadata(item);
if (!objectOrInterfaceTypeField) {
if (!item.typeFn || !item.typeOptions) {
throw new UndefinedTypeError(item.target.name, item.methodName);
Expand All @@ -366,7 +350,7 @@ export class TypeMetadataStorageHost {
deprecationReason: item.deprecationReason,
description: item.description,
typeFn: item.typeFn,
target: objectTypeRef,
target,
options: item.typeOptions,
methodArgs: item.methodArgs,
directives: item.directives,
Expand Down Expand Up @@ -394,6 +378,41 @@ export class TypeMetadataStorageHost {
}
}

private findModelFieldMetadata(
item: FieldResolverMetadata,
): [Function, ClassMetadata, PropertyMetadata | undefined] {
const objectTypeRef = this.metadataByTargetCollection
.get(item.target)
.resolver.typeFn();
const getTypeMetadata = (objectTypeRef: any) =>
this.metadataByTargetCollection.get(objectTypeRef).objectType ||
this.metadataByTargetCollection.get(objectTypeRef).interface;
for (
let _objectTypeRef = objectTypeRef;
_objectTypeRef?.prototype;
_objectTypeRef = Object.getPrototypeOf(_objectTypeRef)
) {
const possibleTypeMetadata = getTypeMetadata(_objectTypeRef);
if (!possibleTypeMetadata) {
throw new CannotDetermineHostTypeError(
item.schemaName,
_objectTypeRef?.name,
);
}
const objectOrInterfaceTypeField = possibleTypeMetadata.properties.find(
(fieldDef) => fieldDef.name === item.methodName,
);
if (objectOrInterfaceTypeField) {
return [
_objectTypeRef,
possibleTypeMetadata,
objectOrInterfaceTypeField,
];
}
}
return [objectTypeRef, getTypeMetadata(objectTypeRef), undefined];
}

private compileExtendedResolversMetadata() {
this.metadataByTargetCollection.all.resolver.forEach((item) => {
let parentClass = Object.getPrototypeOf(item.target);
Expand Down

0 comments on commit 7ddef62

Please sign in to comment.