diff --git a/packages/extend/src/extend.test.ts b/packages/extend/src/extend.test.ts index 47b6739..c6c908d 100644 --- a/packages/extend/src/extend.test.ts +++ b/packages/extend/src/extend.test.ts @@ -419,7 +419,7 @@ test("using an existing object type", () => { `); }); -test("errors when no type ", () => { +test("errors when no type exists with that name", () => { expect(() => { extend((base) => ({ query: { @@ -525,7 +525,9 @@ test(".scalar works for custom scalars", () => { }, }), }); - const extended = extend((base) => ({ + const extended = extend<{ + Something: typeof Something; + }>((base) => ({ query: { hello: g.field({ type: base.scalar("Something"), diff --git a/packages/extend/src/index.ts b/packages/extend/src/index.ts index 5b65e66..505ef17 100644 --- a/packages/extend/src/index.ts +++ b/packages/extend/src/index.ts @@ -26,18 +26,24 @@ import { parse, ObjectTypeDefinitionNode, print, + GraphQLInterfaceType, + GraphQLInputObjectType, + GraphQLUnionType, + GraphQLScalarType, } from "graphql"; import { GField, GObjectType, - GArg, GEnumType, GUnionType, GInterfaceType, GScalarType, GOutputType, GInputObjectType, + GInputType, + GArg, + GInterfaceField, } from "@graphql-ts/schema"; const builtinScalars = new Set(specifiedScalarTypes.map((x) => x.name)); @@ -91,11 +97,11 @@ const builtinScalars = new Set(specifiedScalarTypes.map((x) => x.name)); * } * ``` */ -export function extend( +export function extend>( extension: | Extension | readonly Extension[] - | ((base: BaseSchemaMeta) => Extension | readonly Extension[]) + | ((base: BaseSchemaMeta) => Extension | readonly Extension[]) ): (schema: GraphQLSchema) => GraphQLSchema { return (schema) => { const getType = (name: string) => { @@ -113,8 +119,11 @@ export function extend( typeof extension === "function" ? extension({ schema, + all(name) { + return getType(name as string) as any; + }, object(name) { - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isObjectType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -122,10 +131,10 @@ export function extend( )} in the schema being extended but it is not an object type` ); } - return graphQLType; + return graphQLType as any; }, inputObject(name) { - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isInputObjectType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -133,10 +142,10 @@ export function extend( )} in the schema being extended but it is not an input object type` ); } - return graphQLType; + return graphQLType as any; }, enum(name) { - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isEnumType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -144,10 +153,10 @@ export function extend( )} in the schema being extended but it is not an enum type` ); } - return graphQLType; + return graphQLType as any; }, interface(name) { - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isInterfaceType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -155,15 +164,17 @@ export function extend( )} in the schema being extended but it is not an interface type` ); } - return graphQLType; + return graphQLType as any; }, scalar(name) { - if (builtinScalars.has(name)) { + if (builtinScalars.has(name as string)) { throw new Error( - `The names of built-in scalars cannot be passed to BaseSchemaInfo.scalar but ${name} was passed` + `The names of built-in scalars cannot be passed to BaseSchemaInfo.scalar but ${ + name as string + } was passed` ); } - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isScalarType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -171,10 +182,10 @@ export function extend( )} in the schema being extended but it is not a scalar type` ); } - return graphQLType; + return graphQLType as any; }, union(name) { - const graphQLType = getType(name); + const graphQLType = getType(name as string); if (!isUnionType(graphQLType)) { throw new Error( `There is a type named ${JSON.stringify( @@ -182,7 +193,7 @@ export function extend( )} in the schema being extended but it is not a union type` ); } - return graphQLType; + return graphQLType as any; }, }) : extension @@ -426,12 +437,39 @@ export type Extension = { // unreferencedConcreteInterfaceImplementations?: ObjectType[]; }; +export type NamedType = + | GObjectType + | GInputObjectType<{ [key: string]: GArg }> + | GEnumType> + | GUnionType + | GInterfaceType< + unknown, + Record, unknown>>, + unknown + > + | GScalarType; + +export type NamedTypes = Record; + +type TypeOfKind, Constraint> = { + [K in keyof Types]: Extract extends never ? never : K; +}[keyof Types]; + /** * This object contains the schema being extended and functions to get GraphQL * types from the schema. */ -export type BaseSchemaMeta = { +export type BaseSchemaMeta< + Types extends Record = NamedTypes, +> = { schema: GraphQLSchema; + all< + Name extends { + [K in keyof Types]: string extends K ? never : K; + }[keyof Types], + >( + name: Name + ): Types[Name]; /** * Gets an {@link GObjectType object type} from the existing GraphQL schema. If * there is no object type in the existing schema with the name passed, an @@ -452,7 +490,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - object(name: string): GObjectType; + object>( + name: Name + ): Extract; /** * Gets an {@link GInputObjectType input object type} from the existing GraphQL * schema. If there is no input object type in the existing schema with the @@ -479,9 +519,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - inputObject( - name: string - ): GInputObjectType<{ [key: string]: GArg }, boolean>; + inputObject>( + name: Name + ): Extract; /** * Gets an {@link GEnumType enum type} from the existing GraphQL schema. If * there is no enum type in the existing schema with the name passed, an error @@ -507,7 +547,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - enum(name: string): GEnumType>; + enum>>( + name: Name + ): Extract>; /** * Gets a {@link GUnionType union type} from the existing GraphQL schema. If * there is no union type in the existing schema with the name passed, an @@ -528,7 +570,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - union(name: string): GUnionType; + union>( + name: Name + ): Extract; /** * Gets an {@link GInterfaceType interface type} from the existing GraphQL * schema. If there is no interface type in the existing schema with the name @@ -549,7 +593,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - interface(name: string): GInterfaceType; + interface>( + name: Name + ): Extract; /** * Gets a {@link GScalarType scalar type} from the existing GraphQL schema. If * there is no scalar type in the existing schema with the name passed, an @@ -578,7 +624,9 @@ export type BaseSchemaMeta = { * }))(originalSchema); * ``` */ - scalar(name: string): GScalarType; + scalar>>( + name: Name + ): Extract>; }; function findObjectTypeUsages(