| 'use strict'; |
|
|
| var definition = require('graphql/type/definition'); |
| var scalars = require('graphql/type/scalars'); |
|
|
| /** |
| * An individual enum value in an {@link EnumType enum type} created using |
| * {@link enumType `graphql.enum`}. You can use the |
| * {@link enumValues `graphql.enumValues`} shorthand to create enum values more easily. |
| * |
| * Note the value property/generic here represents the deserialized form of the |
| * enum. It does not indicate the name of the enum value that is visible in the |
| * GraphQL schema. The value can be anything, not necessarily a string. Usually |
| * though, it will be a string which is equal to the key where the value is used. |
| */ |
|
|
| /** |
| * A shorthand to easily create {@link EnumValue enum values} to pass to |
| * {@link enumType `graphql.enum`}. |
| * |
| * If you need to set a `description` or `deprecationReason` for an enum |
| * variant, you should pass values directly to `graphql.enum` without using |
| * `graphql.enumValues`. |
| * |
| * ```ts |
| * const MyEnum = graphql.enum({ |
| * name: "MyEnum", |
| * values: graphql.enumValues(["a", "b"]), |
| * }); |
| * ``` |
| * |
| * ```ts |
| * const values = graphql.enumValues(["a", "b"]); |
| * |
| * assertDeepEqual(values, { |
| * a: { value: "a" }, |
| * b: { value: "b" }, |
| * }); |
| * ``` |
| */ |
| function enumValues(values) { |
| return Object.fromEntries(values.map(value => [value, { |
| value |
| }])); |
| } |
| /** |
| * Creates an {@link EnumType enum type} with a number of {@link EnumValue enum values}. |
| * |
| * ```ts |
| * const MyEnum = graphql.enum({ |
| * name: "MyEnum", |
| * values: graphql.enumValues(["a", "b"]), |
| * }); |
| * // == |
| * graphql` |
| * enum MyEnum { |
| * a |
| * b |
| * } |
| * `; |
| * ``` |
| * |
| * ```ts |
| * const MyEnum = graphql.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") |
| * } |
| * `;) |
| * ``` |
| */ |
|
|
| function enumType(config) { |
| const graphQLType = new definition.GraphQLEnumType({ |
| name: config.name, |
| description: config.description, |
| extensions: config.extensions, |
| values: config.values |
| }); |
| return { |
| kind: "enum", |
| values: config.values, |
| graphQLType, |
| __context: undefined |
| }; |
| } |
|
|
| /** |
| * Creates a {@link Arg GraphQL argument}. |
| * |
| * Args can can be used as arguments on output fields: |
| * |
| * ```ts |
| * graphql.field({ |
| * type: graphql.String, |
| * args: { |
| * something: graphql.arg({ type: graphql.String }), |
| * }, |
| * resolve(source, { something }) { |
| * return something || somethingElse; |
| * }, |
| * }); |
| * // == |
| * graphql`(something: String): String`; |
| * ``` |
| * |
| * Or as fields on input objects: |
| * |
| * ```ts |
| * const Something = graphql.inputObject({ |
| * name: "Something", |
| * fields: { |
| * something: graphql.arg({ type: graphql.String }), |
| * }, |
| * }); |
| * // == |
| * graphql` |
| * input Something { |
| * something: String |
| * } |
| * `; |
| * ``` |
| */ |
| function arg(arg) { |
| if (!arg.type) { |
| throw new Error("A type must be passed to graphql.arg()"); |
| } |
|
|
| return arg; |
| } |
| /** |
| * Creates an {@link InputObjectType} |
| * |
| * ```ts |
| * const Something = graphql.inputObject({ |
| * name: "Something", |
| * fields: { |
| * something: graphql.arg({ type: graphql.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 |
| * type SomethingInputType = graphql.InputObjectType<{ |
| * something: graphql.Arg<SomethingInputType>; |
| * }>; |
| * const Something: SomethingInputType = graphql.inputObject({ |
| * name: "Something", |
| * fields: () => ({ |
| * something: graphql.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 |
| * const nonCircularFields = { |
| * thing: graphql.arg({ type: graphql.String }), |
| * }; |
| * type SomethingInputType = graphql.InputObjectType< |
| * typeof nonCircularFields & { |
| * something: graphql.Arg<SomethingInputType>; |
| * } |
| * >; |
| * const Something: SomethingInputType = graphql.inputObject({ |
| * name: "Something", |
| * fields: () => ({ |
| * ...nonCircularFields, |
| * something: graphql.arg({ type: Something }), |
| * }), |
| * }); |
| * ``` |
| */ |
|
|
| function inputObject(config) { |
| const fields = config.fields; |
| const graphQLType = new definition.GraphQLInputObjectType({ |
| name: config.name, |
| description: config.description, |
| fields: () => { |
| return Object.fromEntries(Object.entries(typeof fields === "function" ? fields() : fields).map(([key, value]) => [key, { |
| description: value.description, |
| type: value.type.graphQLType, |
| defaultValue: value.defaultValue, |
| deprecationReason: value.deprecationReason |
| }])); |
| } |
| }); |
| return { |
| kind: "input", |
| __fields: undefined, |
| __context: undefined, |
| graphQLType |
| }; |
| } |
|
|
| /** |
| * A GraphQL scalar type which wraps an underlying graphql-js |
| * `GraphQLScalarType` with a type representing the deserialized form of the |
| * scalar. These should be created used {@link scalar `graphql.scalar`}. |
| * |
| * ```ts |
| * const someScalar = graphql.scalar<string>(new GraphQLScalarType({})); |
| * |
| * // for fields on output types |
| * graphql.field({ type: someScalar }); |
| * |
| * // for args on output fields or fields on input types |
| * graphql.arg({ type: someScalar }); |
| * ``` |
| */ |
|
|
| /** |
| * Creates a {@link ScalarType} from a graphql-js {@link GraphQLScalarType}. |
| * |
| * You should provide a type as a type parameter which is the type of the scalar |
| * value. 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. |
| * |
| * ```ts |
| * const JSON = graphql.scalar<JSONValue>(GraphQLJSON); |
| * // for fields on output types |
| * graphql.field({ type: someScalar }); |
| * |
| * // for args on output fields or fields on input types |
| * graphql.arg({ type: someScalar }); |
| * ``` |
| */ |
| function scalar(scalar) { |
| return { |
| kind: "scalar", |
| __type: undefined, |
| __context: undefined, |
| graphQLType: scalar |
| }; |
| } |
| const ID = scalar(scalars.GraphQLID); |
| const String = scalar(scalars.GraphQLString); |
| const Float = scalar(scalars.GraphQLFloat); |
| const Int = scalar(scalars.GraphQLInt); |
| const Boolean = scalar(scalars.GraphQLBoolean); |
|
|
| /** |
| * Wraps any GraphQL type in a {@link ListType}. |
| * |
| * ```ts |
| * const stringListType = graphql.list(graphql.String); |
| * // == |
| * graphql`[String]`; |
| * ``` |
| * |
| * When used as an input type, you will recieve an array of the inner type. |
| * |
| * ```ts |
| * graphql.field({ |
| * type: graphql.String, |
| * args: { thing: graphql.arg({ type: graphql.list(graphql.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 |
| * graphql.field({ |
| * type: graphql.list(graphql.String), |
| * resolve() { |
| * return [""]; |
| * }, |
| * }); |
| * ``` |
| * |
| * ```ts |
| * graphql.field({ |
| * type: graphql.list(graphql.String), |
| * resolve() { |
| * return new Set([""]); |
| * }, |
| * }); |
| * ``` |
| * |
| * ```ts |
| * graphql.field({ |
| * type: graphql.list(graphql.String), |
| * resolve() { |
| * // this will not be allowed |
| * return "some things"; |
| * }, |
| * }); |
| * ``` |
| */ |
| function list(of) { |
| return { |
| kind: "list", |
| of, |
| __context: of["__context"], |
| graphQLType: new definition.GraphQLList(of.graphQLType) |
| }; |
| } |
| /** |
| * Wraps a {@link NullableType} with a non-null type. |
| * |
| * See the documentation for {@link nonNull `graphql.nonNull`} for more information. |
| */ |
|
|
| /** |
| * Wraps a {@link NullableType} with a {@link NonNullType}. |
| * |
| * 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 = graphql.nonNull(graphql.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 |
| * graphql.field({ |
| * args: { |
| * someNonNullAndRequiredArg: graphql.arg({ |
| * type: graphql.nonNull(graphql.String), |
| * }), |
| * someNonNullButOptionalArg: graphql.arg({ |
| * type: graphql.nonNull(graphql.String), |
| * defaultValue: "some default", |
| * }), |
| * }, |
| * type: graphql.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 |
| * graphql.field({ |
| * type: graphql.nonNull(graphql.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 'TypesExcludingNonNull'. |
| * graphql.nonNull(graphql.nonNull(graphql.String)); |
| * ``` |
| */ |
| function nonNull(of) { |
| return { |
| kind: "non-null", |
| of, |
| __context: of["__context"], |
| graphQLType: new definition.GraphQLNonNull(of.graphQLType) |
| }; |
| } |
|
|
| exports.Boolean = Boolean; |
| exports.Float = Float; |
| exports.ID = ID; |
| exports.Int = Int; |
| exports.String = String; |
| exports.arg = arg; |
| exports.enumType = enumType; |
| exports.enumValues = enumValues; |
| exports.inputObject = inputObject; |
| exports.list = list; |
| exports.nonNull = nonNull; |
| exports.scalar = scalar; |