diff --git a/packages/plugin-dataloader/src/schema-builder.ts b/packages/plugin-dataloader/src/schema-builder.ts index e8c279cc7..6246ce15a 100644 --- a/packages/plugin-dataloader/src/schema-builder.ts +++ b/packages/plugin-dataloader/src/schema-builder.ts @@ -1,6 +1,8 @@ +import type { GraphQLResolveInfo } from 'graphql'; import SchemaBuilder, { InterfaceParam, ObjectParam, + OutputRef, PothosSchemaError, SchemaTypes, ShapeFromTypeParam, @@ -159,7 +161,37 @@ schemaBuilderProto.loadableNode = function loadableNode< options, ); - ref.implement(options); + // ref.implement(options); + ref.implement({ + ...options, + isTypeOf: + options.isTypeOf ?? + (typeof nameOrRef === 'function' + ? (maybeNode: unknown, context: object, info: GraphQLResolveInfo) => { + if (!maybeNode) { + return false; + } + + if (maybeNode instanceof (nameOrRef as Function)) { + return true; + } + + const proto = Object.getPrototypeOf(maybeNode) as { constructor: unknown }; + + try { + if (proto?.constructor) { + const config = this.configStore.getTypeConfig(proto.constructor as OutputRef); + + return config.name === name; + } + } catch { + // ignore + } + + return false; + } + : undefined), + }); if (typeof nameOrRef !== 'string') { this.configStore.associateRefWithName(nameOrRef, name); diff --git a/packages/plugin-dataloader/tests/__snapshots__/index.test.ts.snap b/packages/plugin-dataloader/tests/__snapshots__/index.test.ts.snap index c2c45283f..613042543 100644 --- a/packages/plugin-dataloader/tests/__snapshots__/index.test.ts.snap +++ b/packages/plugin-dataloader/tests/__snapshots__/index.test.ts.snap @@ -319,8 +319,12 @@ exports[`dataloader > queries > valid queries 1`] = ` "classThing": { "id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjEyMw==", }, + "classThingNode": { + "__typename": "ClassLoadableThing", + "id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=", + }, "classThingRef": { - "id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjEyMw==", + "id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=", }, "counts": [ { diff --git a/packages/plugin-dataloader/tests/example/schema/nodes.ts b/packages/plugin-dataloader/tests/example/schema/nodes.ts index b842e230c..a2a2374d5 100644 --- a/packages/plugin-dataloader/tests/example/schema/nodes.ts +++ b/packages/plugin-dataloader/tests/example/schema/nodes.ts @@ -11,21 +11,25 @@ const UserNode = builder.loadableNodeRef('UserNode', { load: (keys: string[], context: ContextType) => { countCall(context, userNodeCounts, keys.length); return Promise.resolve( - keys.map((id) => (Number(id) > 0 ? { id: Number(id) } : new Error(`Invalid ID ${id}`))), + keys.map((id) => + Number(id) > 0 ? { objType: 'UserNode', id: Number(id) } : new Error(`Invalid ID ${id}`), + ), ); }, }); builder.objectType(UserNode, { interfaces: [TestInterface], - isTypeOf: (obj) => - typeof obj === 'object' && obj !== null && Object.prototype.hasOwnProperty.call(obj, 'id'), + isTypeOf: (obj) => (obj as any).objType === 'UserNode', fields: (t) => ({}), }); class ClassThing { - id: number = 123; + id: number; name: string = 'some name'; + constructor(id = 123) { + this.id = id; + } } const ClassThingRef = builder.loadableNode(ClassThing, { @@ -36,7 +40,8 @@ const ClassThingRef = builder.loadableNode(ClassThing, { }, loaderOptions: { maxBatchSize: 20 }, // eslint-disable-next-line @typescript-eslint/require-await - load: async (keys: string[], context: ContextType) => [new ClassThing()], + load: async (keys: string[], context: ContextType) => + keys.map((k) => new ClassThing(Number.parseInt(k, 10))), fields: (t) => ({}), }); diff --git a/packages/plugin-dataloader/tests/index.test.ts b/packages/plugin-dataloader/tests/index.test.ts index 68edc06cb..a0ccb6ea7 100644 --- a/packages/plugin-dataloader/tests/index.test.ts +++ b/packages/plugin-dataloader/tests/index.test.ts @@ -158,6 +158,10 @@ describe('dataloader', () => { threeToMany: oneToMany(id: 3) { id } + classThingNode: node(id: "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=") { + __typename + id + } } `;