UNPKG

3.06 kBPlain TextView Raw
1import type { ExecutionResult } from 'graphql'
2import { standardScalarTypeNames } from '../../lib/graphql.js'
3import { assertArray, mapValues } from '../../lib/prelude.js'
4import type { Object$2, Schema } from '../1_Schema/__.js'
5import { Output } from '../1_Schema/__.js'
6import { readMaybeThunk } from '../1_Schema/core/helpers.js'
7import type { GraphQLObject } from '../4_ResultSet/runtime.js'
8import { assertGraphQLObject } from '../4_ResultSet/runtime.js'
9
10export const decode = <$Data extends ExecutionResult['data']>(index: Schema.Object$2, data: $Data): $Data => {
11 if (!data) return data
12 return mapValues(data, (v, fieldName) => {
13 const indexField = index.fields[fieldName]
14 if (!indexField) throw new Error(`Field not found: ${String(fieldName)}`)
15
16 const type = readMaybeThunk(indexField.type)
17 const typeWithoutNonNull = Output.unwrapNullable(type) as Output.Named | Output.List<any>
18 const v2 = decodeCustomScalarValue(typeWithoutNonNull, v as any)
19 return v2
20 }) as $Data
21}
22
23const decodeCustomScalarValue = (
24 indexType: Output.Any,
25 fieldValue: string | boolean | null | number | GraphQLObject | GraphQLObject[],
26) => {
27 if (fieldValue === null) return null
28
29 const indexTypeDethunked = readMaybeThunk(indexType)
30 const typeWithoutNonNull = Output.unwrapNullable(indexTypeDethunked) as Exclude<Output.Any, Output.Nullable<any>>
31
32 if (typeWithoutNonNull.kind === `list`) {
33 assertArray(fieldValue)
34 return fieldValue.map((v2: any): any => {
35 return decodeCustomScalarValue(typeWithoutNonNull.type, v2)
36 })
37 }
38
39 if (typeWithoutNonNull.kind === `Scalar`) {
40 if ((typeWithoutNonNull.name in standardScalarTypeNames)) {
41 // todo test this case
42 return fieldValue
43 }
44 if (typeof fieldValue === `object`) throw new Error(`Expected scalar. Got: ${String(fieldValue)}`)
45 // @ts-expect-error fixme
46 return typeWithoutNonNull.codec.decode(fieldValue)
47 }
48
49 if (typeWithoutNonNull.kind === `typename`) {
50 return fieldValue
51 }
52
53 assertGraphQLObject(fieldValue)
54
55 if (typeWithoutNonNull.kind === `Object`) {
56 return decode(typeWithoutNonNull, fieldValue)
57 }
58
59 if (typeWithoutNonNull.kind === `Interface` || typeWithoutNonNull.kind === `Union`) {
60 const possibleObjects = typeWithoutNonNull.kind === `Interface`
61 ? typeWithoutNonNull.implementors
62 : typeWithoutNonNull.members
63 // todo handle aliases -- will require having the selection set available for reference too :/
64 // eslint-disable-next-line
65 // @ts-ignore infinite depth issue
66 // eslint-disable-next-line
67 const ObjectType = possibleObjects.find((ObjectType) => {
68 if (fieldValue.__typename === ObjectType.fields.__typename.type.type) return true
69 if (Object.keys(fieldValue).every(fieldName => ObjectType.fields[fieldName] !== undefined)) return true
70 return false
71 }) as undefined | Object$2
72 if (!ObjectType) throw new Error(`Could not pick object for ${typeWithoutNonNull.kind} selection`)
73 return decode(ObjectType, fieldValue)
74 }
75
76 return fieldValue
77}