From cd2accb1359bec40adae242abe6e9670e041f2f9 Mon Sep 17 00:00:00 2001 From: lorefnon Date: Thu, 8 Feb 2024 00:11:59 +0530 Subject: [PATCH 1/2] Add support to augment types with internal properties --- src/index.ts | 100 ++++++++++++++++++++++++++++++++++----------------- src/utils.ts | 1 + 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2a19466..758ffd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -84,28 +84,59 @@ type InferResolverConfig = { } type InferOptions = { + internal: boolean omitResolver?: AnyOmitResolver | never } type RefType = () => AnyType // TODO: Refactor Args to get rid of this mess -export type Infer = ExpandRecursively> -export type InferRaw = T extends AnyInput | AnyObject | AnyInterface ? { +export type Infer = ExpandRecursively> + +export type InferInternal = Infer + +type AnyNested = AnyInput | AnyObject | AnyInterface + +export type InferRaw = T extends AnyNested ? InferNested : InferShallow + +type IsOmitable = + T['_shape'][K] extends AnyOptional | options['omitResolver'] ? true : + T['_shape'][K] extends AnyArgs ? + T['_shape'][K]['_shape'] extends AnyOptional | options['omitResolver'] ? true : false : + false + +type InferNested = { __typename?: T['_name'] } & { - [K in keyof T['_shape'] as T['_shape'][K] extends AnyOptional | options['omitResolver'] ? never : - T['_shape'][K] extends AnyArgs ? - T['_shape'][K]['_shape'] extends AnyOptional | options['omitResolver'] ? never : K : - K]: InferRaw + [K in keyof T['_shape'] as ( + IsOmitable extends true + ? never + : K + )]: InferRaw } & { - [K in keyof T['_shape'] as T['_shape'][K] extends AnyOptional | options['omitResolver'] ? K : - T['_shape'][K] extends AnyArgs ? - T['_shape'][K]['_shape'] extends AnyOptional | options['omitResolver'] ? K : never : - never]?: InferRaw -} : InferShallow - -export type InferShallow = + [K in keyof T['_shape'] as ( + IsOmitable extends true + ? K + : never + )]?: InferRaw +} & ( + T extends GType + ? options["internal"] extends true + ? E + : {} + : {} +) + +export type InferShallow = T extends AnyString | AnyID | AnyScalar | AnyNumber | AnyBoolean ? T['_shape'] : T extends AnyEnum ? T['_inner'] : T extends AnyUnion ? InferRaw, options> : @@ -134,49 +165,50 @@ export type InferUnionNames = T extends AnyUnion ? ObjectToUnion export type InferResolvers = { [K in keyof T]: K extends 'Subscription' ? { [G in keyof T[K]['_shape']]?: { - subscribe: (parent: {}, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise }>> - resolve?: (value: Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> + subscribe: (parent: {}, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise }>> + resolve?: (value: InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> } } : { - [G in keyof T[K]['_shape']]?: (parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise>> | AsyncGenerator> + [G in keyof T[K]['_shape']]?: (parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise>> | AsyncGenerator> } | { [G in keyof T[K]['_shape']]?: { - resolve: (parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> | AsyncGenerator> + resolve: (parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> | AsyncGenerator> } | { - load: (queries: { parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise[]> + load: (queries: { parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise[]> } | { - loadBatch: (queries: { parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise[]> + loadBatch: (queries: { parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise[]> } } & { - __isTypeOf?: (parent: Infer, context: X['context'], info: GraphQLResolveInfo) => MaybePromise - __resolveType?: (parent: Infer, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> + __isTypeOf?: (parent: InferInternal, context: X['context'], info: GraphQLResolveInfo) => MaybePromise + __resolveType?: (parent: InferInternal, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> } } export type InferResolversStrict = { [K in keyof T]: K extends 'Subscription' ? { [G in keyof T[K]['_shape']]: { - subscribe: (parent: {}, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise }>> - resolve?: (value: Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> + subscribe: (parent: {}, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise }>> + resolve?: (value: InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> } } : { - [G in keyof T[K]['_shape']]: (parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise>> | AsyncGenerator> + [G in keyof T[K]['_shape']]: (parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise>> | AsyncGenerator> } | { [G in keyof T[K]['_shape']]: { - resolve: (parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> | AsyncGenerator> + resolve: (parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> | AsyncGenerator> } | { - load: (queries: { parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise>[] + load: (queries: { parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise>[] } | { - loadBatch: (queries: { parent: K extends GraphQLRootType ? {} : Infer, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise>[] + loadBatch: (queries: { parent: K extends GraphQLRootType ? {} : InferInternal, args: InferArg, context: X['context'], info: GraphQLResolveInfo } []) => MaybePromise>[] } } & { - __isTypeOf?: (parent: Infer, context: X['context'], info: GraphQLResolveInfo) => MaybePromise - __resolveType?: (parent: Infer, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> + __isTypeOf?: (parent: InferInternal, context: X['context'], info: GraphQLResolveInfo) => MaybePromise + __resolveType?: (parent: InferInternal, context: X['context'], info: GraphQLResolveInfo) => MaybePromise> } } -class GType extends Type { +class GType extends Type { declare _name: N + declare _ext: E constructor(name: string, shape: T, interfaces?: AnyInterface[], extend?: AnyTypes[]) { super() @@ -192,13 +224,17 @@ class GType extends Type implements(ref: D | D[]) { // This is temporary construct, until we figure out how to properly manage to shared schema this.typeDef.interfaces = Array.isArray(ref) ? ref : [ref] - return new GType>(this.typeDef.name, this.typeDef.shape as any, Array.isArray(ref) ? ref : [ref], this.typeDef.extend) + return new GType, E>(this.typeDef.name, this.typeDef.shape as any, Array.isArray(ref) ? ref : [ref], this.typeDef.extend) } extend(ref: D | D[]) { // This is temporary construct, until we figure out how to properly manage to shared schema this.typeDef.extend = Array.isArray(ref) ? ref : [ref] - return new GType>(this.typeDef.name, this.typeDef.shape as any, this.typeDef.interfaces, Array.isArray(ref) ? ref : [ref]) + return new GType, E>(this.typeDef.name, this.typeDef.shape as any, this.typeDef.interfaces, Array.isArray(ref) ? ref : [ref]) + } + + augment() { + return new GType(this.typeDef.name, this.typeDef.shape as any, this.typeDef.interfaces, this.typeDef.extend) } } diff --git a/src/utils.ts b/src/utils.ts index 20a6e4b..9813a7a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -21,3 +21,4 @@ export type ExpandRecursively ? T extends infer O ? { [K in keyof O]: ExpandRecursively } : never : T + From 60c6b2920157007f26a5dd870bcc877ee715e030 Mon Sep 17 00:00:00 2001 From: lorefnon Date: Thu, 8 Feb 2024 00:11:59 +0530 Subject: [PATCH 2/2] Update loader example to also use internal properties --- examples/loader.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/loader.ts b/examples/loader.ts index 8dbb890..579d906 100644 --- a/examples/loader.ts +++ b/examples/loader.ts @@ -5,16 +5,15 @@ import { createServer } from 'http' const Dog = g.type('Dog', { name: g.string(), owner: g.string().omitResolver() -}) +}).augment<{ + id: number +}>() const queryType = g.type('Query', { dogs: g.ref(() => Dog).list() }) -const owners = { - Apollo: 'Mish', - Buddy: 'Sebastian' -} +const owners = ['Mish', 'Sebastian'] type resolverTypes = InferResolvers<{ Query: typeof queryType, Dog: typeof Dog }, {}> @@ -23,9 +22,11 @@ const resolvers: resolverTypes = { dogs: (parent, args, context, info) => { return [ { + id: 0, name: 'Apollo', }, { + id: 1, name: 'Buddy', } ] @@ -36,7 +37,7 @@ const resolvers: resolverTypes = { load (queries) { return new Promise(resolve => { setTimeout(() => { - resolve(queries.map(q => owners[q.parent.name])) + resolve(queries.map(q => owners[q.parent.id])) }, 1000) }) }