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 +142 -14
- package/dist/server/index.d.ts +33 -2
- package/dist/server/register.js +4 -2
- package/dist/server/types.d.ts +2 -2
- package/dist/server/utils/collection-type.d.ts +19 -6
- package/dist/server/utils/collection-type.js +40 -21
- package/dist/server/utils/index.d.ts +1 -0
- package/dist/server/utils/index.js +1 -0
- package/dist/server/utils/middleware.d.ts +17 -0
- package/dist/server/utils/middleware.js +77 -0
- package/dist/server/utils/override.d.ts +6 -2
- package/dist/server/utils/single-type.d.ts +1 -0
- package/dist/server/utils/single-type.js +10 -1
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +1 -1
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
|
307
|
-
|
|
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
|
|
320
|
-
|
|
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
|
|
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
|
|
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.
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
+
}
|
package/dist/server/register.js
CHANGED
|
@@ -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.
|
|
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
|
});
|
package/dist/server/types.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
}):
|
|
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.
|
|
9
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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, {
|
|
@@ -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 {
|
|
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, {
|