Skip to content

Commit 5e71c28

Browse files
committed
support indirect paths in queryFromInfo
1 parent 72de623 commit 5e71c28

File tree

8 files changed

+157
-19
lines changed

8 files changed

+157
-19
lines changed

.changeset/smooth-rocks-bathe.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@pothos/plugin-prisma': minor
3+
---
4+
5+
update queryFromInfo to support indirect paths

packages/plugin-prisma/src/field-builder.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ fieldBuilderProto.prismaField = function prismaField({ type, resolve, ...options
3333
return this.field({
3434
...(options as {}),
3535
type: typeParam,
36-
resolve: (parent: never, args: unknown, ctx: {}, info: GraphQLResolveInfo) => {
37-
const query = queryFromInfo(ctx, info);
36+
resolve: (parent: never, args: unknown, context: {}, info: GraphQLResolveInfo) => {
37+
const query = queryFromInfo({ context, info });
3838

39-
return resolve(query, parent, args as never, ctx, info) as never;
39+
return resolve(query, parent, args as never, context, info) as never;
4040
},
4141
}) as never;
4242
};
@@ -89,21 +89,25 @@ fieldBuilderProto.prismaConnection = function prismaConnection<
8989
resolve: (
9090
parent: unknown,
9191
args: PothosSchemaTypes.DefaultConnectionArguments,
92-
ctx: {},
92+
context: {},
9393
info: GraphQLResolveInfo,
9494
) =>
9595
resolvePrismaCursorConnection(
9696
{
97-
query: queryFromInfo(ctx, info, undefined, { select: cursorSelection as {} }),
98-
ctx,
97+
query: queryFromInfo({
98+
context,
99+
info,
100+
select: cursorSelection as {},
101+
}),
102+
ctx: context,
99103
parseCursor,
100104
maxSize,
101105
defaultSize,
102106
args,
103-
totalCount: totalCount && (() => totalCount(parent, args as never, ctx, info)),
107+
totalCount: totalCount && (() => totalCount(parent, args as never, context, info)),
104108
},
105109
formatCursor,
106-
(query) => resolve(query as never, parent, args as never, ctx, info),
110+
(query) => resolve(query as never, parent, args as never, context, info),
107111
),
108112
},
109113
{

packages/plugin-prisma/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export class PrismaPlugin<Types extends SchemaTypes> extends BasePlugin<Types> {
9999
}
100100

101101
if (fallback) {
102-
return fallback(queryFromInfo(context, info), parent, args, context, info);
102+
return fallback(queryFromInfo({ context, info }), parent, args, context, info);
103103
}
104104

105105
const selectionState = selectionStateFromInfo(context, info);

packages/plugin-prisma/src/schema-builder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ schemaBuilderProto.prismaNode = function prismaNode(
9797
context: SchemaTypes['Context'],
9898
info: GraphQLResolveInfo,
9999
) => {
100-
const query = queryFromInfo(context, info, typeName);
100+
const query = queryFromInfo({ context, info, typeName });
101101
const delegate = getDelegateFromModel(getClient(this, context), type);
102102

103103
const record = await (delegate.findUniqueOrThrow

packages/plugin-prisma/src/util/map-query.ts

+29-9
Original file line numberDiff line numberDiff line change
@@ -306,20 +306,40 @@ function addFieldSelection(
306306
}
307307
}
308308

309-
export function queryFromInfo(
310-
context: object,
311-
info: GraphQLResolveInfo,
312-
typeName?: string,
313-
initialSelection?: SelectionMap,
314-
): {} {
309+
export function queryFromInfo({
310+
context,
311+
info,
312+
typeName,
313+
select,
314+
path = [],
315+
}: {
316+
context: object;
317+
info: GraphQLResolveInfo;
318+
typeName?: string;
319+
select?: SelectionMap['select'];
320+
path?: string[];
321+
}): {} {
315322
const type = typeName ? info.schema.getTypeMap()[typeName] : getNamedType(info.returnType);
316323
const state = createStateForType(type, info);
317324

318-
if (initialSelection) {
319-
mergeSelection(state, initialSelection);
325+
if (select) {
326+
mergeSelection(state, { select });
320327
}
321328

322-
addTypeSelectionsForField(type, context, info, state, info.fieldNodes[0], []);
329+
if (path.length > 0) {
330+
resolveIndirectInclude(
331+
getNamedType(info.returnType),
332+
info,
333+
info.fieldNodes[0],
334+
path.map((n) => (typeof n === 'string' ? { name: n } : n)),
335+
[],
336+
(resolvedType, resolvedField, nested) => {
337+
addTypeSelectionsForField(resolvedType, context, info, state, resolvedField, nested);
338+
},
339+
);
340+
} else {
341+
addTypeSelectionsForField(type, context, info, state, info.fieldNodes[0], []);
342+
}
323343

324344
setLoaderMappings(context, info, state.mappings);
325345

packages/plugin-prisma/tests/__snapshots__/index.test.ts.snap

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ exports[`prisma generates schema 1`] = `
55
message: String!
66
}
77
8+
type Blog {
9+
pages: [Int!]!
10+
posts: [Post!]!
11+
}
12+
813
type Comment {
914
author: User!
1015
authorBio: String
@@ -109,6 +114,7 @@ type Profile {
109114
110115
type Query {
111116
badUser: User!
117+
blog: Blog!
112118
findUniqueRelations: FindUniqueRelations!
113119
findUniqueRelationsSelect: FindUniqueRelations!
114120
manualConnection(after: ID, before: ID, first: Int, last: Int): QueryManualConnection!

packages/plugin-prisma/tests/example/schema/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable no-underscore-dangle */
22
import { resolveCursorConnection, ResolveCursorConnectionArgs } from '@pothos/plugin-relay';
3+
import { queryFromInfo } from '../../../src/util/map-query';
34
import { Post } from '../../client';
45
import builder, { prisma } from '../builder';
56

@@ -769,4 +770,27 @@ builder.queryField('manualConnection', (t) =>
769770
}),
770771
);
771772

773+
const Blog = builder.objectRef<{ posts: Post[]; pages: number[] }>('Blog').implement({
774+
fields: (t) => ({
775+
posts: t.prismaField({
776+
type: ['Post'],
777+
resolve: (_, blog) => blog.posts,
778+
}),
779+
pages: t.exposeIntList('pages'),
780+
}),
781+
});
782+
783+
builder.queryField('blog', (t) =>
784+
t.field({
785+
type: Blog,
786+
resolve: async (_, args, context, info) => ({
787+
posts: await prisma.post.findMany({
788+
...queryFromInfo({ context, info, typeName: 'Post', path: ['posts'] }),
789+
take: 3,
790+
}),
791+
pages: [1, 2, 3],
792+
}),
793+
}),
794+
);
795+
772796
export default builder.toSchema({});

packages/plugin-prisma/tests/nested-query.test.ts

+79
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,83 @@ describe('nested query', () => {
194194
]
195195
`);
196196
});
197+
198+
it('queryFromInfo with nested path', async () => {
199+
const query = gql`
200+
query {
201+
blog {
202+
posts {
203+
id
204+
author {
205+
name
206+
}
207+
}
208+
pages
209+
}
210+
}
211+
`;
212+
213+
const result = await execute({
214+
schema,
215+
document: query,
216+
contextValue: { user: { id: 1 } },
217+
});
218+
219+
expect(result).toMatchInlineSnapshot(`
220+
Object {
221+
"data": Object {
222+
"blog": Object {
223+
"pages": Array [
224+
1,
225+
2,
226+
3,
227+
],
228+
"posts": Array [
229+
Object {
230+
"author": Object {
231+
"name": "Maurine Rath",
232+
},
233+
"id": "1",
234+
},
235+
Object {
236+
"author": Object {
237+
"name": "Maurine Rath",
238+
},
239+
"id": "2",
240+
},
241+
Object {
242+
"author": Object {
243+
"name": "Maurine Rath",
244+
},
245+
"id": "3",
246+
},
247+
],
248+
},
249+
},
250+
}
251+
`);
252+
253+
expect(queries).toMatchInlineSnapshot(`
254+
Array [
255+
Object {
256+
"action": "findMany",
257+
"args": Object {
258+
"include": Object {
259+
"author": true,
260+
"comments": Object {
261+
"include": Object {
262+
"author": true,
263+
},
264+
"take": 3,
265+
},
266+
},
267+
"take": 3,
268+
},
269+
"dataPath": Array [],
270+
"model": "Post",
271+
"runInTransaction": false,
272+
},
273+
]
274+
`);
275+
});
197276
});

0 commit comments

Comments
 (0)