使用 type-graphql 和 RESTDataSource 为第二个 api 调用添加字段解析器
Posted
技术标签:
【中文标题】使用 type-graphql 和 RESTDataSource 为第二个 api 调用添加字段解析器【英文标题】:Adding a field resolver for a second api call with type-graphql and the RESTDataSource 【发布时间】:2021-03-09 08:58:20 【问题描述】:我们希望下面的查询根据返回的truckId
解析truck
字段:
实体
// RosterEntity.ts
import Truck from '@sap-truck-roster/entity/Truck'
import Field, ID, ObjectType from 'type-graphql'
@ObjectType()
export class Roster
@Field(() => Truck, nullable: true )
truck: Truck
@Field(() => ID)
readonly truckId: string
// TruckEntity.ts
import Field, ID, ObjectType from 'type-graphql'
@ObjectType()
export class Truck
@Field(() => ID)
readonly id: string
@Field()
readonly description: string
解析器
// TruckResolver.ts
import Resolver, Arg, Query, Ctx, Field, ObjectType, createUnionType, from 'type-graphql'
import Truck from '@sap-truck-roster/entity/Truck'
import plainToClass from 'class-transformer'
import Context from '@shared/typings'
import ApiError from '@shared/graphql'
@ObjectType()
class TruckArray
@Field(() => [Truck], nullable: true )
data?: [Truck]
const TruckQueryResultUnion = createUnionType(
name: 'TruckQueryResult',
// types: () => [[Truck], ApiError] as const,
// an array is not supported by the Graphql spec in unions
types: () => [TruckArray, ApiError] as const,
)
@Resolver(() => Truck)
export class TruckResolver
@Query(() => TruckQueryResultUnion)
async truck(
@Ctx() ctx: Context,
@Arg('id', nullable: true ) id?: string,
@Arg('country', nullable: true ) country?: string
): Promise<typeof TruckQueryResultUnion>
const response = await ctx.dataSources.sapTruckRosterAPI.getTruck( id, country )
return plainToClass(TruckArray, data: response.data, )
// RosterResolver.ts
import Resolver, Arg, Query, Ctx, Field, ObjectType, createUnionType, from 'type-graphql'
import Roster from '@sap-truck-roster/entity/Roster'
import plainToClass from 'class-transformer'
import Context from '@shared/typings'
import ApiError from '@shared/graphql'
import Truck from '@sap-truck-roster/entity/Truck'
@ObjectType()
class RosterArray
@Field(() => [Roster], nullable: true )
data?: [Roster]
const RosterQueryResultUnion = createUnionType(
name: 'RosterQueryResult',
// types: () => [[Roster], ApiError] as const,
// an array is not supported by the Graphql spec in unions
types: () => [RosterArray, ApiError] as const,
)
@Resolver(() => Roster)
export class RosterResolver
@Query(() => RosterQueryResultUnion)
async roster(
@Ctx() ctx: Context,
@Arg('date', () => String) date: string,
@Arg('truckId', nullable: true ) truckId?: string,
@Arg('driverId', nullable: true ) driverId?: string
): Promise<typeof RosterQueryResultUnion>
const response = await ctx.dataSources.sapTruckRosterAPI.getRoster( date, driverId, truckId )
// @FieldResolver(() => Truck)
// truck(@Root() truck: Truck)
// return await ctx.dataSources.sapTruckRosterAPI.getTruck(
// id: response.truckId
// )
//
return plainToClass(RosterArray, data: response.data )
正如您在RosterResolver.ts
中看到的,我们尝试使用response.truckId
来查询API 上的另一个端点,但失败了。用数据填充 truck
字段的正确方法是什么?
这会在控制台中返回正确的数据,但与 roster
不匹配,因为我们获得了所有 truck
属性的 null
值:
// RosterResolver.ts
@FieldResolver(() => Truck, nullable: true )
async truck(@Root() roster: Roster, @Ctx() ctx: Context)
console.log('roster.truckId: ', roster.truckId)
const response = await ctx.dataSources.sapTruckRosterAPI.getTruck(
id: roster.truckId,
)
console.log('response: ', response);
return response
【问题讨论】:
【参考方案1】:您可以做的是解析器继承。 https://github.com/MichalLytek/type-graphql/blob/master/docs/resolvers.md#field-resolvers
@Resolver(() => Roster)
export class RosterResolver
....
@FieldResolver()
truck(@Root() roster: Roster)
return ctx.dataSources.sapTruckRosterAPI.getTruck(
id: roster.truckId
);
【讨论】:
谢谢你的建议,但我试过了,但它失败了,“不能为不可为空的字段 Truck.id 返回 null。”。即使这样做@FieldResolver(() => Truck, nullable: true )
当我尝试 @FieldResolver(() => Roster, nullable: true )
时,我收到错误“无法在类型 \"Roster\" 上查询字段 \"id\"以上是关于使用 type-graphql 和 RESTDataSource 为第二个 api 调用添加字段解析器的主要内容,如果未能解决你的问题,请参考以下文章
使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法
使用 type-graphql 和 RESTDataSource 为第二个 api 调用添加字段解析器
对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是不是正确?