@strapi/plugin-graphql 4.0.0-next.6 → 4.0.0
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 +1 -1
- package/admin/src/index.js +0 -8
- package/package.json +39 -32
- package/server/bootstrap.js +148 -0
- package/server/config/default-config.js +13 -0
- package/server/config/index.js +7 -0
- package/server/format-graphql-error.js +50 -0
- package/server/services/builders/dynamic-zones.js +97 -0
- package/server/services/builders/entity-meta.js +7 -0
- package/server/services/builders/entity.js +43 -0
- package/server/services/builders/enums.js +24 -0
- package/server/services/builders/filters/content-type.js +93 -0
- package/server/services/builders/filters/index.js +7 -0
- package/server/services/builders/filters/operators/and.js +15 -0
- package/server/services/builders/filters/operators/between.js +15 -0
- package/server/services/builders/filters/operators/contains.js +13 -0
- package/server/services/builders/filters/operators/containsi.js +13 -0
- package/server/services/builders/filters/operators/ends-with.js +13 -0
- package/server/services/builders/filters/operators/eq.js +23 -0
- package/server/services/builders/filters/operators/gt.js +13 -0
- package/server/services/builders/filters/operators/gte.js +13 -0
- package/server/services/builders/filters/operators/in.js +15 -0
- package/server/services/builders/filters/operators/index.js +38 -0
- package/server/services/builders/filters/operators/lt.js +13 -0
- package/server/services/builders/filters/operators/lte.js +13 -0
- package/server/services/builders/filters/operators/ne.js +13 -0
- package/server/services/builders/filters/operators/not-contains.js +13 -0
- package/server/services/builders/filters/operators/not-containsi.js +13 -0
- package/server/services/builders/filters/operators/not-in.js +15 -0
- package/server/services/builders/filters/operators/not-null.js +13 -0
- package/server/services/builders/filters/operators/not.js +19 -0
- package/server/services/builders/filters/operators/null.js +13 -0
- package/server/services/builders/filters/operators/or.js +15 -0
- package/server/services/builders/filters/operators/starts-with.js +13 -0
- package/server/services/builders/generic-morph.js +41 -0
- package/server/services/builders/index.js +92 -0
- package/server/services/builders/input.js +121 -0
- package/server/services/builders/mutations/collection-type.js +191 -0
- package/server/services/builders/mutations/index.js +9 -0
- package/server/services/builders/mutations/single-type.js +141 -0
- package/server/services/builders/queries/collection-type.js +120 -0
- package/server/services/builders/queries/index.js +9 -0
- package/server/services/builders/queries/single-type.js +70 -0
- package/server/services/builders/relation-response-collection.js +35 -0
- package/server/services/builders/resolvers/association.js +85 -0
- package/server/services/builders/resolvers/component.js +18 -0
- package/server/services/builders/resolvers/dynamic-zone.js +9 -0
- package/server/services/builders/resolvers/index.js +18 -0
- package/server/services/builders/resolvers/mutation.js +33 -0
- package/server/services/builders/resolvers/query.js +19 -0
- package/server/services/builders/response-collection.js +43 -0
- package/server/services/builders/response.js +32 -0
- package/server/services/builders/type.js +364 -0
- package/server/services/builders/utils.js +134 -0
- package/server/services/constants.js +147 -0
- package/server/services/content-api/index.js +179 -0
- package/server/services/content-api/policy.js +60 -0
- package/server/services/content-api/register-functions/collection-type.js +72 -0
- package/server/services/content-api/register-functions/component.js +15 -0
- package/server/services/content-api/register-functions/content-type/dynamic-zones.js +36 -0
- package/server/services/content-api/register-functions/content-type/enums.js +33 -0
- package/server/services/content-api/register-functions/content-type/filters.js +15 -0
- package/server/services/content-api/register-functions/content-type/index.js +13 -0
- package/server/services/content-api/register-functions/content-type/inputs.js +21 -0
- package/server/services/content-api/register-functions/index.js +22 -0
- package/server/services/content-api/register-functions/internals.js +13 -0
- package/server/services/content-api/register-functions/polymorphic.js +69 -0
- package/server/services/content-api/register-functions/scalars.js +14 -0
- package/server/services/content-api/register-functions/single-type.js +72 -0
- package/server/services/content-api/wrap-resolvers.js +144 -0
- package/server/services/extension/extension.js +95 -0
- package/server/services/extension/index.js +5 -0
- package/server/services/extension/shadow-crud-manager.js +159 -0
- package/server/services/format/index.js +7 -0
- package/server/services/format/return-types.js +27 -0
- package/server/services/index.js +21 -0
- package/server/services/internals/args/index.js +11 -0
- package/server/services/internals/args/pagination.js +19 -0
- package/server/services/internals/args/publication-state.js +12 -0
- package/server/services/internals/args/sort.js +10 -0
- package/server/services/internals/helpers/get-enabled-scalars.js +15 -0
- package/server/services/internals/helpers/index.js +7 -0
- package/server/services/internals/index.js +13 -0
- package/server/services/internals/scalars/index.js +18 -0
- package/server/services/internals/scalars/time.js +36 -0
- package/server/services/internals/types/error.js +34 -0
- package/server/services/internals/types/filters.js +39 -0
- package/server/services/internals/types/index.js +29 -0
- package/server/services/internals/types/pagination.js +24 -0
- package/server/services/internals/types/publication-state.js +24 -0
- package/server/services/internals/types/response-collection-meta.js +38 -0
- package/server/services/type-registry.js +104 -0
- package/server/services/utils/attributes.js +84 -0
- package/server/services/utils/index.js +11 -0
- package/server/services/utils/mappers/entity-to-response-entity.js +12 -0
- package/server/services/utils/mappers/graphql-filters-to-strapi-query.js +109 -0
- package/server/services/utils/mappers/graphql-scalar-to-operators.js +17 -0
- package/server/services/utils/mappers/index.js +13 -0
- package/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.js +25 -0
- package/server/services/utils/naming.js +287 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +13 -0
- package/admin/src/assets/images/logo.svg +0 -38
- package/config/routes.json +0 -3
- package/config/schema.graphql +0 -1
- package/config/settings.json +0 -12
- package/controllers/GraphQL.js +0 -9
- package/hooks/graphql/defaults.json +0 -5
- package/hooks/graphql/index.js +0 -174
- package/hooks/graphql/load-config.js +0 -42
- package/services/build-aggregation.js +0 -565
- package/services/data-loaders.js +0 -55
- package/services/naming.js +0 -15
- package/services/resolvers-builder.js +0 -204
- package/services/schema-definitions.js +0 -131
- package/services/schema-generator.js +0 -178
- package/services/shadow-crud.js +0 -612
- package/services/type-builder.js +0 -311
- package/services/utils.js +0 -200
- package/types/dynamiczoneScalar.js +0 -40
- package/types/publication-state.js +0 -16
- package/types/time.js +0 -26
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ValidationError } = require('@strapi/utils').errors;
|
|
4
|
+
|
|
5
|
+
const EQ_FIELD_NAME = 'eq';
|
|
6
|
+
|
|
7
|
+
module.exports = ({ strapi }) => ({
|
|
8
|
+
fieldName: EQ_FIELD_NAME,
|
|
9
|
+
|
|
10
|
+
strapiOperator: '$eq',
|
|
11
|
+
|
|
12
|
+
add(t, type) {
|
|
13
|
+
const { GRAPHQL_SCALARS } = strapi.plugin('graphql').service('constants');
|
|
14
|
+
|
|
15
|
+
if (!GRAPHQL_SCALARS.includes(type)) {
|
|
16
|
+
throw new ValidationError(
|
|
17
|
+
`Can't use "${EQ_FIELD_NAME}" operator. "${type}" is not a valid scalar`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
t.field(EQ_FIELD_NAME, { type });
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { list } = require('nexus');
|
|
4
|
+
|
|
5
|
+
const IN_FIELD_NAME = 'in';
|
|
6
|
+
|
|
7
|
+
module.exports = () => ({
|
|
8
|
+
fieldName: IN_FIELD_NAME,
|
|
9
|
+
|
|
10
|
+
strapiOperator: '$in',
|
|
11
|
+
|
|
12
|
+
add(t, type) {
|
|
13
|
+
t.field(IN_FIELD_NAME, { type: list(type) });
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { mapValues } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
const operators = {
|
|
6
|
+
and: require('./and'),
|
|
7
|
+
or: require('./or'),
|
|
8
|
+
not: require('./not'),
|
|
9
|
+
|
|
10
|
+
eq: require('./eq'),
|
|
11
|
+
ne: require('./ne'),
|
|
12
|
+
|
|
13
|
+
startsWith: require('./starts-with'),
|
|
14
|
+
endsWith: require('./ends-with'),
|
|
15
|
+
|
|
16
|
+
contains: require('./contains'),
|
|
17
|
+
notContains: require('./not-contains'),
|
|
18
|
+
|
|
19
|
+
containsi: require('./containsi'),
|
|
20
|
+
notContainsi: require('./not-containsi'),
|
|
21
|
+
|
|
22
|
+
gt: require('./gt'),
|
|
23
|
+
gte: require('./gte'),
|
|
24
|
+
|
|
25
|
+
lt: require('./lt'),
|
|
26
|
+
lte: require('./lte'),
|
|
27
|
+
|
|
28
|
+
null: require('./null'),
|
|
29
|
+
notNull: require('./not-null'),
|
|
30
|
+
|
|
31
|
+
in: require('./in'),
|
|
32
|
+
notIn: require('./not-in'),
|
|
33
|
+
|
|
34
|
+
between: require('./between'),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Instantiate every operator with the Strapi instance
|
|
38
|
+
module.exports = context => mapValues(opCtor => opCtor(context), operators);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { list } = require('nexus');
|
|
4
|
+
|
|
5
|
+
const NOT_IN_FIELD_NAME = 'notIn';
|
|
6
|
+
|
|
7
|
+
module.exports = () => ({
|
|
8
|
+
fieldName: NOT_IN_FIELD_NAME,
|
|
9
|
+
|
|
10
|
+
strapiOperator: '$notIn',
|
|
11
|
+
|
|
12
|
+
add(t, type) {
|
|
13
|
+
t.field(NOT_IN_FIELD_NAME, { type: list(type) });
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const NOT_FIELD_NAME = 'not';
|
|
4
|
+
|
|
5
|
+
module.exports = ({ strapi }) => ({
|
|
6
|
+
fieldName: NOT_FIELD_NAME,
|
|
7
|
+
|
|
8
|
+
strapiOperator: '$not',
|
|
9
|
+
|
|
10
|
+
add(t, type) {
|
|
11
|
+
const { naming, attributes } = strapi.plugin('graphql').service('utils');
|
|
12
|
+
|
|
13
|
+
if (attributes.isGraphQLScalar({ type })) {
|
|
14
|
+
t.field(NOT_FIELD_NAME, { type: naming.getScalarFilterInputTypeName(type) });
|
|
15
|
+
} else {
|
|
16
|
+
t.field(NOT_FIELD_NAME, { type });
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { list } = require('nexus');
|
|
4
|
+
|
|
5
|
+
const OR_FIELD_NAME = 'or';
|
|
6
|
+
|
|
7
|
+
module.exports = () => ({
|
|
8
|
+
fieldName: OR_FIELD_NAME,
|
|
9
|
+
|
|
10
|
+
strapiOperator: '$or',
|
|
11
|
+
|
|
12
|
+
add(t, type) {
|
|
13
|
+
t.field(OR_FIELD_NAME, { type: list(type) });
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { unionType } = require('nexus');
|
|
4
|
+
const { prop } = require('lodash/fp');
|
|
5
|
+
|
|
6
|
+
module.exports = ({ strapi, registry }) => {
|
|
7
|
+
const { naming } = strapi.plugin('graphql').service('utils');
|
|
8
|
+
const { KINDS, GENERIC_MORPH_TYPENAME } = strapi.plugin('graphql').service('constants');
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
buildGenericMorphDefinition() {
|
|
12
|
+
return unionType({
|
|
13
|
+
name: GENERIC_MORPH_TYPENAME,
|
|
14
|
+
|
|
15
|
+
resolveType(obj) {
|
|
16
|
+
const contentType = strapi.getModel(obj.__type);
|
|
17
|
+
|
|
18
|
+
if (!contentType) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (contentType.modelType === 'component') {
|
|
23
|
+
return naming.getComponentName(contentType);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return naming.getTypeName(contentType);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
definition(t) {
|
|
30
|
+
const members = registry
|
|
31
|
+
// Resolve every content-type or component
|
|
32
|
+
.where(({ config }) => [KINDS.type, KINDS.component].includes(config.kind))
|
|
33
|
+
// Only keep their name (the type's id)
|
|
34
|
+
.map(prop('name'));
|
|
35
|
+
|
|
36
|
+
t.members(...members);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { merge, map, pipe, reduce } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
// Builders Factories
|
|
6
|
+
|
|
7
|
+
const enums = require('./enums');
|
|
8
|
+
const dynamicZone = require('./dynamic-zones');
|
|
9
|
+
const entity = require('./entity');
|
|
10
|
+
const entityMeta = require('./entity-meta');
|
|
11
|
+
const type = require('./type');
|
|
12
|
+
const response = require('./response');
|
|
13
|
+
const responseCollection = require('./response-collection');
|
|
14
|
+
const relationResponseCollection = require('./relation-response-collection');
|
|
15
|
+
const queries = require('./queries');
|
|
16
|
+
const mutations = require('./mutations');
|
|
17
|
+
const filters = require('./filters');
|
|
18
|
+
const inputs = require('./input');
|
|
19
|
+
const genericMorph = require('./generic-morph');
|
|
20
|
+
const resolvers = require('./resolvers');
|
|
21
|
+
|
|
22
|
+
// Misc
|
|
23
|
+
|
|
24
|
+
const operators = require('./filters/operators');
|
|
25
|
+
const utils = require('./utils');
|
|
26
|
+
|
|
27
|
+
const buildersFactories = [
|
|
28
|
+
enums,
|
|
29
|
+
dynamicZone,
|
|
30
|
+
entity,
|
|
31
|
+
entityMeta,
|
|
32
|
+
type,
|
|
33
|
+
response,
|
|
34
|
+
responseCollection,
|
|
35
|
+
relationResponseCollection,
|
|
36
|
+
queries,
|
|
37
|
+
mutations,
|
|
38
|
+
filters,
|
|
39
|
+
inputs,
|
|
40
|
+
genericMorph,
|
|
41
|
+
resolvers,
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
module.exports = ({ strapi }) => {
|
|
45
|
+
const buildersMap = new Map();
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
/**
|
|
49
|
+
* Instantiate every builder with a strapi instance & a type registry
|
|
50
|
+
* @param {string} name
|
|
51
|
+
* @param {object} registry
|
|
52
|
+
*/
|
|
53
|
+
new(name, registry) {
|
|
54
|
+
const context = { strapi, registry };
|
|
55
|
+
|
|
56
|
+
const builders = pipe(
|
|
57
|
+
// Create a new instance of every builders
|
|
58
|
+
map(factory => factory(context)),
|
|
59
|
+
// Merge every builder into the same object
|
|
60
|
+
reduce(merge, {})
|
|
61
|
+
).call(null, buildersFactories);
|
|
62
|
+
|
|
63
|
+
buildersMap.set(name, builders);
|
|
64
|
+
|
|
65
|
+
return builders;
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Delete a set of builders instances from
|
|
70
|
+
* the builders map for a given name
|
|
71
|
+
* @param {string} name
|
|
72
|
+
*/
|
|
73
|
+
delete(name) {
|
|
74
|
+
buildersMap.delete(name);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Retrieve a set of builders instances from
|
|
79
|
+
* the builders map for a given name
|
|
80
|
+
* @param {string} name
|
|
81
|
+
*/
|
|
82
|
+
get(name) {
|
|
83
|
+
return buildersMap.get(name);
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
filters: {
|
|
87
|
+
operators: operators({ strapi }),
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
utils: utils({ strapi }),
|
|
91
|
+
};
|
|
92
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { inputObjectType, nonNull } = require('nexus');
|
|
4
|
+
const {
|
|
5
|
+
contentTypes: { isWritableAttribute },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
|
|
8
|
+
module.exports = context => {
|
|
9
|
+
const { strapi } = context;
|
|
10
|
+
|
|
11
|
+
const { naming, mappers, attributes } = strapi.plugin('graphql').service('utils');
|
|
12
|
+
const extension = strapi.plugin('graphql').service('extension');
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
getComponentInputName,
|
|
16
|
+
getContentTypeInputName,
|
|
17
|
+
getEnumName,
|
|
18
|
+
getDynamicZoneInputName,
|
|
19
|
+
} = naming;
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
isStrapiScalar,
|
|
23
|
+
isRelation,
|
|
24
|
+
isMorphRelation,
|
|
25
|
+
isMedia,
|
|
26
|
+
isEnumeration,
|
|
27
|
+
isComponent,
|
|
28
|
+
isDynamicZone,
|
|
29
|
+
} = attributes;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
buildInputType(contentType) {
|
|
33
|
+
const { attributes, modelType } = contentType;
|
|
34
|
+
|
|
35
|
+
const name = (modelType === 'component'
|
|
36
|
+
? getComponentInputName
|
|
37
|
+
: getContentTypeInputName
|
|
38
|
+
).call(null, contentType);
|
|
39
|
+
|
|
40
|
+
return inputObjectType({
|
|
41
|
+
name,
|
|
42
|
+
|
|
43
|
+
definition(t) {
|
|
44
|
+
const isFieldEnabled = fieldName => {
|
|
45
|
+
return extension
|
|
46
|
+
.shadowCRUD(contentType.uid)
|
|
47
|
+
.field(fieldName)
|
|
48
|
+
.hasInputEnabled();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const validAttributes = Object.entries(attributes).filter(([attributeName]) => {
|
|
52
|
+
return isWritableAttribute(contentType, attributeName) && isFieldEnabled(attributeName);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Add the ID for the component to enable inplace updates
|
|
56
|
+
if (modelType === 'component' && isFieldEnabled('id')) {
|
|
57
|
+
t.id('id');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
validAttributes.forEach(([attributeName, attribute]) => {
|
|
61
|
+
// Scalars
|
|
62
|
+
if (isStrapiScalar(attribute)) {
|
|
63
|
+
const gqlScalar = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
64
|
+
|
|
65
|
+
t.field(attributeName, { type: gqlScalar });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Media
|
|
69
|
+
else if (isMedia(attribute)) {
|
|
70
|
+
const isMultiple = attribute.multiple === true;
|
|
71
|
+
|
|
72
|
+
if (extension.shadowCRUD('plugin::upload.file').isDisabled()) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
isMultiple ? t.list.id(attributeName) : t.id(attributeName);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Regular Relations (ignore polymorphic relations)
|
|
80
|
+
else if (isRelation(attribute) && !isMorphRelation(attribute)) {
|
|
81
|
+
if (extension.shadowCRUD(attribute.target).isDisabled()) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
86
|
+
|
|
87
|
+
isToManyRelation ? t.list.id(attributeName) : t.id(attributeName);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Enums
|
|
91
|
+
else if (isEnumeration(attribute)) {
|
|
92
|
+
const enumTypeName = getEnumName(contentType, attributeName);
|
|
93
|
+
|
|
94
|
+
t.field(attributeName, { type: enumTypeName });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Components
|
|
98
|
+
else if (isComponent(attribute)) {
|
|
99
|
+
const isRepeatable = attribute.repeatable === true;
|
|
100
|
+
const component = strapi.components[attribute.component];
|
|
101
|
+
const componentInputType = getComponentInputName(component);
|
|
102
|
+
|
|
103
|
+
if (isRepeatable) {
|
|
104
|
+
t.list.field(attributeName, { type: componentInputType });
|
|
105
|
+
} else {
|
|
106
|
+
t.field(attributeName, { type: componentInputType });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Dynamic Zones
|
|
111
|
+
else if (isDynamicZone(attribute)) {
|
|
112
|
+
const dzInputName = getDynamicZoneInputName(contentType, attributeName);
|
|
113
|
+
|
|
114
|
+
t.list.field(attributeName, { type: nonNull(dzInputName) });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
};
|