#graphql #apollo-server #typegraphql
#graphql #apollo-сервер #typegraphql
Вопрос:
Мы хотим, чтобы приведенный ниже запрос разрешал truck
поля на основе truckId
возвращенных:
Сущности
// 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
as, поскольку мы получаем null
значения для всех truck
свойств:
// 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
});
}
Комментарии:
1. Спасибо за совет, но я попробовал это, и он завершается с ошибкой «Не удается вернуть значение null для ненулевого поля Truck.id .». Даже когда делаешь это
@FieldResolver(() => Truck, { nullable: true })
2. Когда я пытаюсь
@FieldResolver(() => Roster, { nullable: true })
, я получаю сообщение об ошибке «Невозможно запросить поле «id» для типа «Реестр»