@graphql-ts/schema

Search for an npm package
import type { GraphQLFieldExtensions, GraphQLObjectTypeConfig, GraphQLResolveInfo, GraphQLUnionTypeConfig, GraphQLArgumentConfig, GraphQLInputFieldConfig, GraphQLScalarTypeConfig, FieldDefinitionNode } from "graphql";
import { GArg, GEnumType, GEnumTypeConfig, GEnumValueConfig, GField, GInputObjectType, GInputObjectTypeConfig, GInputType, GInterfaceField, GInterfaceType, GInterfaceTypeConfig, GList, GNonNull, GNullableInputType, GNullableType, GObjectType, GOutputType, GScalarType, GType, GUnionType, InferValueFromOutputType, InferValueFromArgs, InferValueFromInputType } from "./types.js";
type SomeTypeThatIsntARecordOfArgs = string;
type ImpliedResolver<Args extends {
[Key in keyof Args]: GArg<GInputType>;
}, Type extends GOutputType<Context>, Context> = InferValueFromOutputType<Type> | ((args: InferValueFromArgs<Args>, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<Type>);
type Maybe<T> = T | null | undefined;
type FieldFuncArgs<Source, Args extends {
[Key in keyof Args]: GArg<GInputType>;
}, Type extends GOutputType<Context>, Context> = {
args?: Args;
type: Type;
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<Readonly<GraphQLFieldExtensions<Source, Context>>>;
astNode?: Maybe<FieldDefinitionNode>;
};
/** @deprecated */
export type InterfaceToInterfaceFields<Interface extends GInterfaceType<any, any, any>> = Interface extends GInterfaceType<any, infer Fields, any> ? Fields : never;
type InterfaceFieldsToOutputFields<Source, Context, Fields extends {
[key: string]: GInterfaceField<any, any, any>;
}> = {
[Key in keyof Fields]: Fields[Key] extends GInterfaceField<infer Args, infer OutputType, any> ? GField<Source, Args, OutputType, Key extends keyof Source ? Source[Key] : unknown, Context> : never;
};
/** @deprecated */
export type _InterfacesToOutputFields<Source, Context, Interfaces extends readonly GInterfaceType<Source, any, Context>[]> = InterfacesToOutputFields<Source, Context, Interfaces>;
export type { _InterfacesToOutputFields as InterfacesToOutputFields };
type InterfacesToOutputFields<Source, Context, Interfaces extends readonly GInterfaceType<Source, any, any>[]> = MergeTuple<{
[Key in keyof Interfaces]: Interfaces[Key] extends GInterfaceType<Source, infer Fields, any> ? InterfaceFieldsToOutputFields<Source, Context, Fields> : never;
}, {}>;
export type InterfacesToInterfaceFields<Interfaces extends readonly GInterfaceType<any, any, any>[]> = MergeTuple<{
[Key in keyof Interfaces]: Interfaces[Key] extends GInterfaceType<any, infer Fields, any> ? Fields : never;
}, {}>;
type MergeTuple<T, Merged> = T extends readonly [infer U, ...infer Rest] ? MergeTuple<Rest, Merged & U> : Merged;
export type GWithContext<Context> = {
/**
* Creates a GraphQL object type.
*
* Note this is an **output** type, if you want an input object, use
* `g.inputObject`.
*
* When calling `g.object`, you must provide a type parameter that is the
* source of the object type. The source is what you receive as the first
* argument of resolvers on this type and what you must return from resolvers
* of fields that return this type.
*
* ```ts
* const Person = g.object<{ name: string }>()({
* name: "Person",
* fields: {
* name: g.field({ type: g.String }),
* },
* });
* // ==
* graphql`
* type Person {
* name: String
* }
* `;
* ```
*
* ## Writing resolvers
*
* To do anything other than just return a field from the source type, you
* need to provide a resolver.
*
* Note: TypeScript will force you to provide a resolve function if the field
* in the source type and the GraphQL field don't match
*
* ```ts
* const Person = g.object<{ name: string }>()({
* name: "Person",
* fields: {
* name: g.field({ type: g.String }),
* excitedName: g.field({
* type: g.String,
* resolve(source, args, context, info) {
* return `${source.name}!`;
* },
* }),
* },
* });
* ```
*
* ## Circularity
*
* GraphQL types will often contain references to themselves and to make
* TypeScript allow that, you need have an explicit type annotation of
* `g<typeof g.object<Source>>` along with making `fields` a function that
* returns the object.
*
* ```ts
* type PersonSource = { name: string; friends: PersonSource[] };
*
* const Person: g<typeof g.object<PersonSource>> =
* g.object<PersonSource>()({
* name: "Person",
* fields: () => ({
* name: g.field({ type: g.String }),
* friends: g.field({ type: g.list(Person) }),
* }),
* });
* ```
*/
object: <Source>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields extends {
[Key in keyof Fields]: GField<Source, any, any, Key extends keyof Source ? Source[Key] : unknown, Context>;
} & InterfaceFieldsToOutputFields<Source, Context, InterfacesToInterfaceFields<Interfaces>>, const Interfaces extends readonly GInterfaceType<Source, any, Context>[] = []>(config: {
fields: Fields | (() => Fields);
interfaces?: [...Interfaces];
} & Omit<GraphQLObjectTypeConfig<Source, Context>, "fields" | "interfaces">) => GObjectType<Source, Context>;
/**
* Create a GraphQL union type.
*
* A union type represents an object that could be one of a list of types.
* Note it is similar to an {@link GInterfaceType interface type} except that a
* union doesn't imply having a common set of fields among the member types.
*
* ```ts
* const A = g.object<{ __typename: "A" }>()({
* name: "A",
* fields: {
* something: g.field({ type: g.String }),
* },
* });
* const B = g.object<{ __typename: "B" }>()({
* name: "B",
* fields: {
* differentThing: g.field({ type: g.String }),
* },
* });
* const AOrB = g.union({
* name: "AOrB",
* types: [A, B],
* });
* ```
*/
union: <Type extends GObjectType<any, Context>>(config: Flatten<Omit<GraphQLUnionTypeConfig<Type extends GObjectType<infer Source, Context> ? Source : never, Context>, "types"> & {
types: readonly Type[] | (() => readonly Type[]);
}>) => GUnionType<Type extends GObjectType<infer Source, Context> ? Source : never, Context>;
/**
* Creates a GraphQL field.
*
* These will generally be passed directly to the `fields` object in a
* `g.object` call.
*
* ```ts
* const Something = g.object<{ thing: string }>()({
* name: "Something",
* fields: {
* thing: g.field({ type: g.String }),
* },
* });
* ```
*/
field: <Source, Type extends GOutputType<Context>, Resolve, Args extends {
[Key in keyof Args]: GArg<GInputType>;
} = {}>(field: FieldFuncArgs<Source, Args, Type, Context> & (Resolve extends {} ? {
resolve: ((source: Source, args: InferValueFromArgs<SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args>, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<Type>) & Resolve;
} : {
resolve?: ((source: Source, args: InferValueFromArgs<SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args>, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<Type>) & Resolve;
})) => GField<Source, Args, Type, Resolve extends {} ? unknown : ImpliedResolver<Args, Type, Context>, Context>;
/**
* A helper to declare fields while providing the source type a single time
* rather than in every resolver.
*
* ```ts
* const nodeFields = g.fields<{ id: string }>()({
* id: g.field({ type: g.ID }),
* relatedIds: g.field({
* type: g.list(g.ID),
* resolve(source) {
* return loadRelatedIds(source.id);
* },
* }),
* otherRelatedIds: g.field({
* type: g.list(g.ID),
* resolve(source) {
* return loadOtherRelatedIds(source.id);
* },
* }),
* });
*
* const Person = g.object<{
* id: string;
* name: string;
* }>()({
* name: "Person",
* fields: {
* ...nodeFields,
* name: g.field({ type: g.String }),
* },
* });
* ```
*/
fields: <Source>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields extends Record<string, GField<Source, any, GOutputType<Context>, any, Context>> & {
[Key in keyof Source]?: GField<Source, any, GOutputType<Context>, Source[Key], Context>;
}>(fields: Fields) => Fields;
/**
* Creates a GraphQL interface field.
*
* These will generally be passed directly to the `fields` object in a
* {@link g.interface} call. Interfaces fields are similar to
* {@link GField regular fields} except that they **don't define how the field
* is resolved**.
*
* ```ts
* const Entity = g.interface()({
* name: "Entity",
* fields: {
* name: g.interfaceField({ type: g.String }),
* },
* });
* ```
*
* Note that {@link GField regular fields} are assignable to
* {@link GInterfaceField interface fields} but the opposite is not true. This
* means that you can use a regular field in an
* {@link GInterfaceType interface type}.
*/
interfaceField: <Args extends {
[Key in keyof Args]: GArg<GInputType>;
}, Type extends GOutputType<Context>>(field: GInterfaceField<Args, Type, Context>) => GInterfaceField<Args, Type, Context>;
/**
* Creates a GraphQL interface type that can be implemented by other GraphQL
* object and interface types.
*
* ```ts
* const Entity = g.interface()({
* name: "Entity",
* fields: {
* name: g.interfaceField({ type: g.String }),
* },
* });
*
* type PersonSource = { __typename: "Person"; name: string };
*
* const Person = g.object<PersonSource>()({
* name: "Person",
* interfaces: [Entity],
* fields: {
* name: g.field({ type: g.String }),
* },
* });
*
* type OrganisationSource = {
* __typename: "Organisation";
* name: string;
* };
*
* const Organisation = g.object<OrganisationSource>()({
* name: "Organisation",
* interfaces: [Entity],
* fields: {
* name: g.field({ type: g.String }),
* },
* });
* ```
*
* ## Resolving Types
*
* When using GraphQL interface and union types, there needs to a way to
* determine which concrete object type has been returned from a resolver.
* With `graphql-js` and `@graphql-ts/schema`, this is done with `isTypeOf` on
* object types and `resolveType` on interface and union types. Note
* `@graphql-ts/schema` **does not aim to strictly type the implementation of
* `resolveType` and `isTypeOf`**. If you don't provide `resolveType` or
* `isTypeOf`, a `__typename` property on the source type will be used, if
* that fails, an error will be thrown at runtime.
*
* ## Fields vs Interface Fields
*
* You might have noticed that `g.interfaceField` was used instead of
* `g.field` for the fields on the interfaces. This is because **interfaces
* aren't defining implementation of fields** which means that fields on an
* interface don't need define resolvers.
*
* ## Sharing field implementations
*
* Even though interfaces don't contain field implementations, you may still
* want to share field implementations between interface implementations. You
* can use `g.fields` to do that. See `g.fields` for more information about
* why you should use `g.fields` instead of just defining an object the fields
* and spreading that.
*
* ```ts
* const nodeFields = g.fields<{ id: string }>({
* id: g.field({ type: g.ID }),
* });
*
* const Node = g.field({
* name: "Node",
* fields: nodeFields,
* });
*
* const Person = g.object<{
* __typename: "Person";
* id: string;
* name: string;
* }>()({
* name: "Person",
* interfaces: [Node],
* fields: {
* ...nodeFields,
* name: g.field({ type: g.String }),
* },
* });
* ```
*/
interface: <Source>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields extends {
[Key in keyof Fields]: GInterfaceField<any, GOutputType<Context>, Context>;
} & InterfacesToInterfaceFields<Interfaces>, const Interfaces extends readonly GInterfaceType<Source, any, Context>[] = []>(config: GInterfaceTypeConfig<Source, Fields, Interfaces, Context>) => GInterfaceType<Source, Fields, Context>;
/**
* A shorthand to easily create {@link GEnumValueConfig enum values} to pass to
* {@link g.enum}.
*
* If you need to set a `description` or `deprecationReason` for an enum
* variant, you should pass values directly to `g.enum` without using
* `g.enumValues`.
*
* ```ts
* const MyEnum = g.enum({
* name: "MyEnum",
* values: g.enumValues(["a", "b"]),
* });
* ```
*
* ```ts
* const values = g.enumValues(["a", "b"]);
*
* assertDeepEqual(values, {
* a: { value: "a" },
* b: { value: "b" },
* });
* ```
*/
enumValues: <const Values extends readonly string[]>(values: readonly [...Values]) => {
[Key in Values[number]]: GEnumValueConfig<Key>;
};
/**
* Creates an {@link GEnumType enum type} with a number of
* {@link GEnumValueConfig enum values}.
*
* ```ts
* const MyEnum = g.enum({
* name: "MyEnum",
* values: g.enumValues(["a", "b"]),
* });
* // ==
* graphql`
* enum MyEnum {
* a
* b
* }
* `;
* ```
*
* ```ts
* const MyEnum = g.enum({
* name: "MyEnum",
* description: "My enum does things",
* values: {
* something: {
* description: "something something",
* value: "something",
* },
* thing: {
* description: "thing thing",
* deprecationReason: "something should be used instead of thing",
* value: "thing",
* },
* },
* });
* // ==
* graphql`
* """
* My enum does things
* """
* enum MyEnum {
* """
* something something
* """
* something
* """
* thing thing
* """
* thing @\deprecated(reason: "something should be used instead of thing")
* }
* `;)
* ```
*/
enum: <const Values extends Record<string, unknown>>(config: GEnumTypeConfig<Values>) => GEnumType<Values>;
/**
* Creates a {@link GArg GraphQL argument}.
*
* 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`(something: String): String`;
* ```
*
* Or as fields on input objects:
*
* ```ts
* const Something = g.inputObject({
* name: "Something",
* fields: {
* something: g.arg({ type: g.String }),
* },
* });
* // ==
* graphql`
* input Something {
* something: String
* }
* `;
* ```
*/
arg: <Type extends GInputType, DefaultValue extends InferValueFromInputType<Type> | undefined = undefined>(arg: Flatten<{
type: Type;
} & Omit<GraphQLInputFieldConfig & GraphQLArgumentConfig, "type" | "defaultValue">> & (undefined extends DefaultValue ? {
defaultValue?: DefaultValue;
} : {
defaultValue: DefaultValue;
})) => GArg<Type, DefaultValue extends undefined ? false : true>;
/**
* Creates an {@link GInputObjectType input object type}
*
* ```ts
* const Something = g.inputObject({
* name: "Something",
* fields: {
* something: g.arg({ type: g.String }),
* },
* });
* // ==
* graphql`
* input Something {
* something: String
* }
* `;
* ```
*
* ### Handling circular objects
*
* Circular input objects require explicitly specifying the fields on the
* object in the type because of TypeScript's limits with circularity.
*
* ```ts
* import { GInputObjectType } from "@graphql-ts/schema";
*
* type SomethingInputType = GInputObjectType<{
* something: g<typeof g.arg<SomethingInputType>>;
* }>;
* const Something: SomethingInputType = g.inputObject({
* name: "Something",
* fields: () => ({
* something: g.arg({ type: Something }),
* }),
* });
* ```
*
* You can specify all of your non-circular fields outside of the fields
* object and then use `typeof` to get the type to avoid writing the
* non-circular fields as types again.
*
* ```ts
* import { GInputObjectType } from "@graphql-ts/schema";
*
* const nonCircularFields = {
* thing: g.arg({ type: g.String }),
* };
* type SomethingInputType = GInputObjectType<
* typeof nonCircularFields & {
* something: g<typeof g.arg<SomethingInputType>>;
* }
* >;
* const Something: SomethingInputType = g.inputObject({
* name: "Something",
* fields: () => ({
* ...nonCircularFields,
* something: g.arg({ type: Something }),
* }),
* });
* ```
*/
inputObject: <Fields extends {
[key: string]: IsOneOf extends true ? GArg<GNullableInputType, false> : GArg<GInputType>;
}, IsOneOf extends boolean = false>(config: GInputObjectTypeConfig<Fields, IsOneOf>) => GInputObjectType<Fields, IsOneOf>;
/**
* Wraps any GraphQL type in a {@link GList list type}.
*
* ```ts
* const stringListType = g.list(g.String);
* // ==
* graphql`[String]`;
* ```
*
* When used as an input type, you will recieve an array of the inner type.
*
* ```ts
* g.field({
* type: g.String,
* args: { thing: g.arg({ type: g.list(g.String) }) },
* resolve(source, { thing }) {
* const theThing: undefined | null | Array<string | null> = thing;
* return "";
* },
* });
* ```
*
* When used as an output type, you can return an iterable of the inner type
* that also matches `typeof val === 'object'` so for example, you'll probably
* return an Array most of the time but you could also return a Set you
* couldn't return a string though, even though a string is an iterable, it
* doesn't match `typeof val === 'object'`.
*
* ```ts
* g.field({
* type: g.list(g.String),
* resolve() {
* return [""];
* },
* });
* ```
*
* ```ts
* g.field({
* type: g.list(g.String),
* resolve() {
* return new Set([""]);
* },
* });
* ```
*
* ```ts
* g.field({
* type: g.list(g.String),
* resolve() {
* // this will not be allowed
* return "some things";
* },
* });
* ```
*/
list: <Of extends GType<any>>(of: Of) => GList<Of>;
/**
* Wraps a {@link GNullableType nullable type} with a
* {@link GNonNull non-nullable type}.
*
* Types in GraphQL are always nullable by default so if you want to enforce
* that a type must always be there, you can use the non-null type.
*
* ```ts
* const nonNullableString = g.nonNull(g.String);
* // ==
* graphql`String!`;
* ```
*
* When using a non-null type as an input type, your resolver will never
* recieve null and consumers of your GraphQL API **must** provide a value for
* it unless you provide a default value.
*
* ```ts
* g.field({
* args: {
* someNonNullAndRequiredArg: g.arg({
* type: g.nonNull(g.String),
* }),
* someNonNullButOptionalArg: g.arg({
* type: g.nonNull(g.String),
* defaultValue: "some default",
* }),
* },
* type: g.String,
* resolve(source, args) {
* // both of these will always be a string
* args.someNonNullAndRequiredArg;
* args.someNonNullButOptionalArg;
*
* return "";
* },
* });
* // ==
* graphql`
* fieldName(
* someNonNullAndRequiredArg: String!
* someNonNullButOptionalArg: String! = "some default"
* ): String
* `;
* ```
*
* When using a non-null type as an output type, your resolver must never
* return null. If you do return null(which unless you do
* type-casting/ts-ignore/etc. `@graphql-ts/schema` will not let you do)
* graphql-js will return an error to consumers of your GraphQL API.
*
* Non-null types should be used very carefully on output types. If you have
* to do a fallible operation like a network request or etc. to get the value,
* it probably shouldn't be non-null. If you make a field non-null and doing
* the fallible operation fails, consumers of your GraphQL API will be unable
* to see any of the other fields on the object that the non-null field was
* on. For example, an id on some type is a good candidate for being non-null
* because if you have the item, you will already have the id so getting the
* id will never fail but fetching a related item from a database would be
* fallible so even if it will never be null in the success case, you should
* make it nullable.
*
* ```ts
* g.field({
* type: g.nonNull(g.String),
* resolve(source, args) {
* return "something";
* },
* });
* // ==
* graphql`
* fieldName: String!
* `;
* ```
*
* If you try to wrap another non-null type in a non-null type again, you will
* get a type error.
*
* ```ts
* // Argument of type 'NonNullType<ScalarType<string>>'
* // is not assignable to parameter of type 'NullableType'.
* g.nonNull(g.nonNull(g.String));
* ```
*/
nonNull: <Of extends GNullableType<any>>(of: Of) => GNonNull<Of>;
/**
* Creates a {@link GScalarType scalar type}.
*
* ```ts
* const BigInt = g.scalar({
* name: "BigInt",
* serialize(value) {
* if (typeof value !== "bigint")
* throw new GraphQLError(
* `unexpected value provided to BigInt scalar: ${value}`
* );
* return value.toString();
* },
* parseLiteral(value) {
* if (value.kind !== "StringValue")
* throw new GraphQLError("BigInt only accepts values as strings");
* return globalThis.BigInt(value.value);
* },
* parseValue(value) {
* if (typeof value === "bigint") return value;
* if (typeof value !== "string")
* throw new GraphQLError("BigInt only accepts values as strings");
* return globalThis.BigInt(value);
* },
* });
* // for fields on output types
* g.field({ type: someScalar });
*
* // for args on output fields or fields on input types
* g.arg({ type: someScalar });
* ```
*
* Note, while graphql-js allows you to express scalar types like the `ID`
* type which accepts integers and strings as both input values and return
* values from resolvers which are transformed into strings before calling
* resolvers and returning the query respectively, the type you use should be
* `string` for `ID` since that is what it is transformed into.
* `@graphql-ts/schema` doesn't currently express the coercion of scalars, you
* should instead convert values to the canonical form yourself before
* returning from resolvers.
*/
scalar: <Internal, External = Internal>(config: GraphQLScalarTypeConfig<Internal, External>) => GScalarType<Internal, External>;
ID: GScalarType<string>;
String: GScalarType<string>;
Float: GScalarType<number>;
Int: GScalarType<number>;
Boolean: GScalarType<boolean>;
};
/**
* The `gWithContext` function accepts a `Context` type parameter which binds
* the returned functions so they can be used to compose GraphQL types into a
* GraphQL schema.
*
* A simple schema with only a query type looks like this:
*
* ```ts
* import { gWithContext } from "@graphql-ts/schema";
* import { GraphQLSchema, graphql } from "graphql";
*
* type Context = {};
*
* const g = gWithContext<Context>();
* type g<T> = gWithContext.infer<T>;
*
* const Query = g.object()({
* name: "Query",
* fields: {
* hello: g.field({
* type: g.String,
* resolve() {
* return "Hello!";
* },
* }),
* },
* });
*
* const schema = new GraphQLSchema({
* query: Query,
* });
*
* graphql({
* source: `
* query {
* hello
* }
* `,
* schema,
* }).then((result) => {
* console.log(result);
* });
* ```
*
* You can use pass the `schema` to `ApolloServer` and other GraphQL servers.
*
* You can also create a more advanced schema with other object types, circular
* types, args, and mutations. See {@link GWithContext} for what the other
* functions on `g` do.
*
* ```ts
* import { gWithContext } from "@graphql-ts/schema";
* import { GraphQLSchema, graphql } from "graphql";
* import { deepEqual } from "node:assert";
*
* type Context = {
* todos: Map<string, TodoItem>;
* };
*
* const g = gWithContext<Context>();
* type g<T> = gWithContext.infer<T>;
*
* type TodoItem = {
* id: string;
* title: string;
* relatedTodos: string[];
* };
*
* const Todo: g<typeof g.object<TodoItem>> = g.object<TodoItem>()({
* name: "Todo",
* fields: () => ({
* id: g.field({ type: g.nonNull(g.ID) }),
* title: g.field({ type: g.nonNull(g.String) }),
* relatedTodos: g.field({
* type: g.list(Todo),
* resolve(source, _args, context) {
* return source.relatedTodos
* .map((id) => context.todos.get(id))
* .filter((todo) => todo !== undefined);
* },
* }),
* }),
* });
*
* const Query = g.object()({
* name: "Query",
* fields: {
* todos: g.field({
* type: g.list(Todo),
* resolve(_source, _args, context) {
* return context.todos.values();
* },
* }),
* },
* });
*
* const Mutation = g.object()({
* name: "Mutation",
* fields: {
* createTodo: g.field({
* args: {
* title: g.arg({ type: g.nonNull(g.String) }),
* relatedTodos: g.arg({
* type: g.nonNull(g.list(g.nonNull(g.ID))),
* defaultValue: [],
* }),
* },
* type: Todo,
* resolve(_source, { title, relatedTodos }, context) {
* const todo = { title, relatedTodos, id: crypto.randomUUID() };
* context.todos.set(todo.id, todo);
* return todo;
* },
* }),
* },
* });
*
* const schema = new GraphQLSchema({
* query: Query,
* mutation: Mutation,
* });
*
* (async () => {
* const contextValue: Context = { todos: new Map() };
* {
* const result = await graphql({
* source: `
* query {
* todos {
* title
* }
* }
* `,
* schema,
* contextValue,
* });
* deepEqual(result, { data: { todos: [] } });
* }
*
* {
* const result = await graphql({
* source: `
* mutation {
* createTodo(title: "Try graphql-ts") {
* title
* }
* }
* `,
* schema,
* contextValue,
* });
* deepEqual(result, {
* data: { createTodo: { title: "Try graphql-ts" } },
* });
* }
* {
* const result = await graphql({
* source: `
* query {
* todos {
* title
* }
* }
* `,
* schema,
* contextValue,
* });
* deepEqual(result, {
* data: { todos: [{ title: "Try graphql-ts" }] },
* });
* }
* })();
* ```
*/
export declare function gWithContext<Context>(): GWithContext<Context>;
export declare namespace gWithContext {
/**
* The `gWithContext.infer` type is useful particularly when defining circular
* types to resolve errors from TypeScript because of the circularity.
*
* We recommend aliasing `gWithContext.infer` to your `g` like this to make it
* easier to use:
*
* ```ts
* import { gWithContext } from "@graphql-ts/schema";
* type Context = {};
*
* const g = gWithContext<Context>();
* type g<T> = gWithContext.infer<T>;
*
* type PersonSource = { name: string; friends: PersonSource[] };
*
* const Person: g<typeof g.object<PersonSource>> =
* g.object<PersonSource>()({
* name: "Person",
* fields: () => ({
* name: g.field({ type: g.String }),
* friends: g.field({ type: g.list(Person) }),
* }),
* });
* ```
*/
type infer<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never;
}
type Flatten<T> = {
[Key in keyof T]: T[Key];
} & {};
//# sourceMappingURL=output.d.ts.map
No newline at end of file