/** * This module exports modified versions of the GraphQL types from the `graphql` * package that add more type-safety but are still at runtime exactly the same * as the original types. Some of the constructors * * @module */ import { GraphQLArgumentExtensions, GraphQLEnumType, type GraphQLEnumTypeConfig, type GraphQLEnumValueConfig, GraphQLFieldExtensions, GraphQLInputField, GraphQLInputFieldExtensions, GraphQLInputObjectType, type GraphQLInputObjectTypeConfig, GraphQLInterfaceType, GraphQLInterfaceTypeConfig, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLObjectTypeConfig, GraphQLResolveInfo, GraphQLScalarType, type GraphQLTypeResolver, GraphQLUnionType, type GraphQLUnionTypeConfig, type FieldDefinitionNode, type InputValueDefinitionNode, } from "graphql"; import type { g } from "./g-for-doc-references.js"; type Maybe = T | null | undefined; export type GNullableOutputType = | GScalarType | GObjectType | GInterfaceType | GUnionType | GEnumType> | GList>; export type GOutputType = | GNullableOutputType | GNonNull>; export type GNullableInputType = | GScalarType | GEnumType> | GInputObjectType | GList; export type GInputType = GNullableInputType | GNonNull; export type GNullableType = | GNullableOutputType | GNullableInputType; export type GType = GOutputType | GInputType; export type GFieldResolver< Source, Args extends Record>, Type extends GOutputType, Context, > = ( source: Source, args: InferValueFromArgs, context: Context, info: GraphQLResolveInfo ) => InferValueFromOutputType; type InferValueFromOutputTypeWithoutAddingNull> = Type extends GraphQLScalarType ? Value : Type extends GraphQLEnumType ? Type extends GEnumType ? Values[keyof Values] : never : Type extends GList> ? // the `object` bit is here because graphql checks `typeof maybeIterable === 'object'` // which means that things like `string` won't be allowed // (which is probably a good thing because returning a string from a resolver that needs // a graphql list of strings is almost definitely not what you want and if it is, use Array.from) // sadly functions that are iterables will be allowed by this type but not allowed by graphql-js // (though tbh, i think the chance of that causing problems is quite low) object & Iterable> : Type extends GraphQLObjectType ? Source : Type extends GraphQLUnionType | GraphQLInterfaceType ? Type extends | GUnionType | GInterfaceType ? Source : unknown : never; export type InferValueFromOutputType> = MaybePromise< Type extends GNonNull> ? InferValueFromOutputTypeWithoutAddingNull : InferValueFromOutputTypeWithoutAddingNull | null | undefined >; type MaybePromise = Promise | T; type InferValueFromNullableInputType = Type extends GraphQLScalarType ? Value : Type extends GraphQLEnumType ? Type extends GEnumType ? Values[keyof Values] : unknown : Type extends GList ? InferValueFromInputType[] : Type extends GraphQLInputObjectType ? Type extends GInputObjectType ? IsOneOf extends true ? InferValueForOneOf : InferValueFromArgs : Record : never; type InferValueForOneOf< T extends { [key: string]: { type: GInputType } }, Key extends keyof T = keyof T, > = Flatten< Key extends unknown ? { readonly [K in Key]: InferValueFromNullableInputType; } & { readonly [K in Exclude]?: never; } : never >; export type InferValueFromArgs>> = { readonly [Key in keyof Args]: InferValueFromArg; } & {}; export type InferValueFromArg> = // the distribution technically only needs to be around the AddUndefined // but having it here instead of inside the union // means that TypeScript will print the resulting type // when you use it rather than keep the alias and // the resulting type is generally far more readable Arg extends unknown ? | InferValueFromInputType | AddUndefined : never; type AddUndefined = TInputType extends GNonNull ? never : DefaultValue & undefined; export type InferValueFromInputType = Type extends GNonNull ? InferValueFromNullableInputType : InferValueFromNullableInputType | null; /** * A GraphQL output field for an {@link GObjectType object type} which should be * created using {@link g.field}. */ export type GField< Source, Args extends { [Key in keyof Args]: GArg }, Type extends GOutputType, SourceAtKey, Context, > = { args?: Args; type: Type; resolve?: GFieldResolver; description?: Maybe; deprecationReason?: Maybe; extensions?: Maybe>>; astNode?: Maybe; __missingResolve: undefined | ((arg: SourceAtKey) => void); }; /** * A GraphQL object type. This should generally be constructed with * {@link g.object}. * * Note this is an **output** type, if you want an input object, use * {@link GInputObjectType}. * * If you use the `GObjectType` constructor directly, all fields will need * explicit resolvers so you should use `g.object` instead. */ export class GObjectType extends GraphQLObjectType< Source, Context > { constructor( config: Readonly< GObjectTypeConfig< Source, Context, Record>, readonly GInterfaceType[] > > ); } export type GObjectTypeConfig< Source, Context, Fields extends Record>, Interfaces extends readonly GInterfaceType[], > = { fields: Fields | (() => Fields); interfaces?: [...Interfaces]; } & Omit, "fields" | "interfaces">; /** * A GraphQL union type. This should generally be constructed with * {@link g.union}. * * A union type represents an object that could be one of a list of types. Note * it is similar to an {@link GInterfaceType} except that a union doesn't imply * having a common set of fields among the member types. * * While this constructor will work, you should generally use `g.union` because * you will need to explicitly provide the source type parameter as TypeScript * is unable to infer it correctly. Note this is only required for this * constructor, this is not required when using `g.union`. */ export class GUnionType extends GraphQLUnionType { constructor( config: Readonly< GUnionTypeConfig< Source extends any ? GObjectType : never, Context > > ); resolveType: Maybe>; } export type GUnionTypeConfig< ObjectType extends GObjectType, Context, > = Flatten< { types: readonly ObjectType[] | (() => readonly ObjectType[]); } & Omit< GraphQLUnionTypeConfig< ObjectType extends GObjectType ? Source : never, Context >, "types" > >; export type GInterfaceField< Args extends Record>, Type extends GOutputType, Context, > = { description?: Maybe; type: Type; args?: Args; deprecationReason?: Maybe; extensions?: Maybe>>; astNode?: Maybe; }; /** * A GraphQL interface type that can be implemented by other * {@link GObjectType GraphQL object} and interface types. This should generally * be constructed with {@link g.interface}. * * If you use the `GInterfaceType` constructor directly, all fields will need * explicit resolvers so you should use `g.interface` instead. */ export class GInterfaceType< Source, Fields extends Record< string, GInterfaceField, Context> >, Context, > extends GraphQLInterfaceType { declare resolveType: Maybe>; constructor( config: Readonly< GInterfaceTypeConfig< Source, Fields, readonly GInterfaceType[], Context > > ); toConfig(): Omit, "fields"> & { fields: Fields; }; } export type GInterfaceTypeConfig< Source, Fields extends Record< string, GInterfaceField, Context> >, Interfaces extends readonly GInterfaceType[], Context, > = Flatten< { fields: Fields | (() => Fields); interfaces?: [...Interfaces]; } & Omit, "interfaces" | "fields"> >; /** * A GraphQL argument. These should be created with {@link g.arg} * * Args can can be used as arguments on output fields: * * ```ts * g.field({ * type: g.String, * args: { * something: g.arg({ type: g.String }), * }, * resolve(source, { something }) { * return something || somethingElse; * }, * }); * // == * graphql`fieldName(something: String): String`; * ``` * * Or as fields on input objects: * * ```ts * g.inputObject({ * name: "Something", * fields: { * something: g.arg({ type: g.String }), * }, * }); * // == * graphql` * input Something { * something: String * } * `; * ``` * * When the type of an arg is {@link GNonNull non-null}, the value will always * exist. * * ```ts * g.field({ * type: g.String, * args: { * something: g.arg({ type: g.nonNull(g.String) }), * }, * resolve(source, { something }) { * // `something` will always be a string * return something; * }, * }); * // == * graphql`fieldName(something: String!): String`; * ``` */ export type GArg< Type extends GInputType, HasDefaultValue extends boolean = boolean, > = { type: Type; defaultValue: { true: {} | null; false: undefined; }[`${HasDefaultValue}`]; description?: Maybe; deprecationReason?: Maybe; extensions?: Maybe; astNode?: Maybe; }; export type GInputObjectTypeConfig< Fields extends { [key: string]: IsOneOf extends true ? GArg : GArg; }, IsOneOf extends boolean = false, > = Flatten< Omit & { fields: Fields | (() => Fields); isOneOf?: IsOneOf; } > & (true extends IsOneOf ? { isOneOf: unknown } : unknown); /** * A GraphQL input object type. This should generally be constructed with * {@link g.inputObject}. * * Unlike some other constructors in this module, this constructor functions * exactly the same as it's counterpart `g.inputObject` so it is safe to use * directly if desired. */ export class GInputObjectType< Fields extends { [key: string]: IsOneOf extends true ? GArg : GArg; }, IsOneOf extends boolean = false, > extends GraphQLInputObjectType { isOneOf: IsOneOf; constructor(config: Readonly>); getFields(): { [K in keyof Fields]: GraphQLInputField & { type: Fields[K]["type"]; defaultValue: Fields[K]["defaultValue"]; }; }; } export type GEnumValueConfig = GraphQLEnumValueConfig & { value: Value; }; export type GEnumTypeConfig = Flatten< { values: { [Name in keyof Values]: GEnumValueConfig; }; } & Omit >; /** * A GraphQL enum type. This should generally be constructed with {@link g.enum}. * * Unlike some other constructors in this module, this constructor functions * exactly the same as it's counterpart `g.enum` so it is safe to use directly * if desired. */ export class GEnumType< const Values extends { [key: string]: unknown }, > extends GraphQLEnumType { constructor(config: Readonly>); toConfig(): Omit, "values"> & { values: { [Name in keyof Values]: Partial>; }; }; } /** * A GraphQL enum type. This should generally be constructed with * {@link g.scalar}. * * Unlike some other constructors in this module, this constructor functions * exactly the same as it's counterpart `g.scalar` so it is safe to use directly * if desired. * * Also unlike some other types in this module, this type is exactly equivalent * to the original {@link GraphQLScalarType `GraphQLScalarType`} type from the * `graphql` package. */ export class GScalarType< Internal = unknown, External = Internal, > extends GraphQLScalarType {} type Flatten = { [K in keyof T]: T[K]; } & {}; /** * A GraphQL non-null type. This should generally be constructed with * {@link g.nonNull}. * * Unlike some other constructors in this module, this constructor functions * exactly the same as it's counterpart `g.nonNull` so it is safe to use * directly if desired. * * Also unlike the named types in this module, the original * {@link GraphQLNonNull `GraphQLNonNull`} type from the `graphql` package cannot * be assigned to a variable of type `GNonNull`. Though `GNonNull` _is_ * assignable to `GraphQLNonNull`. * * For example, the following code will not compile: * * ```ts * const nonNull: GNonNull> = new GraphQLNonNull( * GraphQLString * ); * ``` * * But the following code will compile: * * ```ts * const nonNull: GraphQLNonNull> = new GNonNull( * GraphQLString * ); * ``` * * This is due to the lack of a discriminating property between the * `GraphQLNonNull` and `GraphQLList` types. */ export class GNonNull< Of extends GNullableType, > extends GraphQLNonNull { get [Symbol.toStringTag](): "GraphQLNonNull"; } /** * A GraphQL list type. This should generally be constructed with {@link g.list}. * * Unlike some other constructors in this module, this constructor functions * exactly the same as it's counterpart `g.list` so it is safe to use directly * if desired. * * Also unlike the named types in this module, the original * {@link GraphQLList `GraphQLList`} type from the `graphql` package cannot be * assigned to a variable of type `GList`. Though `GList` _is_ assignable to * `GraphQLList`. * * For example, the following code will not compile: * * ```ts * const list: GList> = new GraphQLList(GraphQLString); * ``` * * But the following code will compile: * * ```ts * const list: GraphQLList> = new GList( * GraphQLString * ); * ``` * * This is due to the lack of a discriminating property between the * `GraphQLNonNull` and `GraphQLList` types. */ export class GList> extends GraphQLList { get [Symbol.toStringTag](): "GraphQLList"; } export {};