diff --git a/packages/extend/src/extend.test.ts b/packages/extend/src/extend.test.ts index a8dbc3c..47b6739 100644 --- a/packages/extend/src/extend.test.ts +++ b/packages/extend/src/extend.test.ts @@ -4,9 +4,12 @@ import { graphqlSync, printSchema, } from "graphql"; -import { g } from "@graphql-ts/schema"; +import { gWithContext } from "@graphql-ts/schema"; import { extend } from "."; +const g = gWithContext(); +type g = gWithContext.infer; + const getGql = (schema: GraphQLSchema) => ([source]: TemplateStringsArray) => @@ -162,7 +165,7 @@ test("basic mutation with existing mutations", () => { }); test("errors when query type is used elsewhere in schema", () => { - const Query: g.ObjectType<{}> = g.object<{}>()({ + const Query: g> = g.object<{}>()({ name: "Query", fields: () => ({ thing: g.field({ @@ -200,7 +203,7 @@ test("errors when query type is used elsewhere in schema", () => { }); test("errors when query and mutation type is used elsewhere in schema", () => { - const Query: g.ObjectType<{}> = g.object<{}>()({ + const Query: g> = g.object<{}>()({ name: "Query", fields: () => ({ thing: g.field({ @@ -211,7 +214,7 @@ test("errors when query and mutation type is used elsewhere in schema", () => { }), }), }); - const Mutation: g.ObjectType<{}> = g.object<{}>()({ + const Mutation: g> = g.object<{}>()({ name: "Mutation", fields: () => ({ thing: g.field({ @@ -250,7 +253,7 @@ test("errors when query and mutation type is used elsewhere in schema", () => { }); test("errors when query and mutation type is used elsewhere in schema", () => { - const Query: g.ObjectType<{}> = g.object<{}>()({ + const Query: g> = g.object<{}>()({ name: "Query", fields: () => ({ thing: g.field({ @@ -273,7 +276,7 @@ test("errors when query and mutation type is used elsewhere in schema", () => { }), }), }); - const Mutation: g.ObjectType<{}> = g.object<{}>()({ + const Mutation: g> = g.object<{}>()({ name: "Mutation", fields: () => ({ thing: g.field({ diff --git a/packages/extend/src/index.ts b/packages/extend/src/index.ts index 2233671..5b65e66 100644 --- a/packages/extend/src/index.ts +++ b/packages/extend/src/index.ts @@ -29,7 +29,6 @@ import { } from "graphql"; import { - g, GField, GObjectType, GArg, @@ -323,13 +322,13 @@ function flattenExtensions( `More than one extension defines a field named ${JSON.stringify( key )} on the ${operation} type.\nThe first field:\n${printFieldOnType( - g.object()({ + new GObjectType({ name: "ForError", fields: { [key]: val }, }), key )}\nThe second field:\n${printFieldOnType( - g.object()({ + new GObjectType({ name: "ForError", fields: { [key]: resolvedExtension[operation][key] }, }), diff --git a/packages/schema/src/g-for-doc-references.ts b/packages/schema/src/g-for-doc-references.ts new file mode 100644 index 0000000..b5365d2 --- /dev/null +++ b/packages/schema/src/g-for-doc-references.ts @@ -0,0 +1,3 @@ +import { GWithContext } from "./output"; + +export declare const g: GWithContext; diff --git a/packages/schema/src/output.ts b/packages/schema/src/output.ts index 942e41b..3374fc9 100644 --- a/packages/schema/src/output.ts +++ b/packages/schema/src/output.ts @@ -11,11 +11,6 @@ import type { InferValueFromArgs, InferValueFromInputType, } from "./api-without-context"; -import type { - object, - field, - interface as interfaceFunc, -} from "./api-with-context"; import { GArg, GEnumType, @@ -46,12 +41,7 @@ import { GraphQLFloat, GraphQLString, } from "graphql"; - -export type __toMakeTypeScriptEmitImportsForItemsOnlyUsedInJSDoc = [ - typeof interfaceFunc, - typeof field, - typeof object, -]; +import type { g } from "./g-for-doc-references"; type SomeTypeThatIsntARecordOfArgs = string; @@ -399,7 +389,7 @@ export type GWithContext = { * Creates a GraphQL interface field. * * These will generally be passed directly to the `fields` object in a - * {@link interfaceFunc `g.interface`} call. Interfaces fields are similar to + * {@link g.interface} call. Interfaces fields are similar to * {@link GField regular fields} except that they **don't define how the field * is resolved**. * @@ -531,7 +521,7 @@ export type GWithContext = { ) => GInterfaceType; /** * A shorthand to easily create {@link GEnumValueConfig enum values} to pass to - * {@link enumType `g.enum`}. + * {@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 diff --git a/packages/schema/src/types.d.ts b/packages/schema/src/types.d.ts index 28b2a15..1e94fce 100644 --- a/packages/schema/src/types.d.ts +++ b/packages/schema/src/types.d.ts @@ -29,18 +29,7 @@ import { type FieldDefinitionNode, type InputValueDefinitionNode, } from "graphql"; -import type { - field, - union, - interface as interface_, - object, -} from "./api-with-context"; -import type { - scalar, - enum as enum_, - inputObject, - arg, -} from "./api-without-context"; +import type { g } from "./g-for-doc-references"; type Maybe = T | null | undefined; @@ -173,7 +162,7 @@ export type InferValueFromInputType = /** * A GraphQL output field for an {@link GObjectType object type} which should be - * created using {@link field `g.field`}. + * created using {@link g.field}. */ export type GField< Source, @@ -194,7 +183,7 @@ export type GField< /** * A GraphQL object type. This should generally be constructed with - * {@link object `g.object`}. + * {@link g.object}. * * Note this is an **output** type, if you want an input object, use * {@link GInputObjectType}. @@ -230,7 +219,7 @@ export type GObjectTypeConfig< /** * A GraphQL union type. This should generally be constructed with - * {@link union `g.union`}. + * {@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 @@ -285,7 +274,7 @@ export type GInterfaceField< /** * A GraphQL interface type that can be implemented by other * {@link GObjectType GraphQL object} and interface types. This should generally - * be constructed with {@link interface_ `g.interface`}. + * 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. @@ -330,7 +319,7 @@ export type GInterfaceTypeConfig< >; /** - * A GraphQL argument. These should be created with {@link arg `g.arg`} + * A GraphQL argument. These should be created with {@link g.arg} * * Args can can be used as arguments on output fields: * @@ -388,7 +377,10 @@ export type GArg< HasDefaultValue extends boolean = boolean, > = { type: Type; - defaultValue: HasDefaultValue extends true ? {} | null : undefined; + defaultValue: { + true: {} | null; + false: undefined; + }[`${HasDefaultValue}`]; description?: Maybe; deprecationReason?: Maybe; extensions?: Maybe; @@ -412,7 +404,7 @@ export type GInputObjectTypeConfig< /** * A GraphQL input object type. This should generally be constructed with - * {@link inputObject `g.inputObject`}. + * {@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 @@ -450,8 +442,7 @@ export type GEnumTypeConfig = >; /** - * A GraphQL enum type. This should generally be constructed with - * {@link enum_ `g.enum`}. + * 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 @@ -470,7 +461,7 @@ export class GEnumType< /** * A GraphQL enum type. This should generally be constructed with - * {@link scalar `g.scalar`}. + * {@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 @@ -491,7 +482,7 @@ type Flatten = { /** * A GraphQL non-null type. This should generally be constructed with - * {@link enum_ `g.nonNull`}. + * {@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 @@ -528,8 +519,7 @@ export class GNonNull< } /** - * A GraphQL list type. This should generally be constructed with - * {@link list `g.list`}. + * 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 diff --git a/test-project/index.test-d.ts b/test-project/index.test-d.ts index ed23da4..dffb419 100644 --- a/test-project/index.test-d.ts +++ b/test-project/index.test-d.ts @@ -1,15 +1,7 @@ import { - g, gWithContext, - Arg, InferValueFromInputType, - InputObjectType, - ScalarType, InferValueFromOutputType, - graphql, - OutputType, - Field, - InputType, InferValueFromArgs, GArg, GEnumType, @@ -21,9 +13,11 @@ import { GObjectType, GScalarType, GUnionType, + InferValueFromArg, + GOutputType, + GField, } from "@graphql-ts/schema"; import { extend } from "@graphql-ts/extend"; -import * as boundG from "./schema-api"; import { GraphQLEnumType, GraphQLFieldExtensions, @@ -42,8 +36,11 @@ function expectType(type: T) { console.log(type); } -boundG.arg({ - type: boundG.Boolean, +const g = gWithContext(); +type g = gWithContext.infer; + +g.arg({ + type: g.Boolean, }); const someEnum = g.enum({ @@ -74,8 +71,8 @@ const Something = g.inputObject({ }, }); -type CircularInputType = g.InputObjectType<{ - circular: g.Arg; +type CircularInputType = GInputObjectType<{ + circular: GArg; }>; const Circular: CircularInputType = g.inputObject({ @@ -107,24 +104,24 @@ function useType(a?: T) { { // should be unknown for G* types but for GraphQLOutputType, it is any - type a = g.InferValueFromOutputType; + type a = InferValueFromOutputType>; useType(); } { // should be unknown - type a = g.InferValueFromInputType; + type a = InferValueFromInputType; useType(); - type b = g.InferValueFromArg>; + type b = InferValueFromArg>; useType(); // should be { readonly a: unknown } - type c = g.InferValueFromArgs<{ a: g.Arg }>; + type c = InferValueFromArgs<{ a: GArg }>; useType(); } { - type RecursiveInput = InputObjectType<{ - nullableString: Arg>; - recursive: Arg; + type RecursiveInput = GInputObjectType<{ + nullableString: GArg>; + recursive: GArg; }>; const Recursive: RecursiveInput = g.inputObject({ @@ -152,9 +149,9 @@ function useType(a?: T) { nullableString: g.arg({ type: g.String }), }; - type RecursiveInput = InputObjectType< + type RecursiveInput = GInputObjectType< typeof nonRecursiveFields & { - recursive: Arg; + recursive: GArg; } >; @@ -180,8 +177,8 @@ function useType(a?: T) { // TODO: if possible, this should error. not really a massive deal if it doesn't though tbh // since if people forget to add something here, they will see an error when they try to read a field that doesn't exist -export const ExplicitDefinitionMissingFieldsThatAreSpecifiedInCalls: InputObjectType<{ - nullableString: Arg; +export const ExplicitDefinitionMissingFieldsThatAreSpecifiedInCalls: GInputObjectType<{ + nullableString: GArg; }> = g.inputObject({ name: "ExplicitDefinitionMissingFieldsThatAreSpecifiedInCalls", fields: () => ({ @@ -672,7 +669,7 @@ g.fields<{ thing: Promise }>()({ type: g.String, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -682,7 +679,7 @@ g.fields<{ thing: Promise }>()({ defaultValue: undefined, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -692,7 +689,7 @@ g.fields<{ thing: Promise }>()({ defaultValue: "", }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -702,7 +699,7 @@ g.fields<{ thing: Promise }>()({ defaultValue: null, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -712,7 +709,7 @@ g.fields<{ thing: Promise }>()({ defaultValue: null, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -722,7 +719,7 @@ g.fields<{ thing: Promise }>()({ defaultValue: Math.random() > 0.5 ? "" : null, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); } @@ -739,20 +736,20 @@ g.fields<{ thing: Promise }>()({ defaultValue: "", } : {}; - const arg = g.arg({ + const arg: GArg = g.arg({ type: g.String, ...x, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); // @ts-expect-error - const _assert1: g.Arg = arg; + const _assert1: GArg = arg; console.log(_assert1); // @ts-expect-error - const _assert2: g.Arg = arg; + const _assert2: GArg = arg; console.log(_assert2); - const _assert3: (x: g.Arg) => void = ( + const _assert3: (x: GArg) => void = ( x: typeof arg ) => { console.log(x); @@ -776,13 +773,13 @@ g.fields<{ thing: Promise }>()({ ...x, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); // @ts-expect-error - const _assert1: g.Arg = arg; + const _assert1: GArg = arg; console.log(_assert1); // @ts-expect-error - const _assert2: g.Arg = arg; + const _assert2: GArg = arg; console.log(_assert2); } @@ -801,13 +798,13 @@ g.fields<{ thing: Promise }>()({ type: g.String, ...x, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); // @ts-expect-error - const _assert1: g.Arg = arg; + const _assert1: GArg = arg; console.log(_assert1); // @ts-expect-error - const _assert2: g.Arg = arg; + const _assert2: GArg = arg; console.log(_assert2); } @@ -819,13 +816,13 @@ g.fields<{ thing: Promise }>()({ ...thing, }); - const _assert: g.Arg = arg; + const _assert: GArg = arg; console.log(_assert); // @ts-expect-error - const _assert1: g.Arg = arg; + const _assert1: GArg = arg; console.log(_assert1); // @ts-expect-error - const _assert2: g.Arg = arg; + const _assert2: GArg = arg; console.log(_assert2); } @@ -897,7 +894,7 @@ g.object<{ thing: () => Promise }>()({ }) ); // @ts-expect-error - const thing3: g.InputType = g.nonNull( + const thing3: GInputType = g.nonNull( g.object()({ name: "something", fields: {}, @@ -1139,38 +1136,6 @@ function assertCompatible() {} }); } -// just to ensure the old alias works -{ - graphql.object()({ - name: "Query", - fields: { - hello: g.field({ - type: g.String, - resolve() { - return "something"; - }, - }), - }, - }); - const Something: graphql.ObjectType<{}> = graphql.object<{}>()({ - name: "Something", - fields: () => ({ - a: graphql.field({ - type: Something, - resolve() { - return {}; - }, - }), - b: graphql.field({ - type: graphql.String, - resolve() { - return "something"; - }, - }), - }), - }); -} - const someInputFields = { a: g.arg({ type: g.String }), b: g.arg({ type: g.String }), @@ -1183,7 +1148,7 @@ const someInputFields = { isOneOf: true, }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); g.field({ @@ -1218,7 +1183,7 @@ const someInputFields = { isOneOf: Math.random() > 0.5, }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); g.field({ @@ -1257,7 +1222,7 @@ const someInputFields = { }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); @@ -1288,7 +1253,7 @@ const someInputFields = { }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1300,7 +1265,7 @@ const someInputFields = { }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1340,7 +1305,7 @@ const someInputFields = { isOneOf: true, }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1352,7 +1317,7 @@ const someInputFields = { isOneOf: false, }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1364,7 +1329,7 @@ const someInputFields = { isOneOf: Math.random() > 0.5, }); assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1392,7 +1357,7 @@ const someInputFields = { // this would also be banned under exactOptionalPropertyTypes // which again feels conceptually correct rather than banning when not using exactOptionalPropertyTypes assertCompatible< - Invariant>, + Invariant>, Invariant >(); } @@ -1503,13 +1468,14 @@ const someInputFields = { }); assertCompatible< Invariant< - g.UnionType< + GUnionType< | { __typename: "A"; } | { __typename: "B"; - } + }, + unknown > >, Invariant @@ -1557,10 +1523,10 @@ const someInputFields = { }; { // this error is somewhat unfortunate but it's not a big deal imo - // what's going on is that InputType includes InputObjectType + // what's going on is that InputType includes GInputObjectType // so IsOneOf is inferred as boolean // which makes the isOneOf property required (though it can be false) - const a: g.InputType = g.inputObject( + const a: GInputType = g.inputObject( // @ts-expect-error { name: "Something", @@ -1570,7 +1536,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, isOneOf: false, @@ -1578,14 +1544,14 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, }); console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, isOneOf: false, @@ -1593,7 +1559,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject( + const a: GInputType = g.inputObject( // @ts-expect-error { name: "Something", @@ -1603,7 +1569,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, isOneOf: true, @@ -1611,7 +1577,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, isOneOf: true, @@ -1619,7 +1585,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, // @ts-expect-error @@ -1628,7 +1594,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject( + const a: GInputType = g.inputObject( // @ts-expect-error { name: "Something", @@ -1638,7 +1604,7 @@ const someInputFields = { console.log(a); } { - const a: g.InputType = g.inputObject({ + const a: GInputType = g.inputObject({ name: "Something", fields, isOneOf: Math.random() > 0.5, @@ -1743,10 +1709,10 @@ const someInputFields = { x?: any; }; - let discriminantField!: Field< + let discriminantField!: GField< { value: unknown }, - Record>, - OutputType, + Record>, + GOutputType, unknown, Context >; @@ -1962,9 +1928,9 @@ const someInputFields = { { type ImpliedResolver< Args extends { - [Key in keyof Args]: Arg; + [Key in keyof Args]: GArg; }, - Type extends OutputType>, + Type extends GOutputType>, Context extends MyContext, > = | InferValueFromOutputType @@ -1981,12 +1947,12 @@ const someInputFields = { type SomeTypeThatIsntARecordOfArgs = string; const field: < Source, - Type extends OutputType>, + Type extends GOutputType>, Resolve extends | undefined | (( source: Source, - args: g.InferValueFromArgs< + args: InferValueFromArgs< SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args >, context: Context, @@ -1994,7 +1960,7 @@ const someInputFields = { ) => InferValueFromOutputType), Context extends MyContext, Args extends { - [Key in keyof Args]: Arg; + [Key in keyof Args]: GArg; } = {}, >( field: { @@ -2026,7 +1992,7 @@ const someInputFields = { ) => InferValueFromOutputType) & Resolve; }) - ) => Field< + ) => GField< Source, Args, Type, @@ -2056,8 +2022,8 @@ const someInputFields = { } { - const something: g.InputObjectType<{ - [key: string]: g.Arg; + const something: GInputObjectType<{ + [key: string]: GArg; }> = undefined as any; const x = Math.random() > 0.5 ? { id: { equals: "1" } } : {}; const a = g.arg({ @@ -2065,7 +2031,7 @@ const someInputFields = { defaultValue: x, }); assertCompatible< - Invariant, true>>, + Invariant, true>>, Invariant >(); } diff --git a/test-project/runtime.test.ts b/test-project/runtime.test.ts index 9f57990..29f6ed5 100644 --- a/test-project/runtime.test.ts +++ b/test-project/runtime.test.ts @@ -1,6 +1,9 @@ -import { g } from "@graphql-ts/schema"; +import { gWithContext } from "@graphql-ts/schema"; import { GraphQLSchema, graphql } from "graphql"; +const g = gWithContext(); +type g = gWithContext.infer; + test("a basic schema works", async () => { const Query = g.object()({ name: "Query", diff --git a/test-project/schema-api/index.ts b/test-project/schema-api/index.ts deleted file mode 100644 index 543ee37..0000000 --- a/test-project/schema-api/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as graphqltsSchema from "@graphql-ts/schema"; -export * from "@graphql-ts/schema/api-without-context"; -export { - field, - fields, - interface, - interfaceField, - object, - union, -} from "./output-types"; - -export type Context = unknown; - -export type NullableType = graphqltsSchema.NullableType; -export type Type = graphqltsSchema.Type; -export type NullableOutputType = graphqltsSchema.NullableOutputType; -export type OutputType = graphqltsSchema.OutputType; -export type Field< - Source, - Args extends Record>, - TType extends OutputType, - SourceAtKey, -> = graphqltsSchema.Field; -export type FieldResolver< - Source, - Args extends Record>, - TType extends OutputType, -> = graphqltsSchema.FieldResolver; -export type ObjectType = graphqltsSchema.ObjectType; -export type UnionType = graphqltsSchema.UnionType; -export type InterfaceType< - Source, - Fields extends Record< - string, - graphqltsSchema.InterfaceField - >, -> = graphqltsSchema.InterfaceType; -export type InterfaceField< - Args extends Record>, - TType extends OutputType, -> = graphqltsSchema.InterfaceField; diff --git a/test-project/schema-api/output-types.d.ts b/test-project/schema-api/output-types.d.ts deleted file mode 100644 index de94a6b..0000000 --- a/test-project/schema-api/output-types.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { GWithContext } from "@graphql-ts/schema"; -import { Context } from "."; - -declare const __graphql: GWithContext; - -export = __graphql; diff --git a/test-project/schema-api/output-types.js b/test-project/schema-api/output-types.js deleted file mode 100644 index 66119e6..0000000 --- a/test-project/schema-api/output-types.js +++ /dev/null @@ -1 +0,0 @@ -export * from "@graphql-ts/schema/api-with-context";