We want the query below to resolve the truck
fields based on the truckId
returned:
Entities
// 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
}
Resolvers
// 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 })
}
}
As you can see in the RosterResolver.ts
we tried to use the response.truckId
to query the other endpoint on the API but this fails. What is the correct way to populate the truck
field with data?
This returns in the console the correct data but does not match it with the roster
as we get null
values for all truck
properties:
// 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
}
Something you can do is Resolver inheritance. https://github.com/MichalLytek/type-graphql/blob/master/docs/resolvers.md#field-resolvers