buro26-strapi-graphql 0.0.10 → 0.0.12
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/dist/server/bootstrap.d.ts +1 -1
- package/dist/server/controllers/index.d.ts +1 -1
- package/dist/server/destroy.d.ts +1 -1
- package/dist/server/index.d.ts +10 -4
- package/dist/server/index.js +2 -1
- package/dist/server/register.d.ts +2 -2
- package/dist/server/register.js +5 -8
- package/dist/server/services/file-service.d.ts +11 -3
- package/dist/server/services/file-service.js +28 -14
- package/dist/server/services/graphql-service.d.ts +1 -1
- package/dist/server/services/index.d.ts +3 -3
- package/dist/server/types.d.ts +0 -1
- package/dist/server/utils/collection-type.d.ts +8 -0
- package/dist/server/utils/collection-type.js +35 -0
- package/dist/server/utils/index.d.ts +4 -0
- package/dist/server/utils/index.js +20 -0
- package/dist/server/utils/override.d.ts +15 -0
- package/dist/server/utils/override.js +245 -0
- package/dist/server/utils/single-type.d.ts +13 -0
- package/dist/server/utils/single-type.js +21 -0
- package/dist/server/utils/types.d.ts +11 -0
- package/dist/server/utils/types.js +2 -0
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +9 -10
- package/dist/server/services/my-service.js +0 -7
package/dist/server/destroy.d.ts
CHANGED
package/dist/server/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Strapi } from
|
|
2
|
-
import { GraphQLExtension } from
|
|
1
|
+
import { type Strapi } from '@strapi/strapi';
|
|
2
|
+
import { type GraphQLExtension } from './types';
|
|
3
3
|
declare const _default: {
|
|
4
4
|
register: ({ strapi }: {
|
|
5
5
|
strapi: Strapi;
|
|
6
|
-
}) => void
|
|
6
|
+
}) => Promise<void>;
|
|
7
7
|
bootstrap: ({ strapi }: {
|
|
8
8
|
strapi: Strapi;
|
|
9
9
|
}) => void;
|
|
@@ -24,7 +24,7 @@ declare const _default: {
|
|
|
24
24
|
fileService: ({ strapi }: {
|
|
25
25
|
strapi: Strapi;
|
|
26
26
|
}) => {
|
|
27
|
-
getAllFilesInGraphQlDirectory(
|
|
27
|
+
getAllFilesInGraphQlDirectory(directoryPath: string, collectedExtensions?: GraphQLExtension[]): Promise<GraphQLExtension[]>;
|
|
28
28
|
};
|
|
29
29
|
graphQlService: ({ strapi }: {
|
|
30
30
|
strapi: Strapi;
|
|
@@ -36,4 +36,10 @@ declare const _default: {
|
|
|
36
36
|
};
|
|
37
37
|
export default _default;
|
|
38
38
|
export * from './types';
|
|
39
|
+
export * from './utils';
|
|
39
40
|
export declare const createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
|
|
41
|
+
declare module '@strapi/strapi' {
|
|
42
|
+
interface Strapi {
|
|
43
|
+
createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/server/index.js
CHANGED
|
@@ -38,8 +38,9 @@ exports.default = {
|
|
|
38
38
|
services: services_1.default,
|
|
39
39
|
contentTypes: content_types_1.default,
|
|
40
40
|
policies: policies_1.default,
|
|
41
|
-
middlewares: middlewares_1.default
|
|
41
|
+
middlewares: middlewares_1.default
|
|
42
42
|
};
|
|
43
43
|
__exportStar(require("./types"), exports);
|
|
44
|
+
__exportStar(require("./utils"), exports);
|
|
44
45
|
const createGraphQLExtension = (factory) => factory(strapi);
|
|
45
46
|
exports.createGraphQLExtension = createGraphQLExtension;
|
package/dist/server/register.js
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const nexus_1 = require("nexus");
|
|
4
|
-
exports.default = ({ strapi }) => {
|
|
4
|
+
exports.default = async ({ strapi }) => {
|
|
5
5
|
const fileService = strapi
|
|
6
6
|
.plugin('burotwosix-graphql-plugin')
|
|
7
7
|
.service('fileService');
|
|
8
8
|
const graphQlExtensionService = strapi
|
|
9
9
|
.plugin('graphql')
|
|
10
10
|
.service('extension');
|
|
11
|
-
console.log({
|
|
12
|
-
dirs: strapi.dirs,
|
|
13
|
-
});
|
|
14
11
|
const extensions = [
|
|
15
|
-
...fileService.getAllFilesInGraphQlDirectory(strapi.dirs.dist.src)
|
|
12
|
+
...await fileService.getAllFilesInGraphQlDirectory(strapi.dirs.dist.src)
|
|
16
13
|
];
|
|
17
14
|
graphQlExtensionService.use(() => ({
|
|
18
15
|
plugins: [
|
|
19
|
-
(0, nexus_1.fieldAuthorizePlugin)()
|
|
16
|
+
(0, nexus_1.fieldAuthorizePlugin)()
|
|
20
17
|
]
|
|
21
18
|
}));
|
|
22
19
|
for (const extension of extensions) {
|
|
23
|
-
(extension === null || extension === void 0 ? void 0 : extension.init)
|
|
20
|
+
(extension === null || extension === void 0 ? void 0 : extension.init) && extension.init();
|
|
24
21
|
graphQlExtensionService.use(() => {
|
|
25
22
|
var _a, _b, _c, _d, _e, _f;
|
|
26
23
|
return ({
|
|
27
24
|
types: (_b = (_a = extension === null || extension === void 0 ? void 0 : extension.getTypes) === null || _a === void 0 ? void 0 : _a.call(extension)) !== null && _b !== void 0 ? _b : [],
|
|
28
25
|
resolvers: (_d = (_c = extension === null || extension === void 0 ? void 0 : extension.resolvers) === null || _c === void 0 ? void 0 : _c.call(extension)) !== null && _d !== void 0 ? _d : { Query: {}, Mutation: {} },
|
|
29
|
-
resolversConfig: (_f = (_e = extension === null || extension === void 0 ? void 0 : extension.getResolverConfig) === null || _e === void 0 ? void 0 : _e.call(extension)) !== null && _f !== void 0 ? _f : {}
|
|
26
|
+
resolversConfig: (_f = (_e = extension === null || extension === void 0 ? void 0 : extension.getResolverConfig) === null || _e === void 0 ? void 0 : _e.call(extension)) !== null && _f !== void 0 ? _f : {}
|
|
30
27
|
});
|
|
31
28
|
});
|
|
32
29
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { Strapi } from '@strapi/strapi';
|
|
2
|
-
import { GraphQLExtension } from
|
|
1
|
+
import { type Strapi } from '@strapi/strapi';
|
|
2
|
+
import { GraphQLExtension } from '../types';
|
|
3
3
|
declare const _default: ({ strapi }: {
|
|
4
4
|
strapi: Strapi;
|
|
5
5
|
}) => {
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Fetch all the files in the graphql directories within the given directory path
|
|
8
|
+
* Recursively searches for files in the graphql directory
|
|
9
|
+
* Returns an array of GraphQLExtension objects
|
|
10
|
+
*
|
|
11
|
+
* @param directoryPath
|
|
12
|
+
* @param collectedExtensions
|
|
13
|
+
*/
|
|
14
|
+
getAllFilesInGraphQlDirectory(directoryPath: string, collectedExtensions?: GraphQLExtension[]): Promise<GraphQLExtension[]>;
|
|
7
15
|
};
|
|
8
16
|
export default _default;
|
|
@@ -3,27 +3,41 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const fs_1 =
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
7
8
|
exports.default = ({ strapi }) => ({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Fetch all the files in the graphql directories within the given directory path
|
|
11
|
+
* Recursively searches for files in the graphql directory
|
|
12
|
+
* Returns an array of GraphQLExtension objects
|
|
13
|
+
*
|
|
14
|
+
* @param directoryPath
|
|
15
|
+
* @param collectedExtensions
|
|
16
|
+
*/
|
|
17
|
+
async getAllFilesInGraphQlDirectory(directoryPath, collectedExtensions = []) {
|
|
18
|
+
const fileEntries = await fs_1.promises.readdir(directoryPath);
|
|
19
|
+
// Create an array of promises for all the files
|
|
20
|
+
const filePromises = fileEntries.map(async (file) => {
|
|
21
|
+
const filePath = path_1.default.join(directoryPath, file);
|
|
22
|
+
const fileStats = await fs_1.promises.stat(filePath);
|
|
23
|
+
if (fileStats.isDirectory()) {
|
|
24
|
+
// Recursively get files from the directory
|
|
25
|
+
return this.getAllFilesInGraphQlDirectory(filePath, collectedExtensions);
|
|
14
26
|
}
|
|
15
|
-
if (!
|
|
27
|
+
if (!directoryPath.endsWith('/graphql') && !directoryPath.includes('/graphql/')) {
|
|
16
28
|
return;
|
|
17
29
|
}
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
30
|
+
const graphqlModule = require(filePath.replace('.js', ''));
|
|
31
|
+
if (!graphqlModule) {
|
|
20
32
|
return;
|
|
21
33
|
}
|
|
22
|
-
|
|
23
|
-
...
|
|
24
|
-
...(
|
|
34
|
+
collectedExtensions.push({
|
|
35
|
+
...graphqlModule,
|
|
36
|
+
...(graphqlModule.default || {})
|
|
25
37
|
});
|
|
26
38
|
});
|
|
27
|
-
|
|
39
|
+
// Wait for all the promises to resolve
|
|
40
|
+
await Promise.all(filePromises);
|
|
41
|
+
return collectedExtensions;
|
|
28
42
|
}
|
|
29
43
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
fileService: ({ strapi }: {
|
|
3
|
-
strapi: import("@strapi/
|
|
3
|
+
strapi: import("@strapi/types").Strapi;
|
|
4
4
|
}) => {
|
|
5
|
-
getAllFilesInGraphQlDirectory(
|
|
5
|
+
getAllFilesInGraphQlDirectory(directoryPath: string, collectedExtensions?: import("..").GraphQLExtension[]): Promise<import("..").GraphQLExtension[]>;
|
|
6
6
|
};
|
|
7
7
|
graphQlService: ({ strapi }: {
|
|
8
|
-
strapi: import("@strapi/
|
|
8
|
+
strapi: import("@strapi/types").Strapi;
|
|
9
9
|
}) => {};
|
|
10
10
|
};
|
|
11
11
|
export default _default;
|
package/dist/server/types.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Easily resolve a collection of entities
|
|
3
|
+
*
|
|
4
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/resolvers/association.js
|
|
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>[]>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Easily resolve a collection of entities
|
|
4
|
+
*
|
|
5
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/resolvers/association.js
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.resolveEntityRelationCollection = exports.resolveEntityCollection = void 0;
|
|
9
|
+
const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
|
|
10
|
+
const { toEntityResponseCollection } = strapi.plugin('graphql').service('format').returnTypes;
|
|
11
|
+
const resolveEntityCollection = async (contentType, resolveArgs) => {
|
|
12
|
+
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
|
+
const { find } = buildQueriesResolvers({
|
|
18
|
+
contentType: strapi.contentTypes[contentType]
|
|
19
|
+
});
|
|
20
|
+
const items = await find(resolveArgs.parent, transformedArgs, resolveArgs.context);
|
|
21
|
+
return toEntityResponseCollection(items, {
|
|
22
|
+
args: transformedArgs,
|
|
23
|
+
resourceUID: contentType
|
|
24
|
+
});
|
|
25
|
+
};
|
|
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;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./single-type"), exports);
|
|
19
|
+
__exportStar(require("./collection-type"), exports);
|
|
20
|
+
__exportStar(require("./override"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Override a field in a content type
|
|
3
|
+
*
|
|
4
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
|
|
5
|
+
*/
|
|
6
|
+
import { type GraphQLResolveInfo } from 'graphql';
|
|
7
|
+
type OverrideFieldOptions<T extends Object> = {
|
|
8
|
+
contentTypeName: string;
|
|
9
|
+
fieldName: keyof T;
|
|
10
|
+
type?: string;
|
|
11
|
+
authorize?: <Args = unknown, Context = unknown, Info = GraphQLResolveInfo>(parent: T, args: Args, context: Context, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
|
|
12
|
+
resolve?: <Args = unknown, Context = unknown, Info = GraphQLResolveInfo>(parent: T, args: Args, context: Context, info: GraphQLResolveInfo) => unknown;
|
|
13
|
+
};
|
|
14
|
+
export declare const overrideField: <T extends Object>(t: any, overrideOptions: OverrideFieldOptions<T>) => void;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Override a field in a content type
|
|
4
|
+
*
|
|
5
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.overrideField = void 0;
|
|
9
|
+
const fp_1 = require("lodash/fp");
|
|
10
|
+
const utils_1 = require("@strapi/utils");
|
|
11
|
+
const getGraphQLService = strapi.plugin('graphql').service;
|
|
12
|
+
const extension = getGraphQLService('extension');
|
|
13
|
+
/**
|
|
14
|
+
* Add a scalar attribute to the type definition
|
|
15
|
+
*
|
|
16
|
+
* The attribute is added based on a simple association between a Strapi
|
|
17
|
+
* type and a GraphQL type (the map is defined in `strapiTypeToGraphQLScalar`)
|
|
18
|
+
*/
|
|
19
|
+
const addScalarAttribute = ({ builder, attributeName, attribute, ...options }) => {
|
|
20
|
+
const { mappers } = getGraphQLService('utils');
|
|
21
|
+
const gqlType = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
22
|
+
builder.field(attributeName, { type: gqlType, ...options });
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Add a component attribute to the type definition
|
|
26
|
+
*
|
|
27
|
+
* The attribute is added by fetching the component's type
|
|
28
|
+
* name and using it as the attribute's type
|
|
29
|
+
*/
|
|
30
|
+
const addComponentAttribute = ({ builder, attributeName, contentType, attribute, ...options }) => {
|
|
31
|
+
let localBuilder = builder;
|
|
32
|
+
const { naming } = getGraphQLService('utils');
|
|
33
|
+
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
34
|
+
const { buildComponentResolver } = getGraphQLService('builders').get('content-api');
|
|
35
|
+
const type = naming.getComponentNameFromAttribute(attribute);
|
|
36
|
+
if (attribute.repeatable) {
|
|
37
|
+
localBuilder = localBuilder.list;
|
|
38
|
+
}
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
const targetComponent = strapi.getModel(attribute.component);
|
|
41
|
+
const resolve = buildComponentResolver({
|
|
42
|
+
contentTypeUID: contentType.uid,
|
|
43
|
+
attributeName,
|
|
44
|
+
strapi,
|
|
45
|
+
});
|
|
46
|
+
const args = getContentTypeArgs(targetComponent, { multiple: !!attribute.repeatable });
|
|
47
|
+
localBuilder.field(attributeName, { type, resolve, args, ...options });
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Add a dynamic zone attribute to the type definition
|
|
51
|
+
*
|
|
52
|
+
* The attribute is added by fetching the dynamic zone's
|
|
53
|
+
* type name and using it as the attribute's type
|
|
54
|
+
*/
|
|
55
|
+
const addDynamicZoneAttribute = ({ builder, attributeName, contentType, ...options }) => {
|
|
56
|
+
const { naming } = getGraphQLService('utils');
|
|
57
|
+
const { ERROR_CODES } = getGraphQLService('constants');
|
|
58
|
+
const { buildDynamicZoneResolver } = getGraphQLService('builders').get('content-api');
|
|
59
|
+
const { components } = contentType.attributes[attributeName];
|
|
60
|
+
const isEmpty = components.length === 0;
|
|
61
|
+
const type = naming.getDynamicZoneName(contentType, attributeName);
|
|
62
|
+
const resolve = isEmpty
|
|
63
|
+
? // If the dynamic zone don't have any component, then return an error payload
|
|
64
|
+
(0, fp_1.constant)({
|
|
65
|
+
code: ERROR_CODES.emptyDynamicZone,
|
|
66
|
+
message: `This dynamic zone don't have any component attached to it`,
|
|
67
|
+
})
|
|
68
|
+
: // Else, return a classic dynamic-zone resolver
|
|
69
|
+
buildDynamicZoneResolver({
|
|
70
|
+
contentTypeUID: contentType.uid,
|
|
71
|
+
attributeName,
|
|
72
|
+
});
|
|
73
|
+
builder.list.field(attributeName, { type, resolve, ...options });
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Add an enum attribute to the type definition
|
|
77
|
+
*
|
|
78
|
+
* The attribute is added by fetching the enum's type
|
|
79
|
+
* name and using it as the attribute's type
|
|
80
|
+
*/
|
|
81
|
+
const addEnumAttribute = ({ builder, attributeName, contentType, ...options }) => {
|
|
82
|
+
const { naming } = getGraphQLService('utils');
|
|
83
|
+
const type = naming.getEnumName(contentType, attributeName);
|
|
84
|
+
builder.field(attributeName, { type, ...options });
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Add a media attribute to the type definition
|
|
88
|
+
*/
|
|
89
|
+
const addMediaAttribute = (options) => {
|
|
90
|
+
const { naming } = getGraphQLService('utils');
|
|
91
|
+
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
92
|
+
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
93
|
+
const extension = getGraphQLService('extension');
|
|
94
|
+
const { builder } = options;
|
|
95
|
+
const { attributeName, attribute, contentType } = options;
|
|
96
|
+
const fileUID = 'plugin::upload.file';
|
|
97
|
+
if (extension.shadowCRUD(fileUID).isDisabled()) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const fileContentType = strapi.contentTypes[fileUID];
|
|
101
|
+
const resolve = buildAssociationResolver({
|
|
102
|
+
contentTypeUID: contentType.uid,
|
|
103
|
+
attributeName,
|
|
104
|
+
strapi,
|
|
105
|
+
});
|
|
106
|
+
const args = attribute.multiple ? getContentTypeArgs(fileContentType) : undefined;
|
|
107
|
+
const type = attribute.multiple
|
|
108
|
+
? naming.getRelationResponseCollectionName(fileContentType)
|
|
109
|
+
: naming.getEntityResponseName(fileContentType);
|
|
110
|
+
builder.field(attributeName, { type, resolve, args, ...options });
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Add a polymorphic relational attribute to the type definition
|
|
114
|
+
*/
|
|
115
|
+
const addPolymorphicRelationalAttribute = (options) => {
|
|
116
|
+
const { GENERIC_MORPH_TYPENAME } = getGraphQLService('constants');
|
|
117
|
+
const { naming } = getGraphQLService('utils');
|
|
118
|
+
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
119
|
+
let { builder } = options;
|
|
120
|
+
const { attributeName, attribute, contentType } = options;
|
|
121
|
+
const { target } = attribute; // @ts-ignore
|
|
122
|
+
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
123
|
+
if (isToManyRelation) {
|
|
124
|
+
builder = builder.list;
|
|
125
|
+
}
|
|
126
|
+
const resolve = buildAssociationResolver({
|
|
127
|
+
contentTypeUID: contentType.uid,
|
|
128
|
+
attributeName,
|
|
129
|
+
strapi,
|
|
130
|
+
});
|
|
131
|
+
// If there is no specific target specified, then use the GenericMorph type
|
|
132
|
+
if ((0, fp_1.isUndefined)(target)) {
|
|
133
|
+
builder.field(attributeName, {
|
|
134
|
+
type: GENERIC_MORPH_TYPENAME,
|
|
135
|
+
resolve,
|
|
136
|
+
...options,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// If the target is an array of string, resolve the associated morph type and use it
|
|
140
|
+
else if ((0, fp_1.isArray)(target) && target.every(fp_1.isString)) {
|
|
141
|
+
const type = naming.getMorphRelationTypeName(contentType, attributeName);
|
|
142
|
+
builder.field(attributeName, { type, resolve, ...options });
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Add a regular relational attribute to the type definition
|
|
147
|
+
*/
|
|
148
|
+
const addRegularRelationalAttribute = (options) => {
|
|
149
|
+
const { naming } = getGraphQLService('utils');
|
|
150
|
+
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
151
|
+
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
152
|
+
const extension = getGraphQLService('extension');
|
|
153
|
+
const { builder } = options;
|
|
154
|
+
const { attributeName, attribute, contentType } = options;
|
|
155
|
+
if (extension.shadowCRUD(attribute.target).isDisabled()) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
160
|
+
const resolve = buildAssociationResolver({
|
|
161
|
+
contentTypeUID: contentType.uid,
|
|
162
|
+
attributeName,
|
|
163
|
+
strapi,
|
|
164
|
+
});
|
|
165
|
+
// @ts-ignore
|
|
166
|
+
const targetContentType = strapi.getModel(attribute.target);
|
|
167
|
+
const type = isToManyRelation
|
|
168
|
+
? naming.getRelationResponseCollectionName(targetContentType)
|
|
169
|
+
: naming.getEntityResponseName(targetContentType);
|
|
170
|
+
const args = isToManyRelation ? getContentTypeArgs(targetContentType) : undefined;
|
|
171
|
+
const resolverPath = `${naming.getTypeName(contentType)}.${attributeName}`;
|
|
172
|
+
const resolverScope = `${targetContentType.uid}.find`;
|
|
173
|
+
extension.use({ resolversConfig: { [resolverPath]: { auth: { scope: [resolverScope] } } } });
|
|
174
|
+
builder.field(attributeName, { type, resolve, args, ...options });
|
|
175
|
+
};
|
|
176
|
+
const isPrivate = (contentType) => (attributeName) => {
|
|
177
|
+
return utils_1.contentTypes.isPrivateAttribute(contentType, attributeName);
|
|
178
|
+
};
|
|
179
|
+
const isDisabled = (contentType) => (attributeName) => {
|
|
180
|
+
return !extension.shadowCRUD(contentType.uid).field(attributeName).hasOutputEnabled();
|
|
181
|
+
};
|
|
182
|
+
const overrideField = (t, overrideOptions) => {
|
|
183
|
+
const utils = getGraphQLService('utils');
|
|
184
|
+
const { contentTypeName, fieldName } = overrideOptions;
|
|
185
|
+
const { isStrapiScalar, isComponent, isDynamicZone, isEnumeration, isMedia, isMorphRelation, isRelation, } = utils.attributes;
|
|
186
|
+
const contentType = strapi.contentTypes[contentTypeName];
|
|
187
|
+
const { attributes } = contentType;
|
|
188
|
+
// @ts-ignore
|
|
189
|
+
const attribute = attributes[fieldName];
|
|
190
|
+
if (isPrivate(contentType)(attribute)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (isDisabled(contentType)(attribute)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
// We create a copy of the builder (t) to apply custom
|
|
197
|
+
// rules only on the current attribute (eg: nonNull, list, ...)
|
|
198
|
+
let builder = t;
|
|
199
|
+
if (attribute.required) {
|
|
200
|
+
builder = builder.nonNull;
|
|
201
|
+
}
|
|
202
|
+
const options = {
|
|
203
|
+
builder,
|
|
204
|
+
attributeName: fieldName,
|
|
205
|
+
attribute,
|
|
206
|
+
contentType,
|
|
207
|
+
...overrideOptions,
|
|
208
|
+
};
|
|
209
|
+
// Enums
|
|
210
|
+
if (isEnumeration(attribute)) {
|
|
211
|
+
// @ts-ignore
|
|
212
|
+
addEnumAttribute(options);
|
|
213
|
+
}
|
|
214
|
+
// Scalars
|
|
215
|
+
else if (isStrapiScalar(attribute)) {
|
|
216
|
+
// @ts-ignore
|
|
217
|
+
addScalarAttribute(options);
|
|
218
|
+
}
|
|
219
|
+
// Components
|
|
220
|
+
else if (isComponent(attribute)) {
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
addComponentAttribute(options);
|
|
223
|
+
}
|
|
224
|
+
// Dynamic Zones
|
|
225
|
+
else if (isDynamicZone(attribute)) {
|
|
226
|
+
// @ts-ignore
|
|
227
|
+
addDynamicZoneAttribute(options);
|
|
228
|
+
}
|
|
229
|
+
// Media
|
|
230
|
+
else if (isMedia(attribute)) {
|
|
231
|
+
// @ts-ignore
|
|
232
|
+
addMediaAttribute(options);
|
|
233
|
+
}
|
|
234
|
+
// Polymorphic Relations
|
|
235
|
+
else if (isMorphRelation(attribute)) {
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
addPolymorphicRelationalAttribute(options);
|
|
238
|
+
}
|
|
239
|
+
// Regular Relations
|
|
240
|
+
else if (isRelation(attribute)) {
|
|
241
|
+
// @ts-ignore
|
|
242
|
+
addRegularRelationalAttribute(options);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
exports.overrideField = overrideField;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Easily resolve a entity
|
|
3
|
+
*
|
|
4
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
|
|
5
|
+
*/
|
|
6
|
+
import { Entity, ResolveArgs } from './types';
|
|
7
|
+
type ResolveEntityArgs = Omit<ResolveArgs, 'args'> & {
|
|
8
|
+
args: {
|
|
9
|
+
id: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare const resolveEntity: <T extends Object>(contentType: string, resolveArgs: ResolveEntityArgs) => Promise<Entity<T>>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Easily resolve a entity
|
|
4
|
+
*
|
|
5
|
+
* Based on node_modules/@strapi/plugin-graphql/server/services/builders/type.js
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.resolveEntity = void 0;
|
|
9
|
+
const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
|
|
10
|
+
const { toEntityResponse } = strapi.plugin('graphql').service('format').returnTypes;
|
|
11
|
+
const resolveEntity = async (contentType, resolveArgs) => {
|
|
12
|
+
const { buildQueriesResolvers } = strapi.plugin('graphql').service('builders').get('content-api');
|
|
13
|
+
const transformedArgs = transformArgs(resolveArgs.args, { contentType });
|
|
14
|
+
const { findOne } = buildQueriesResolvers({ contentType });
|
|
15
|
+
const item = await findOne(resolveArgs.parent, transformedArgs, resolveArgs.context);
|
|
16
|
+
return toEntityResponse(item, {
|
|
17
|
+
args: resolveArgs.args,
|
|
18
|
+
resourceUID: contentType,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
exports.resolveEntity = resolveEntity;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GraphQLResolveInfo } from "graphql";
|
|
2
|
+
export type ResolveArgs<Parent = unknown, Args = unknown, Context = unknown, Info = GraphQLResolveInfo> = {
|
|
3
|
+
parent: Parent;
|
|
4
|
+
args: Args;
|
|
5
|
+
context: Context;
|
|
6
|
+
info: Info;
|
|
7
|
+
};
|
|
8
|
+
export type Entity<T extends Object> = {
|
|
9
|
+
id: string;
|
|
10
|
+
attributes: Omit<T, 'id'>;
|
|
11
|
+
};
|