buro26-strapi-graphql 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,10 +43,13 @@ extensions with Strapi.
43
43
  From each file create a default export that uses th `createGraphQLExtension` factory function. This function takes a
44
44
  function as an argument that will receive the Strapi instance and should return an object with the following methods:
45
45
 
46
- - init: Called when the extension is initialized
47
- - getTypes: Returns an array of GraphQL types
48
- - resolvers: Returns an object with resolvers
49
- - getResolverConfig: Returns an object with resolver configuration
46
+ | Method | Description |
47
+ |-----------------|--------------------------------------------------|
48
+ | init | Called when the extension is initialized |
49
+ | types | Returns an array of GraphQL types |
50
+ | typeDefs | Returns a string with the type definition in SDL |
51
+ | resolvers | Returns an object with resolvers |
52
+ | resolversConfig | Returns an object with resolver configuration |
50
53
 
51
54
  The functions you can implement follow the pattern of the Strapi customization
52
55
  options: https://docs.strapi.io/dev-docs/plugins/graphql#customization. The return values here will be registered as-is
@@ -54,7 +57,7 @@ with Strapi in the register hook.
54
57
 
55
58
  ```typescript
56
59
  import { createGraphQLExtension } from 'buro26-strapi-graphql';
57
- import { extendType, stringArg, nonNull } from 'nexus'
60
+ import { extendType, nonNull, stringArg } from 'nexus';
58
61
 
59
62
  export default createGraphQLExtension(strapi => ({
60
63
 
@@ -67,6 +70,14 @@ export default createGraphQLExtension(strapi => ({
67
70
  .disableActions(['find', 'findOne', 'create', 'update', 'delete']);
68
71
  },
69
72
 
73
+ typeDefs() {
74
+ return `
75
+ type HelloWorldResponse {
76
+ greeting: String!
77
+ }
78
+ `;
79
+ },
80
+
70
81
  types() {
71
82
  return [
72
83
  // Extend an existing type
@@ -124,7 +135,7 @@ export default createGraphQLExtension(strapi => ({
124
135
  };
125
136
  },
126
137
 
127
- resolverConfig() {
138
+ resolversConfig() {
128
139
  return {
129
140
  'Query.helloWorld': {
130
141
  policies: [
@@ -224,6 +235,68 @@ export default createGraphQLExtension(strapi => ({
224
235
  }));
225
236
  ```
226
237
 
238
+ ### Field middleware
239
+
240
+ You can add middleware to a specific field, similarly to adding authorization. Each field can have multiple middlewares.
241
+
242
+ This can be useful when you want to add some logic before or after the field is resolved. E.g. logging, caching,
243
+ response parsing, etc.
244
+
245
+ ```typescript
246
+ import { createGraphQLExtension, overrideField } from 'buro26-strapi-graphql';
247
+ import { extendType } from 'nexus';
248
+
249
+ export default createGraphQLExtension(strapi => ({
250
+ types() {
251
+ return [
252
+ // Extend an existing type
253
+ extendType({
254
+ type: 'MyType',
255
+ definition(t) {
256
+ t.field('myField', {
257
+ type: 'MyFieldType',
258
+ extensions: {
259
+ middlewares: [
260
+ next => async (root, args, context, info) => {
261
+ // Do something before the field is resolved
262
+
263
+ const res = await next(root, args, context, info);
264
+
265
+ // Do something after the field is resolved
266
+
267
+ return res;
268
+ }
269
+ ]
270
+ },
271
+ resolve: async (root) => {
272
+ // Resolver is optional
273
+ }
274
+ })
275
+ overrideField<MyContentType>(t, {
276
+ contentTypeName: 'api::my-type.my-type',
277
+ fieldName: 'myField',
278
+ extensions: {
279
+ middlewares: [
280
+ next => async (root, args, context, info) => {
281
+ // Do something before the field is resolved
282
+
283
+ const res = await next(root, args, context, info);
284
+
285
+ // Do something after the field is resolved
286
+
287
+ return res;
288
+ }
289
+ ]
290
+ }
291
+ });
292
+ }
293
+ })
294
+
295
+ ];
296
+ }
297
+ }));
298
+ ```
299
+
227
300
  ### Utility functions
228
301
 
229
302
  The plugin also provides utility functions to help you resolve entities and collections. These functions are useful when
@@ -283,6 +356,58 @@ export default createGraphQLExtension(strapi => ({
283
356
  }));
284
357
  ```
285
358
 
359
+ #### resolveEntityRelation
360
+
361
+ The `resolveEntityRelation` function can be used to resolve an entity by id. The function takes the content type name and an
362
+ object with all the resolve args passed the resolver function. The function will return the resolved entity as
363
+ EntityResponse.
364
+
365
+ ```typescript
366
+ import { createGraphQLExtension, overrideField, resolveEntityRelation } from 'buro26-strapi-graphql';
367
+ import { extendType } from 'nexus';
368
+
369
+ export default createGraphQLExtension(strapi => ({
370
+ types() {
371
+ return [
372
+ // Extend an existing type
373
+ extendType({
374
+ type: 'MyType',
375
+ definition(t) {
376
+ t.field('myFields', {
377
+ type: 'MyFieldEntityResponse',
378
+ resolve: async (parent, args, context, info) => {
379
+ // Do something, and resolve the entit
380
+ return resolveEntityRelation<MyContentType>('api::my-content-type.my-content-type', {
381
+ args: {
382
+ id: 'the id here',
383
+ },
384
+ parent,
385
+ context,
386
+ info,
387
+ })
388
+ }
389
+ });
390
+ overrideField<MyContentType>(t, {
391
+ contentTypeName: 'api::my-type.my-type',
392
+ fieldName: 'myOtherField',
393
+ resolve: async (parent, args, context, info) => {
394
+ // Do something, and resolve the entit
395
+ return resolveEntityRelation<MyContentType>('api::my-content-type.my-content-type', 'myRelationField', {
396
+ args,
397
+ parent, // needs to have the id field populated
398
+ context,
399
+ info,
400
+ })
401
+ }
402
+ });
403
+ }
404
+ })
405
+
406
+ ];
407
+ }
408
+ }));
409
+ ```
410
+
286
411
  #### resolveEntityCollection
287
412
 
288
413
  The `resolveEntityCollection` function can be used to resolve a collection of entities. The function takes the content
@@ -290,7 +415,7 @@ type name and an object with all the resolve args passed the resolver function.
290
415
  collection as EntityCollectionResponse.
291
416
 
292
417
  ```typescript
293
- import { createGraphQLExtension, overrideField, resolveEntityCollection } from 'buro26-strapi-graphql';
418
+ import { createGraphQLExtension, overrideField, createEntityCollectionResolver } from 'buro26-strapi-graphql';
294
419
  import { extendType } from 'nexus';
295
420
 
296
421
  export default createGraphQLExtension(strapi => ({
@@ -303,8 +428,9 @@ export default createGraphQLExtension(strapi => ({
303
428
  t.field('myFields', {
304
429
  type: 'MyFieldEntityResponseCollection',
305
430
  resolve: async (parent, args, context, info) => {
306
- // Do something, and resolve the entit
307
- return resolveEntityCollection<MyContentType>('api::my-content-type.my-content-type', {
431
+ // Do something, and resolve the entity
432
+ const resolver = createEntityCollectionResolver<MyContentType>('api::my-content-type.my-content-type');
433
+ return resolver({
308
434
  args,
309
435
  parent,
310
436
  context,
@@ -316,8 +442,9 @@ export default createGraphQLExtension(strapi => ({
316
442
  contentTypeName: 'api::my-type.my-type',
317
443
  fieldName: 'myOtherField',
318
444
  resolve: async (parent, args, context, info) => {
319
- // Do something, and resolve the entit
320
- return resolveEntityCollection<MyContentType>('api::my-content-type.my-content-type', {
445
+ // Do something, and resolve the entity
446
+ const resolver = createEntityCollectionResolver<MyContentType>('api::my-content-type.my-content-type');
447
+ return resolver({
321
448
  args,
322
449
  parent,
323
450
  context,
@@ -335,8 +462,8 @@ export default createGraphQLExtension(strapi => ({
335
462
 
336
463
  #### resolveEntityRelationCollection
337
464
 
338
- This function has the same API as `resolveEntityCollection` but is used to resolve a collection of entities from a
339
- relational field on the provided content type.
465
+ This function has a similar API as `createEntityRelationCollectionResolver` but is used to resolve a collection of entities from a
466
+ relational field on the provided content type. The only difference is that the resolvers first argument is the relation field name that should be resolved.
340
467
 
341
468
  #### toEntityResponse
342
469
 
@@ -354,7 +481,8 @@ This function is re-exported from the Strapi GraphQL plugin.
354
481
 
355
482
  #### resolveArgs
356
483
 
357
- This function is a typesafe utility function to resolve the args passed to the resolver function. It will transform the graphql
484
+ This function is a typesafe utility function to resolve the args passed to the resolver function. It will transform the
485
+ graphql
358
486
  args into args that can be passed to the entityManager.
359
487
 
360
488
  This function is re-exported from the Strapi GraphQL plugin.
@@ -1,5 +1,8 @@
1
- import { type Strapi } from '@strapi/strapi';
2
- import { type GraphQLExtension } from './types';
1
+ import type { Strapi } from '@strapi/strapi';
2
+ import type { GraphQLExtension } from './types';
3
+ import type { Middleware, ResolveContext } from './utils';
4
+ import type { GraphQLResolveInfo } from 'graphql';
5
+ import type { GraphQLFieldConfig } from 'graphql/type';
3
6
  declare const _default: {
4
7
  register: ({ strapi }: {
5
8
  strapi: Strapi;
@@ -43,3 +46,31 @@ declare module '@strapi/strapi' {
43
46
  createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
44
47
  }
45
48
  }
49
+ /**
50
+ * Extend Nexus's field definition to include a middleware array.
51
+ */
52
+ declare module 'nexus/dist/core' {
53
+ /**
54
+ * Extends Nexus's OutputFieldConfig to include a `middleware` property.
55
+ */
56
+ interface NexusOutputFieldConfig<TypeName extends string, FieldName extends string> {
57
+ extensions?: {
58
+ middlewares?: Middleware[];
59
+ } & GraphQLFieldConfig<any, any>['extensions'];
60
+ /**
61
+ * A function that determines if the current user is authorized to access this field.
62
+ *
63
+ * @param parent The parent object.
64
+ * @param args The arguments passed to the field.
65
+ * @param context The context object.
66
+ * @param info The GraphQLResolveInfo object.
67
+ */
68
+ authorize?: <Parent extends Object, Args extends Object, Context = ResolveContext>(parent: Parent, args: Args, context: Context, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
69
+ }
70
+ interface GraphQLFieldExtensions<_TSource, _TContext, _TArgs> {
71
+ /**
72
+ * An array of middleware functions to apply to this field.
73
+ */
74
+ middleware?: Middleware[];
75
+ }
76
+ }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const nexus_1 = require("nexus");
4
+ const utils_1 = require("./utils");
4
5
  exports.default = async ({ strapi }) => {
5
6
  const fileService = strapi
6
7
  .plugin('burotwosix-graphql-plugin')
@@ -13,7 +14,8 @@ exports.default = async ({ strapi }) => {
13
14
  ];
14
15
  graphQlExtensionService.use(() => ({
15
16
  plugins: [
16
- (0, nexus_1.fieldAuthorizePlugin)()
17
+ (0, nexus_1.fieldAuthorizePlugin)(),
18
+ (0, utils_1.nexusMiddlewarePlugin)(),
17
19
  ]
18
20
  }));
19
21
  for (const extension of extensions) {
@@ -30,7 +32,7 @@ exports.default = async ({ strapi }) => {
30
32
  resolvers: (_k = (_j = extension === null || extension === void 0 ? void 0 : extension.resolvers) === null || _j === void 0 ? void 0 : _j.call(extension)) !== null && _k !== void 0 ? _k : { Query: {}, Mutation: {} },
31
33
  resolversConfig: {
32
34
  ...(_m = (_l = extension === null || extension === void 0 ? void 0 : extension.getResolverConfig) === null || _l === void 0 ? void 0 : _l.call(extension)) !== null && _m !== void 0 ? _m : {},
33
- ...(_p = (_o = extension === null || extension === void 0 ? void 0 : extension.resolverConfig) === null || _o === void 0 ? void 0 : _o.call(extension)) !== null && _p !== void 0 ? _p : {},
35
+ ...(_p = (_o = extension === null || extension === void 0 ? void 0 : extension.resolversConfig) === null || _o === void 0 ? void 0 : _o.call(extension)) !== null && _p !== void 0 ? _p : {},
34
36
  },
35
37
  });
36
38
  });
@@ -43,7 +43,7 @@ export interface GraphQLExtension {
43
43
  * This is used to configure middlewares and other resolver options
44
44
  * @see https://docs.strapi.io/developer-docs/latest/plugins/graphql.html#extending-the-schema
45
45
  *
46
- * @deprecated Use resolverConfig() instead
46
+ * @deprecated Use resolversConfig() instead
47
47
  */
48
48
  getResolverConfig?: () => any;
49
49
  /**
@@ -51,7 +51,7 @@ export interface GraphQLExtension {
51
51
  * This is used to configure middlewares and other resolver options
52
52
  * @see https://docs.strapi.io/developer-docs/latest/plugins/graphql.html#extending-the-schema
53
53
  */
54
- resolverConfig?: () => Record<string, ResolverConfigOption>;
54
+ resolversConfig?: () => Record<string, ResolverConfigOption>;
55
55
  }
56
56
  type ResolverConfigOption = {
57
57
  auth?: boolean | undefined;
@@ -3,18 +3,31 @@
3
3
  *
4
4
  * Based on node_modules/@strapi/plugin-graphql/server/services/builders/resolvers/association.js
5
5
  */
6
- import { Entity, type ResolveArgs } from './types';
7
- export declare const resolveEntityCollection: <T extends Object>(contentType: string, resolveArgs: ResolveArgs) => Promise<Entity<T>[]>;
8
- export declare const resolveEntityRelationCollection: <T extends Object>(contentType: string, relationFieldName: keyof T, resolveArgs: ResolveArgs) => Promise<Entity<T>[]>;
9
- type EntityResponse<T extends Object> = {
10
- value: Entity<T> | null;
6
+ import { type ResolveArgs } from './types';
7
+ /**
8
+ * Create a resolver for a collection of entities
9
+ * Returns a resolver that resolves the entities based on the content type UID
10
+ *
11
+ * @param contentType The content type UID of the entities
12
+ */
13
+ export declare const createEntityCollectionResolver: <ContentType extends Object>(contentType: string) => (resolveArgs: ResolveArgs<ContentType>) => Promise<EntityResponseCollection<ContentType>>;
14
+ /**
15
+ * Create a resolver for a collection of entities related to a parent entity
16
+ * Returns a resolver that resolves the related entities based on the relation field name
17
+ *
18
+ * @param contentType The content type UID of the related entities
19
+ */
20
+ export declare function createEntityRelationCollectionResolver<Parent extends object>(contentType: string): <K extends keyof Parent>(relationFieldName: K, resolveArgs: ResolveArgs<Parent>) => Promise<EntityResponseCollection<ExtractRelation<Parent, K>>>;
21
+ type EntityResponseCollection<T extends Object> = {
22
+ nodes: T[];
11
23
  info: {
12
24
  args: Record<string, any>;
13
25
  resourceUID: string;
14
26
  };
15
27
  };
28
+ type ExtractRelation<Parent, K extends keyof Parent> = Parent[K] extends Array<infer U> ? U extends object ? U : never : Parent[K] extends object ? Parent[K] : never;
16
29
  export default function toEntityResponseCollection<T extends Object>(items: T[], { args, resourceUID }: {
17
30
  args: Record<string, any>;
18
31
  resourceUID: string;
19
- }): EntityResponse<T>[];
32
+ }): EntityResponseCollection<T>;
20
33
  export {};
@@ -5,34 +5,53 @@
5
5
  * Based on node_modules/@strapi/plugin-graphql/server/services/builders/resolvers/association.js
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.resolveEntityRelationCollection = exports.resolveEntityCollection = void 0;
9
- const resolveEntityCollection = async (contentType, resolveArgs) => {
8
+ exports.createEntityRelationCollectionResolver = exports.createEntityCollectionResolver = void 0;
9
+ /**
10
+ * Create a resolver for a collection of entities
11
+ * Returns a resolver that resolves the entities based on the content type UID
12
+ *
13
+ * @param contentType The content type UID of the entities
14
+ */
15
+ const createEntityCollectionResolver = (contentType) => {
10
16
  const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
11
17
  const { toEntityResponseCollection } = strapi.plugin('graphql').service('format').returnTypes;
12
18
  const { buildQueriesResolvers } = strapi.plugin('graphql').service('builders').get('content-api');
13
- const transformedArgs = transformArgs(resolveArgs.args, {
14
- contentType: strapi.contentTypes[contentType],
15
- usePagination: true
16
- });
17
19
  const { find } = buildQueriesResolvers({
18
20
  contentType: strapi.contentTypes[contentType]
19
21
  });
20
- const items = await find(resolveArgs.parent, transformedArgs, resolveArgs.context);
21
- return toEntityResponseCollection(items, {
22
- args: transformedArgs,
23
- resourceUID: contentType
24
- });
22
+ return async (resolveArgs) => {
23
+ const transformedArgs = transformArgs(resolveArgs.args, {
24
+ contentType: strapi.contentTypes[contentType],
25
+ usePagination: true
26
+ });
27
+ const items = await find(resolveArgs.parent, transformedArgs, resolveArgs.context);
28
+ return toEntityResponseCollection(items, {
29
+ args: transformedArgs,
30
+ resourceUID: contentType
31
+ });
32
+ };
25
33
  };
26
- exports.resolveEntityCollection = resolveEntityCollection;
27
- const resolveEntityRelationCollection = async (contentType, relationFieldName, resolveArgs) => {
28
- const { buildAssociationResolver } = strapi.plugin('graphql').service('builders').get('content-api');
29
- const find = buildAssociationResolver({
30
- contentTypeUID: contentType,
31
- attributeName: relationFieldName
32
- });
33
- return find(resolveArgs.parent, resolveArgs.args, resolveArgs.context);
34
- };
35
- exports.resolveEntityRelationCollection = resolveEntityRelationCollection;
34
+ exports.createEntityCollectionResolver = createEntityCollectionResolver;
35
+ /**
36
+ * Create a resolver for a collection of entities related to a parent entity
37
+ * Returns a resolver that resolves the related entities based on the relation field name
38
+ *
39
+ * @param contentType The content type UID of the related entities
40
+ */
41
+ function createEntityRelationCollectionResolver(contentType) {
42
+ return async (relationFieldName, resolveArgs) => {
43
+ const { buildAssociationResolver } = strapi
44
+ .plugin('graphql')
45
+ .service('builders')
46
+ .get('content-api');
47
+ const find = buildAssociationResolver({
48
+ contentTypeUID: contentType,
49
+ attributeName: relationFieldName
50
+ });
51
+ return find(resolveArgs.parent, resolveArgs.args, resolveArgs.context);
52
+ };
53
+ }
54
+ exports.createEntityRelationCollectionResolver = createEntityRelationCollectionResolver;
36
55
  function toEntityResponseCollection(items, { args, resourceUID }) {
37
56
  const { toEntityResponseCollection } = strapi.plugin('graphql').service('format').returnTypes;
38
57
  return toEntityResponseCollection(items, {
@@ -1,5 +1,6 @@
1
1
  export * from './types';
2
2
  export * from './single-type';
3
3
  export * from './collection-type';
4
+ export * from './middleware';
4
5
  export * from './misc';
5
6
  export * from './override';
@@ -17,5 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./types"), exports);
18
18
  __exportStar(require("./single-type"), exports);
19
19
  __exportStar(require("./collection-type"), exports);
20
+ __exportStar(require("./middleware"), exports);
20
21
  __exportStar(require("./misc"), exports);
21
22
  __exportStar(require("./override"), exports);
@@ -0,0 +1,17 @@
1
+ import 'nexus';
2
+ import { GraphQLResolveInfo } from 'graphql';
3
+ import { ResolveContext } from './types';
4
+ /**
5
+ * The Resolver type represents a GraphQL resolver function.
6
+ */
7
+ export type Resolver = <Parent extends Object, Args extends Object, Context = ResolveContext>(parent: Parent, args: Args, context: Context, info: GraphQLResolveInfo) => any | Promise<any>;
8
+ /**
9
+ * Middleware is a function that takes a resolver and returns a new resolver.
10
+ */
11
+ export type Middleware = (resolver: Resolver) => Resolver;
12
+ export declare const nexusMiddlewarePlugin: () => import("nexus/dist/plugin").NexusPlugin;
13
+ /**
14
+ * Logging Middleware
15
+ * Logs the execution of the resolver.
16
+ */
17
+ export declare const loggingMiddleware: Middleware;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loggingMiddleware = exports.nexusMiddlewarePlugin = void 0;
4
+ require("nexus");
5
+ const nexus_1 = require("nexus");
6
+ const utils_1 = require("nexus/dist/utils");
7
+ const fieldDefTypes = (0, utils_1.printedGenTyping)({
8
+ optional: true,
9
+ name: 'middlewares',
10
+ description: `
11
+ Authorization for an individual field. Returning "true"
12
+ or "Promise<true>" means the field can be accessed.
13
+ Returning "false" or "Promise<false>" will respond
14
+ with a "Not Authorized" error for the field.
15
+ Returning or throwing an error will also prevent the
16
+ resolver from executing.
17
+ `,
18
+ type: 'any',
19
+ });
20
+ const nexusMiddlewarePlugin = () => (0, nexus_1.plugin)({
21
+ name: 'NexusMiddlewarePlugin',
22
+ description: 'The middleware plugin allows attaching middleware functions to individual fields.',
23
+ /**
24
+ * Defines the field definition types for the plugin.
25
+ */
26
+ fieldDefTypes: fieldDefTypes,
27
+ /**
28
+ * Hook into field resolver creation to apply middleware.
29
+ */
30
+ onCreateFieldResolver(config) {
31
+ var _a;
32
+ const { fieldConfig } = config;
33
+ // @ts-ignore
34
+ const middlewares = ((_a = fieldConfig.extensions) === null || _a === void 0 ? void 0 : _a.middlewares) || [];
35
+ if (middlewares.length === 0) {
36
+ return undefined; // No middleware to apply
37
+ }
38
+ // Convert Middleware[] to MiddlewareFn[]
39
+ const middlewareFns = middlewares.map(middleware => {
40
+ return async (source, args, context, info, next) => {
41
+ const newResolver = middleware(next);
42
+ return newResolver(source, args, context, info);
43
+ };
44
+ });
45
+ // Compose the middleware functions into a single MiddlewareFn
46
+ return async (source, args, context, info, next) => {
47
+ let index = -1;
48
+ const dispatch = async (i) => {
49
+ if (i <= index)
50
+ throw new Error('next() called multiple times');
51
+ index = i;
52
+ const middlewareFn = middlewareFns[i];
53
+ if (middlewareFn) {
54
+ return middlewareFn(source, args, context, info, () => dispatch(i + 1));
55
+ }
56
+ else {
57
+ return next(source, args, context, info);
58
+ }
59
+ };
60
+ return dispatch(0);
61
+ };
62
+ },
63
+ });
64
+ exports.nexusMiddlewarePlugin = nexusMiddlewarePlugin;
65
+ /**
66
+ * Logging Middleware
67
+ * Logs the execution of the resolver.
68
+ */
69
+ const loggingMiddleware = (resolver) => {
70
+ return async (parent, args, context, info) => {
71
+ console.log(`Resolving field ${info.parentType.name}.${info.fieldName}`);
72
+ const result = await resolver(parent, args, context, info);
73
+ console.log(`Resolved field ${info.parentType.name}.${info.fieldName} with result:`, result);
74
+ return result;
75
+ };
76
+ };
77
+ exports.loggingMiddleware = loggingMiddleware;
@@ -3,14 +3,18 @@
3
3
  *
4
4
  * Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
5
5
  */
6
- import { type GraphQLResolveInfo } from 'graphql';
7
- import { ResolveContext } from './types';
6
+ import type { GraphQLResolveInfo } from 'graphql';
7
+ import type { ResolveContext } from './types';
8
+ import type { Middleware } from './middleware';
8
9
  type OverrideFieldOptions<Type extends Object, Args = unknown, Context = ResolveContext, Info = GraphQLResolveInfo> = {
9
10
  contentTypeName: string;
10
11
  fieldName: keyof Type;
11
12
  type?: string;
12
13
  authorize?: (parent: Type, args: Args, context: Context, info: Info) => boolean | Promise<boolean>;
13
14
  resolve?: (parent: Type, args: Args, context: Context, info: Info) => unknown;
15
+ extensions?: {
16
+ middlewares?: Middleware[];
17
+ };
14
18
  };
15
19
  export declare const overrideField: <T extends Object>(t: any, overrideOptions: OverrideFieldOptions<T, unknown, ResolveContext, GraphQLResolveInfo>) => void;
16
20
  export {};
@@ -10,6 +10,7 @@ type ResolveEntityArgs = Omit<ResolveArgs, 'args'> & {
10
10
  };
11
11
  };
12
12
  export declare function resolveEntity<T extends Object>(contentType: string, resolveArgs: ResolveEntityArgs): Promise<Entity<T> | null>;
13
+ export declare const resolveEntityRelation: <T extends Object>(contentType: string, relationFieldName: keyof T, resolveArgs: ResolveArgs) => Promise<Entity<T>[]>;
13
14
  type EntityResponse<T extends Object> = {
14
15
  value: Entity<T> | null;
15
16
  info: {
@@ -5,7 +5,7 @@
5
5
  * Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.toEntityResponse = exports.resolveEntity = void 0;
8
+ exports.toEntityResponse = exports.resolveEntityRelation = exports.resolveEntity = void 0;
9
9
  async function resolveEntity(contentType, resolveArgs) {
10
10
  const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
11
11
  const { toEntityResponse } = strapi.plugin('graphql').service('format').returnTypes;
@@ -19,6 +19,15 @@ async function resolveEntity(contentType, resolveArgs) {
19
19
  });
20
20
  }
21
21
  exports.resolveEntity = resolveEntity;
22
+ const resolveEntityRelation = async (contentType, relationFieldName, resolveArgs) => {
23
+ const { buildAssociationResolver } = strapi.plugin('graphql').service('builders').get('content-api');
24
+ const find = buildAssociationResolver({
25
+ contentTypeUID: contentType,
26
+ attributeName: relationFieldName
27
+ });
28
+ return find(resolveArgs.parent, resolveArgs.args, resolveArgs.context);
29
+ };
30
+ exports.resolveEntityRelation = resolveEntityRelation;
22
31
  async function toEntityResponse(item, { args, resourceUID }) {
23
32
  const { toEntityResponse } = strapi.plugin('graphql').service('format').returnTypes;
24
33
  return toEntityResponse(item, {