UNPKG

7.92 kBPlain TextView Raw
1import type { GraphQLEnumValue, GraphQLError, GraphQLField, GraphQLInputField, GraphQLSchema } from 'graphql'
2import {
3 GraphQLEnumType,
4 GraphQLInputObjectType,
5 GraphQLInterfaceType,
6 GraphQLList,
7 GraphQLNonNull,
8 GraphQLObjectType,
9 GraphQLScalarType,
10 GraphQLUnionType,
11 isListType,
12 isNonNullType,
13} from 'graphql'
14import type { ObjMap } from 'graphql/jsutils/ObjMap.js'
15import type { Errors } from './errors/__.js'
16
17export type TypeMapByKind =
18 & {
19 [Name in keyof NameToClassNamedType]: InstanceType<NameToClassNamedType[Name]>[]
20 }
21 & { GraphQLRootType: GraphQLObjectType[] }
22 & { GraphQLScalarTypeCustom: GraphQLScalarType<any, any>[] }
23 & { GraphQLScalarTypeStandard: GraphQLScalarType<any, any>[] }
24
25export const standardScalarTypeNames = {
26 String: `String`,
27 ID: `ID`,
28 Int: `Int`,
29 Float: `Float`,
30 Boolean: `Boolean`,
31}
32
33export const RootTypeName = {
34 Query: `Query`,
35 Mutation: `Mutation`,
36 Subscription: `Subscription`,
37} as const
38
39export const operationTypeNameToRootTypeName = {
40 query: `Query`,
41 mutation: `Mutation`,
42 subscription: `Subscription`,
43} as const
44
45export const rootTypeNameToOperationName = {
46 Query: `query`,
47 Mutation: `mutation`,
48 Subscription: `subscription`,
49} as const
50
51export type RootTypeName = keyof typeof RootTypeName
52
53export const isStandardScalarType = (type: GraphQLScalarType) => {
54 return type.name in standardScalarTypeNames
55}
56
57export const isCustomScalarType = (type: GraphQLScalarType) => {
58 return !isStandardScalarType(type)
59}
60
61export const unwrapToNamed = (
62 type: AnyClass,
63): AnyClass => {
64 if (isNonNullType(type)) return unwrapToNamed(unwrapToNonNull(type).ofType)
65 if (isListType(type)) return unwrapToNamed(type.ofType)
66 return type
67}
68
69export const unwrapToNonNull = (
70 type: AnyClass,
71): { ofType: AnyClass; nullable: boolean } => {
72 const [nodeUnwrapped, nullable] = type instanceof GraphQLNonNull ? [type.ofType, false] : [type, true]
73 return { ofType: nodeUnwrapped, nullable }
74}
75
76export const getTypeMapByKind = (schema: GraphQLSchema) => {
77 const typeMap = schema.getTypeMap()
78 const typeMapValues = Object.values(typeMap)
79 const typeMapByKind: TypeMapByKind = {
80 GraphQLRootType: [],
81 GraphQLScalarType: [],
82 GraphQLScalarTypeCustom: [],
83 GraphQLScalarTypeStandard: [],
84 GraphQLEnumType: [],
85 GraphQLInputObjectType: [],
86 GraphQLInterfaceType: [],
87 GraphQLObjectType: [],
88 GraphQLUnionType: [],
89 }
90 for (const type of typeMapValues) {
91 if (type.name.startsWith(`__`)) continue
92 switch (true) {
93 case type instanceof GraphQLScalarType:
94 typeMapByKind.GraphQLScalarType.push(type)
95 if (isCustomScalarType(type)) {
96 typeMapByKind.GraphQLScalarTypeCustom.push(type)
97 } else {
98 typeMapByKind.GraphQLScalarTypeStandard.push(type)
99 }
100 break
101 case type instanceof GraphQLEnumType:
102 typeMapByKind.GraphQLEnumType.push(type)
103 break
104 case type instanceof GraphQLInputObjectType:
105 typeMapByKind.GraphQLInputObjectType.push(type)
106 break
107 case type instanceof GraphQLInterfaceType:
108 typeMapByKind.GraphQLInterfaceType.push(type)
109 break
110 case type instanceof GraphQLObjectType:
111 if (type.name === `Query` || type.name === `Mutation` || type.name === `Subscription`) {
112 typeMapByKind.GraphQLRootType.push(type)
113 } else {
114 typeMapByKind.GraphQLObjectType.push(type)
115 }
116 break
117 case type instanceof GraphQLUnionType:
118 typeMapByKind.GraphQLUnionType.push(type)
119 break
120 default:
121 // skip
122 break
123 }
124 }
125 return typeMapByKind
126}
127
128export type ClassToName<C> = C extends GraphQLScalarType ? `GraphQLScalarType`
129 : C extends GraphQLObjectType ? `GraphQLObjectType`
130 : C extends GraphQLInterfaceType ? `GraphQLInterfaceType`
131 : C extends GraphQLUnionType ? `GraphQLUnionType`
132 : C extends GraphQLEnumType ? `GraphQLEnumType`
133 : C extends GraphQLInputObjectType ? `GraphQLInputObjectType`
134 : C extends GraphQLList<any> ? `GraphQLList`
135 : C extends GraphQLNonNull<any> ? `GraphQLNonNull`
136 : never
137
138export const NameToClassNamedType = {
139 GraphQLScalarType: GraphQLScalarType,
140 GraphQLObjectType: GraphQLObjectType,
141 GraphQLInterfaceType: GraphQLInterfaceType,
142 GraphQLUnionType: GraphQLUnionType,
143 GraphQLEnumType: GraphQLEnumType,
144 GraphQLInputObjectType: GraphQLInputObjectType,
145}
146
147export type NameToClassNamedType = typeof NameToClassNamedType
148
149export const NamedNameToClass = {
150 GraphQLScalarType: GraphQLScalarType,
151 GraphQLObjectType: GraphQLObjectType,
152 GraphQLInterfaceType: GraphQLInterfaceType,
153 GraphQLUnionType: GraphQLUnionType,
154 GraphQLEnumType: GraphQLEnumType,
155 GraphQLInputObjectType: GraphQLInputObjectType,
156} as const
157
158export type NamedNameToClass = typeof NamedNameToClass
159
160export const NameToClass = {
161 GraphQLNonNull: GraphQLNonNull,
162 GraphQLList: GraphQLList,
163 ...NamedNameToClass,
164} as const
165
166export type AnyGraphQLOutputField = GraphQLField<any, any>
167
168export type AnyField = AnyGraphQLOutputField | GraphQLInputField
169
170export type NameToClass = typeof NameToClass
171
172export type NodeName = keyof NameToClass
173
174export type NodeNamePlus = NodeName | 'GraphQLField'
175
176export type AnyNamedClassName = keyof NamedNameToClass
177
178export type AnyClass = InstanceType<NameToClass[keyof NameToClass]>
179
180export const isGraphQLOutputField = (object: object): object is AnyGraphQLOutputField => {
181 return `args` in object
182}
183
184/**
185 * Groups
186 */
187
188export type Describable =
189 | GraphQLUnionType
190 | GraphQLObjectType
191 | GraphQLInputObjectType
192 | AnyField
193 | GraphQLInterfaceType
194 | GraphQLEnumType
195
196export const getNodeName = (node: Describable): NodeNamePlus => {
197 switch (true) {
198 case node instanceof GraphQLObjectType:
199 return `GraphQLObjectType`
200 case node instanceof GraphQLInputObjectType:
201 return `GraphQLInputObjectType`
202 case node instanceof GraphQLUnionType:
203 return `GraphQLUnionType`
204 case node instanceof GraphQLInterfaceType:
205 return `GraphQLInterfaceType`
206 case node instanceof GraphQLEnumType:
207 return `GraphQLEnumType`
208 case node instanceof GraphQLScalarType:
209 return `GraphQLScalarType`
210 default:
211 return `GraphQLField`
212 }
213}
214
215// const displayNames = {
216// GraphQLEnumType: `Enum`,
217// GraphQLInputObjectType: `InputObject`,
218// GraphQLInterfaceType: `Interface`,
219// GraphQLList: `List`,
220// GraphQLNonNull: `NonNull`,
221// GraphQLObjectType: `Object`,
222// GraphQLScalarType: `Scalar`,
223// GraphQLUnionType: `Union`,
224// } satisfies Record<NodeName, string>
225
226export const getNodeDisplayName = (node: Describable) => {
227 return toDisplayName(getNodeName(node))
228}
229
230const toDisplayName = (nodeName: NodeNamePlus) => {
231 return nodeName.replace(/^GraphQL/, ``).replace(/Type$/, ``)
232}
233
234export const isDeprecatableNode = (node: object): node is GraphQLEnumValue | AnyField => {
235 return `deprecationReason` in node
236}
237
238export const hasQuery = (typeMapByKind: TypeMapByKind) => typeMapByKind.GraphQLRootType.find((_) => _.name === `Query`)
239
240export const hasMutation = (typeMapByKind: TypeMapByKind) =>
241 typeMapByKind.GraphQLRootType.find((_) => _.name === `Mutation`)
242
243export const hasSubscription = (typeMapByKind: TypeMapByKind) =>
244 typeMapByKind.GraphQLRootType.find((_) => _.name === `Subscription`)
245
246export type StandardScalarVariables = {
247 [key: string]: string | boolean | null | number | StandardScalarVariables
248}
249
250export type GraphQLExecutionResultError = Errors.ContextualAggregateError<GraphQLError>
251
252export type OperationTypeName = 'query' | 'mutation'
253
254export const isOperationTypeName = (value: unknown): value is OperationTypeName =>
255 value === `query` || value === `mutation`
256
257export interface SomeExecutionResultWithoutErrors<
258 TData = ObjMap<unknown>,
259 TExtensions = ObjMap<unknown>,
260> {
261 errors?: readonly []
262 data?: TData | null
263 extensions?: TExtensions
264}