import type { GraphQLInterfaceType } from 'graphql' import { getRootTypeMap } from '../RootTypeMap.js' import type { Schema } from '../schema.js' import * as Type from '../type.js' import { isRoot } from '../type.js' import { isScalarTypeCustom } from '../typeGuards.js' import type { KindMap } from './__.js' export const Name = { Root: `Root`, ScalarCustom: `ScalarCustom`, ScalarStandard: `ScalarStandard`, Enum: `Enum`, InputObject: `InputObject`, OutputObject: `OutputObject`, Interface: `Interface`, Union: `Union`, } satisfies Record export type KindName = keyof KindMap[`list`] export const getKindMap = (schema: Schema): KindMap => { const rootTypeMap = getRootTypeMap(schema) const typeMap = schema.getTypeMap() const typeMapValues = Object.values(typeMap) const kindMap: KindMap = { root: rootTypeMap, index: { Root: { query: rootTypeMap.types.Query, mutation: rootTypeMap.types.Mutation, subscription: rootTypeMap.types.Subscription, }, OutputObject: {}, InputObject: {}, Interface: {}, Union: {}, Enum: {}, ScalarCustom: {}, ScalarStandard: {}, }, list: { Root: [rootTypeMap.types.Query, rootTypeMap.types.Mutation, rootTypeMap.types.Subscription] .filter(_ => _ !== null), OutputObject: [], InputObject: [], Interface: [], Union: [], Enum: [], ScalarCustom: [], ScalarStandard: [], }, } for (const type of typeMapValues) { if (type.name.startsWith(hiddenTypePrefix)) continue switch (true) { case Type.isScalar(type): if (isScalarTypeCustom(type)) { kindMap.list.ScalarCustom.push(type) kindMap.index.ScalarCustom[type.name] = type } else { kindMap.list.ScalarStandard.push(type) kindMap.index.ScalarStandard[type.name] = type } break case Type.isEnum(type): kindMap.list.Enum.push(type) kindMap.index.Enum[type.name] = type break case Type.isInputObject(type): kindMap.list.InputObject.push(type) kindMap.index.InputObject[type.name] = type break case Type.isInterface(type): kindMap.list.Interface.push(type) kindMap.index.Interface[type.name] = type break case Type.isObject(type): if (!isRoot(rootTypeMap, type)) { kindMap.list.OutputObject.push(type) kindMap.index.OutputObject[type.name] = type } break case Type.isUnion(type): kindMap.list.Union.push(type) kindMap.index.Union[type.name] = type break default: // skip break } } return kindMap } export const hasCustomScalars = (typeMapByKind: KindMap) => { return typeMapByKind.list.ScalarCustom.length > 0 } export const getInterfaceImplementors = ( typeMap: KindMap, interfaceTypeSearch: GraphQLInterfaceType, ) => { const outputObjectTypes = typeMap.list.OutputObject.filter(objectType => objectType.getInterfaces().filter(interfaceType => interfaceType.name === interfaceTypeSearch.name).length > 0 ) const interfaceTypes = typeMap.list.Interface.filter(interfaceType => interfaceType.getInterfaces().filter(interfaceType => interfaceType.name === interfaceTypeSearch.name).length > 0 ) return [...outputObjectTypes, ...interfaceTypes] } // todo put in some central place const hiddenTypePrefix = `__`