Skip to content

Commit

Permalink
Merge pull request hayes#808 from hayes/tgriesser/feat/loadableNode-i…
Browse files Browse the repository at this point in the history
…sTypeOf

Tgriesser/feat/loadable node is type of
  • Loading branch information
hayes authored Feb 23, 2023
2 parents 9bbbefa + 22041db commit 286f785
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .changeset/kind-snails-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@pothos/plugin-dataloader': minor
'@pothos/deno': minor
---

Add default isTypeOf for loadableNode
2 changes: 1 addition & 1 deletion packages/deno/packages/plugin-dataloader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ const UserNode = builder.loadableNode('UserNode', {
id: {
resolve: (user) => user.id,
},
// For loadable objects we always need to include an isTypeOf check
// For loadable nodes, we need to include an isTypeOf check if the first arg is a string
isTypeOf: (obj) => obj instanceof User,
load: (ids: string[], context: ContextType) => context.loadUsersById(ids),
fields: (t) => ({}),
Expand Down
31 changes: 29 additions & 2 deletions packages/deno/packages/plugin-dataloader/schema-builder.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/plugin-dataloader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ const UserNode = builder.loadableNode('UserNode', {
id: {
resolve: (user) => user.id,
},
// For loadable objects we always need to include an isTypeOf check
// For loadable nodes, we need to include an isTypeOf check if the first arg is a string
isTypeOf: (obj) => obj instanceof User,
load: (ids: string[], context: ContextType) => context.loadUsersById(ids),
fields: (t) => ({}),
Expand Down
33 changes: 32 additions & 1 deletion packages/plugin-dataloader/src/schema-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { GraphQLResolveInfo } from 'graphql';
import SchemaBuilder, {
InterfaceParam,
ObjectParam,
OutputRef,
PothosSchemaError,
SchemaTypes,
ShapeFromTypeParam,
Expand Down Expand Up @@ -159,7 +161,36 @@ schemaBuilderProto.loadableNode = function loadableNode<
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,12 @@ exports[`dataloader > queries > valid queries 1`] = `
"classThing": {
"id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjEyMw==",
},
"classThingNode": {
"__typename": "ClassLoadableThing",
"id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=",
},
"classThingRef": {
"id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjEyMw==",
"id": "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=",
},
"counts": [
{
Expand Down
15 changes: 10 additions & 5 deletions packages/plugin-dataloader/tests/example/schema/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand All @@ -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) => ({}),
});

Expand Down
4 changes: 4 additions & 0 deletions packages/plugin-dataloader/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ describe('dataloader', () => {
threeToMany: oneToMany(id: 3) {
id
}
classThingNode: node(id: "Q2xhc3NMb2FkYWJsZVRoaW5nOjE=") {
__typename
id
}
}
`;

Expand Down
2 changes: 1 addition & 1 deletion website/pages/docs/plugins/dataloader.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ const UserNode = builder.loadableNode('UserNode', {
id: {
resolve: (user) => user.id,
},
// For loadable objects we always need to include an isTypeOf check
// For loadable nodes, we need to include an isTypeOf check if the first arg is a string
isTypeOf: (obj) => obj instanceof User,
load: (ids: string[], context: ContextType) => context.loadUsersById(ids),
fields: (t) => ({}),
Expand Down

0 comments on commit 286f785

Please sign in to comment.