@strapi/plugin-graphql 4.0.0-next.2 → 4.0.0-next.20

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.
Files changed (117) hide show
  1. package/admin/src/translations/zh-Hans.json +4 -0
  2. package/package.json +17 -15
  3. package/server/bootstrap.js +124 -0
  4. package/server/services/builders/dynamic-zones.js +96 -0
  5. package/server/services/builders/entity-meta.js +7 -0
  6. package/server/services/builders/entity.js +43 -0
  7. package/server/services/builders/enums.js +24 -0
  8. package/server/services/builders/filters/content-type.js +84 -0
  9. package/server/services/builders/filters/index.js +7 -0
  10. package/server/services/builders/filters/operators/and.js +15 -0
  11. package/server/services/builders/filters/operators/between.js +15 -0
  12. package/server/services/builders/filters/operators/contains.js +13 -0
  13. package/server/services/builders/filters/operators/containsi.js +13 -0
  14. package/server/services/builders/filters/operators/ends-with.js +13 -0
  15. package/server/services/builders/filters/operators/eq.js +19 -0
  16. package/server/services/builders/filters/operators/gt.js +13 -0
  17. package/server/services/builders/filters/operators/gte.js +13 -0
  18. package/server/services/builders/filters/operators/in.js +15 -0
  19. package/server/services/builders/filters/operators/index.js +38 -0
  20. package/server/services/builders/filters/operators/lt.js +13 -0
  21. package/server/services/builders/filters/operators/lte.js +13 -0
  22. package/server/services/builders/filters/operators/ne.js +13 -0
  23. package/server/services/builders/filters/operators/not-contains.js +13 -0
  24. package/server/services/builders/filters/operators/not-containsi.js +13 -0
  25. package/server/services/builders/filters/operators/not-in.js +15 -0
  26. package/server/services/builders/filters/operators/not-null.js +13 -0
  27. package/server/services/builders/filters/operators/not.js +19 -0
  28. package/server/services/builders/filters/operators/null.js +13 -0
  29. package/server/services/builders/filters/operators/or.js +15 -0
  30. package/server/services/builders/filters/operators/starts-with.js +13 -0
  31. package/server/services/builders/generic-morph.js +41 -0
  32. package/server/services/builders/index.js +92 -0
  33. package/server/services/builders/input.js +118 -0
  34. package/server/services/builders/mutations/collection-type.js +170 -0
  35. package/server/services/builders/mutations/index.js +9 -0
  36. package/server/services/builders/mutations/single-type.js +135 -0
  37. package/server/services/builders/queries/collection-type.js +120 -0
  38. package/server/services/builders/queries/index.js +9 -0
  39. package/server/services/builders/queries/single-type.js +70 -0
  40. package/server/services/builders/relation-response-collection.js +35 -0
  41. package/server/services/builders/resolvers/association.js +64 -0
  42. package/server/services/builders/resolvers/component.js +14 -0
  43. package/server/services/builders/resolvers/dynamic-zone.js +9 -0
  44. package/server/services/builders/resolvers/index.js +18 -0
  45. package/server/services/builders/resolvers/mutation.js +33 -0
  46. package/server/services/builders/resolvers/query.js +19 -0
  47. package/server/services/builders/response-collection.js +43 -0
  48. package/server/services/builders/response.js +32 -0
  49. package/server/services/builders/type.js +370 -0
  50. package/server/services/builders/utils.js +131 -0
  51. package/server/services/constants.js +147 -0
  52. package/server/services/content-api/index.js +168 -0
  53. package/server/services/content-api/policy.js +59 -0
  54. package/server/services/content-api/register-functions/collection-type.js +72 -0
  55. package/server/services/content-api/register-functions/component.js +15 -0
  56. package/server/services/content-api/register-functions/content-type/dynamic-zones.js +36 -0
  57. package/server/services/content-api/register-functions/content-type/enums.js +33 -0
  58. package/server/services/content-api/register-functions/content-type/filters.js +15 -0
  59. package/server/services/content-api/register-functions/content-type/index.js +13 -0
  60. package/server/services/content-api/register-functions/content-type/inputs.js +21 -0
  61. package/server/services/content-api/register-functions/index.js +22 -0
  62. package/server/services/content-api/register-functions/internals.js +13 -0
  63. package/server/services/content-api/register-functions/polymorphic.js +69 -0
  64. package/server/services/content-api/register-functions/scalars.js +14 -0
  65. package/server/services/content-api/register-functions/single-type.js +72 -0
  66. package/server/services/content-api/wrap-resolvers.js +146 -0
  67. package/server/services/extension/extension.js +95 -0
  68. package/server/services/extension/index.js +5 -0
  69. package/server/services/extension/shadow-crud-manager.js +159 -0
  70. package/server/services/format/index.js +7 -0
  71. package/server/services/format/return-types.js +27 -0
  72. package/server/services/index.js +21 -0
  73. package/server/services/internals/args/index.js +11 -0
  74. package/server/services/internals/args/pagination.js +19 -0
  75. package/server/services/internals/args/publication-state.js +12 -0
  76. package/server/services/internals/args/sort.js +10 -0
  77. package/server/services/internals/helpers/get-enabled-scalars.js +15 -0
  78. package/server/services/internals/helpers/index.js +7 -0
  79. package/server/services/internals/index.js +13 -0
  80. package/server/services/internals/scalars/index.js +18 -0
  81. package/server/services/internals/scalars/time.js +35 -0
  82. package/server/services/internals/types/error.js +33 -0
  83. package/server/services/internals/types/filters.js +39 -0
  84. package/server/services/internals/types/index.js +29 -0
  85. package/server/services/internals/types/pagination.js +24 -0
  86. package/server/services/internals/types/publication-state.js +24 -0
  87. package/server/services/internals/types/response-collection-meta.js +38 -0
  88. package/server/services/type-registry.js +103 -0
  89. package/server/services/utils/attributes.js +84 -0
  90. package/server/services/utils/index.js +11 -0
  91. package/server/services/utils/mappers/entity-to-response-entity.js +12 -0
  92. package/server/services/utils/mappers/graphql-filters-to-strapi-query.js +107 -0
  93. package/server/services/utils/mappers/graphql-scalar-to-operators.js +17 -0
  94. package/server/services/utils/mappers/index.js +13 -0
  95. package/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.js +24 -0
  96. package/server/services/utils/naming.js +282 -0
  97. package/strapi-admin.js +3 -0
  98. package/strapi-server.js +11 -0
  99. package/config/routes.json +0 -3
  100. package/config/schema.graphql +0 -1
  101. package/config/settings.json +0 -12
  102. package/controllers/GraphQL.js +0 -9
  103. package/hooks/graphql/defaults.json +0 -5
  104. package/hooks/graphql/index.js +0 -174
  105. package/hooks/graphql/load-config.js +0 -42
  106. package/services/build-aggregation.js +0 -565
  107. package/services/data-loaders.js +0 -55
  108. package/services/naming.js +0 -15
  109. package/services/resolvers-builder.js +0 -204
  110. package/services/schema-definitions.js +0 -131
  111. package/services/schema-generator.js +0 -178
  112. package/services/shadow-crud.js +0 -612
  113. package/services/type-builder.js +0 -311
  114. package/services/utils.js +0 -200
  115. package/types/dynamiczoneScalar.js +0 -40
  116. package/types/publication-state.js +0 -16
  117. package/types/time.js +0 -26
@@ -0,0 +1,168 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ mergeSchemas,
5
+ makeExecutableSchema,
6
+ addResolversToSchema,
7
+ } = require('@graphql-tools/schema');
8
+ const { makeSchema } = require('nexus');
9
+ const { pipe, prop, startsWith } = require('lodash/fp');
10
+
11
+ const { wrapResolvers } = require('./wrap-resolvers');
12
+ const {
13
+ registerSingleType,
14
+ registerCollectionType,
15
+ registerComponent,
16
+ registerScalars,
17
+ registerInternals,
18
+ registerPolymorphicContentType,
19
+ contentType: {
20
+ registerEnumsDefinition,
21
+ registerInputsDefinition,
22
+ registerFiltersDefinition,
23
+ registerDynamicZonesDefinition,
24
+ },
25
+ } = require('./register-functions');
26
+
27
+ module.exports = ({ strapi }) => {
28
+ const { service: getGraphQLService } = strapi.plugin('graphql');
29
+ const { config } = strapi.plugin('graphql');
30
+
31
+ const { KINDS, GENERIC_MORPH_TYPENAME } = getGraphQLService('constants');
32
+
33
+ // Type Registry
34
+ let registry;
35
+ // Builders Instances
36
+ let builders;
37
+
38
+ const buildSchema = () => {
39
+ const extensionService = getGraphQLService('extension');
40
+
41
+ const isShadowCRUDEnabled = !!config('shadowCRUD', true);
42
+
43
+ // Create a new empty type registry
44
+ registry = getGraphQLService('type-registry').new();
45
+
46
+ // Reset the builders instances associated to the
47
+ // content-api, and link the new type registry
48
+ builders = getGraphQLService('builders').new('content-api', registry);
49
+
50
+ registerScalars({ registry, strapi });
51
+ registerInternals({ registry, strapi });
52
+
53
+ if (isShadowCRUDEnabled) {
54
+ shadowCRUD();
55
+ }
56
+
57
+ // Generate the extension configuration for the content API
58
+ const extension = extensionService.generate({ typeRegistry: registry });
59
+
60
+ return pipe(
61
+ // Build a collection of schema based on the
62
+ // type registry & the extension configuration
63
+ buildSchemas,
64
+ // Merge every created schema into a single one
65
+ schemas => mergeSchemas({ schemas }),
66
+ // Add the extension's resolvers to the final schema
67
+ schema => addResolversToSchema(schema, extension.resolvers),
68
+ // Wrap resolvers if needed (auth, middlewares, policies...) as configured in the extension
69
+ schema => wrapResolvers({ schema, strapi, extension })
70
+ )({ registry, extension });
71
+ };
72
+
73
+ const buildSchemas = ({ registry, extension }) => {
74
+ const { types, plugins, typeDefs = [] } = extension;
75
+
76
+ // Create a new Nexus schema (shadow CRUD) & add it to the schemas collection
77
+ const nexusSchema = makeSchema({
78
+ types: [
79
+ // Add the auto-generated Nexus types (shadow CRUD)
80
+ registry.definitions,
81
+ // Add every Nexus type registered using the extension service
82
+ types,
83
+ ],
84
+
85
+ plugins: [
86
+ // Add every plugin registered using the extension service
87
+ ...plugins,
88
+ ],
89
+ });
90
+
91
+ // Build schemas based on SDL type definitions (defined in the extension)
92
+ const sdlSchemas = typeDefs.map(sdl => makeExecutableSchema({ typeDefs: sdl }));
93
+
94
+ return [nexusSchema, ...sdlSchemas];
95
+ };
96
+
97
+ const shadowCRUD = () => {
98
+ const extensionService = getGraphQLService('extension');
99
+
100
+ // Get every content type & component defined in Strapi
101
+ const contentTypes = [
102
+ ...Object.values(strapi.components),
103
+ ...Object.values(strapi.contentTypes),
104
+ ];
105
+
106
+ // Disable Shadow CRUD for admin content types
107
+ contentTypes
108
+ .map(prop('uid'))
109
+ .filter(startsWith('admin::'))
110
+ .forEach(uid => extensionService.shadowCRUD(uid).disable());
111
+
112
+ const contentTypesWithShadowCRUD = contentTypes.filter(ct =>
113
+ extensionService.shadowCRUD(ct.uid).isEnabled()
114
+ );
115
+
116
+ // Generate and register definitions for every content type
117
+ registerAPITypes(contentTypesWithShadowCRUD);
118
+
119
+ // Generate and register polymorphic types' definitions
120
+ registerMorphTypes(contentTypesWithShadowCRUD);
121
+ };
122
+
123
+ /**
124
+ * Register needed GraphQL types for every content type
125
+ * @param {object[]} contentTypes
126
+ */
127
+ const registerAPITypes = contentTypes => {
128
+ for (const contentType of contentTypes) {
129
+ const { kind, modelType } = contentType;
130
+
131
+ const registerOptions = { registry, strapi, builders };
132
+
133
+ // Generate various types associated to the content type
134
+ // (enums, dynamic-zones, filters, inputs...)
135
+ registerEnumsDefinition(contentType, registerOptions);
136
+ registerDynamicZonesDefinition(contentType, registerOptions);
137
+ registerFiltersDefinition(contentType, registerOptions);
138
+ registerInputsDefinition(contentType, registerOptions);
139
+
140
+ // Generate & register component's definition
141
+ if (modelType === 'component') {
142
+ registerComponent(contentType, registerOptions);
143
+ }
144
+
145
+ // Generate & register single type's definition
146
+ else if (kind === 'singleType') {
147
+ registerSingleType(contentType, registerOptions);
148
+ }
149
+
150
+ // Generate & register collection type's definition
151
+ else if (kind === 'collectionType') {
152
+ registerCollectionType(contentType, registerOptions);
153
+ }
154
+ }
155
+ };
156
+
157
+ const registerMorphTypes = contentTypes => {
158
+ // Create & register a union type that includes every type or component registered
159
+ const genericMorphType = builders.buildGenericMorphDefinition();
160
+ registry.register(GENERIC_MORPH_TYPENAME, genericMorphType, { kind: KINDS.morph });
161
+
162
+ for (const contentType of contentTypes) {
163
+ registerPolymorphicContentType(contentType, { registry, strapi });
164
+ }
165
+ };
166
+
167
+ return { buildSchema };
168
+ };
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const { getOr } = require('lodash/fp');
4
+ const { policy: policyUtils } = require('@strapi/utils');
5
+
6
+ const createPoliciesMiddleware = (resolverConfig, { strapi }) => {
7
+ return async (resolve, ...rest) => {
8
+ const resolverPolicies = getOr([], 'policies', resolverConfig);
9
+
10
+ // Transform every policy into a unique format
11
+ const policies = resolverPolicies.map(policy => policyUtils.get(policy));
12
+
13
+ // Create a graphql policy context
14
+ const context = createGraphQLPolicyContext(...rest);
15
+
16
+ // Run policies & throw an error if one of them fails
17
+ for (const policy of policies) {
18
+ const result = await policy({ context, strapi });
19
+
20
+ if (!result) {
21
+ throw new Error('Policies failed');
22
+ }
23
+ }
24
+
25
+ return resolve(...rest);
26
+ };
27
+ };
28
+
29
+ const createGraphQLPolicyContext = (parent, args, context, info) => {
30
+ return policyUtils.createPolicyContext('graphql', {
31
+ get parent() {
32
+ return parent;
33
+ },
34
+
35
+ get args() {
36
+ return args;
37
+ },
38
+
39
+ get context() {
40
+ return context;
41
+ },
42
+
43
+ get info() {
44
+ return info;
45
+ },
46
+
47
+ get state() {
48
+ return this.context.state;
49
+ },
50
+
51
+ get http() {
52
+ return this.context.koaContext;
53
+ },
54
+ });
55
+ };
56
+
57
+ module.exports = {
58
+ createPoliciesMiddleware,
59
+ };
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const registerCollectionType = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { naming } = getService('utils');
7
+ const { KINDS } = getService('constants');
8
+
9
+ const extension = getService('extension');
10
+
11
+ // Types name (as string)
12
+ const types = {
13
+ base: naming.getTypeName(contentType),
14
+ entity: naming.getEntityName(contentType),
15
+ response: naming.getEntityResponseName(contentType),
16
+ responseCollection: naming.getEntityResponseCollectionName(contentType),
17
+ relationResponseCollection: naming.getRelationResponseCollectionName(contentType),
18
+ queries: naming.getEntityQueriesTypeName(contentType),
19
+ mutations: naming.getEntityMutationsTypeName(contentType),
20
+ };
21
+
22
+ const getConfig = kind => ({ kind, contentType });
23
+
24
+ // Type definition
25
+ registry.register(types.base, builders.buildTypeDefinition(contentType), getConfig(KINDS.type));
26
+
27
+ // Higher level entity definition
28
+ registry.register(
29
+ types.entity,
30
+ builders.buildEntityDefinition(contentType),
31
+ getConfig(KINDS.entity)
32
+ );
33
+
34
+ // Responses definition
35
+ registry.register(
36
+ types.response,
37
+ builders.buildResponseDefinition(contentType),
38
+ getConfig(KINDS.entityResponse)
39
+ );
40
+
41
+ registry.register(
42
+ types.responseCollection,
43
+ builders.buildResponseCollectionDefinition(contentType),
44
+ getConfig(KINDS.entityResponseCollection)
45
+ );
46
+
47
+ registry.register(
48
+ types.relationResponseCollection,
49
+ builders.buildRelationResponseCollectionDefinition(contentType),
50
+ getConfig(KINDS.relationResponseCollection)
51
+ );
52
+
53
+ if (extension.shadowCRUD(contentType.uid).areQueriesEnabled()) {
54
+ // Query extensions
55
+ registry.register(
56
+ types.queries,
57
+ builders.buildCollectionTypeQueries(contentType),
58
+ getConfig(KINDS.query)
59
+ );
60
+ }
61
+
62
+ if (extension.shadowCRUD(contentType.uid).areMutationsEnabled()) {
63
+ // Mutation extensions
64
+ registry.register(
65
+ types.mutations,
66
+ builders.buildCollectionTypeMutations(contentType),
67
+ getConfig(KINDS.mutation)
68
+ );
69
+ }
70
+ };
71
+
72
+ module.exports = { registerCollectionType };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const registerComponent = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { getComponentName } = getService('utils').naming;
7
+ const { KINDS } = getService('constants');
8
+
9
+ const name = getComponentName(contentType);
10
+ const definition = builders.buildTypeDefinition(contentType);
11
+
12
+ registry.register(name, definition, { kind: KINDS.component, contentType });
13
+ };
14
+
15
+ module.exports = { registerComponent };
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const registerDynamicZonesDefinition = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const {
7
+ naming,
8
+ attributes: { isDynamicZone },
9
+ } = getService('utils');
10
+ const { KINDS } = getService('constants');
11
+
12
+ const { attributes } = contentType;
13
+
14
+ const dynamicZoneAttributes = Object.keys(attributes).filter(attributeName =>
15
+ isDynamicZone(attributes[attributeName])
16
+ );
17
+
18
+ for (const attributeName of dynamicZoneAttributes) {
19
+ const attribute = attributes[attributeName];
20
+ const dzName = naming.getDynamicZoneName(contentType, attributeName);
21
+ const dzInputName = naming.getDynamicZoneInputName(contentType, attributeName);
22
+
23
+ const [type, input] = builders.buildDynamicZoneDefinition(attribute, dzName, dzInputName);
24
+
25
+ const baseConfig = {
26
+ contentType,
27
+ attributeName,
28
+ attribute,
29
+ };
30
+
31
+ registry.register(dzName, type, { kind: KINDS.dynamicZone, ...baseConfig });
32
+ registry.register(dzInputName, input, { kind: KINDS.input, ...baseConfig });
33
+ }
34
+ };
35
+
36
+ module.exports = { registerDynamicZonesDefinition };
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const registerEnumsDefinition = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const {
7
+ naming,
8
+ attributes: { isEnumeration },
9
+ } = getService('utils');
10
+ const { KINDS } = getService('constants');
11
+
12
+ const { attributes } = contentType;
13
+
14
+ const enumAttributes = Object.keys(attributes).filter(attributeName =>
15
+ isEnumeration(attributes[attributeName])
16
+ );
17
+
18
+ for (const attributeName of enumAttributes) {
19
+ const attribute = attributes[attributeName];
20
+
21
+ const enumName = naming.getEnumName(contentType, attributeName);
22
+ const enumDefinition = builders.buildEnumTypeDefinition(attribute, enumName);
23
+
24
+ registry.register(enumName, enumDefinition, {
25
+ kind: KINDS.enum,
26
+ contentType,
27
+ attributeName,
28
+ attribute,
29
+ });
30
+ }
31
+ };
32
+
33
+ module.exports = { registerEnumsDefinition };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const registerFiltersDefinition = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { getFiltersInputTypeName } = getService('utils').naming;
7
+ const { KINDS } = getService('constants');
8
+
9
+ const type = getFiltersInputTypeName(contentType);
10
+ const definition = builders.buildContentTypeFilters(contentType);
11
+
12
+ registry.register(type, definition, { kind: KINDS.filtersInput, contentType });
13
+ };
14
+
15
+ module.exports = { registerFiltersDefinition };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const { registerDynamicZonesDefinition } = require('./dynamic-zones');
4
+ const { registerEnumsDefinition } = require('./enums');
5
+ const { registerInputsDefinition } = require('./inputs');
6
+ const { registerFiltersDefinition } = require('./filters');
7
+
8
+ module.exports = {
9
+ registerDynamicZonesDefinition,
10
+ registerFiltersDefinition,
11
+ registerInputsDefinition,
12
+ registerEnumsDefinition,
13
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const registerInputsDefinition = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { getComponentInputName, getContentTypeInputName } = getService('utils').naming;
7
+ const { KINDS } = getService('constants');
8
+
9
+ const { modelType } = contentType;
10
+
11
+ const type = (modelType === 'component' ? getComponentInputName : getContentTypeInputName).call(
12
+ null,
13
+ contentType
14
+ );
15
+
16
+ const definition = builders.buildInputType(contentType);
17
+
18
+ registry.register(type, definition, { kind: KINDS.input, contentType });
19
+ };
20
+
21
+ module.exports = { registerInputsDefinition };
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const { registerCollectionType } = require('./collection-type');
4
+ const { registerSingleType } = require('./single-type');
5
+ const { registerComponent } = require('./component');
6
+ const { registerPolymorphicContentType } = require('./polymorphic');
7
+
8
+ const { registerScalars } = require('./scalars');
9
+ const { registerInternals } = require('./internals');
10
+
11
+ const contentType = require('./content-type');
12
+
13
+ module.exports = {
14
+ registerCollectionType,
15
+ registerSingleType,
16
+ registerComponent,
17
+ registerPolymorphicContentType,
18
+ registerInternals,
19
+ registerScalars,
20
+
21
+ contentType,
22
+ };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const registerInternals = ({ registry, strapi }) => {
4
+ const { buildInternalTypes } = strapi.plugin('graphql').service('internals');
5
+
6
+ const internalTypes = buildInternalTypes({ strapi });
7
+
8
+ for (const [kind, definitions] of Object.entries(internalTypes)) {
9
+ registry.registerMany(Object.entries(definitions), { kind });
10
+ }
11
+ };
12
+
13
+ module.exports = { registerInternals };
@@ -0,0 +1,69 @@
1
+ 'use strict';
2
+
3
+ const { unionType } = require('nexus');
4
+
5
+ const registerPolymorphicContentType = (contentType, { registry, strapi }) => {
6
+ const { service: getService } = strapi.plugin('graphql');
7
+
8
+ const {
9
+ naming,
10
+ attributes: { isMorphRelation },
11
+ } = getService('utils');
12
+ const { KINDS } = getService('constants');
13
+
14
+ const { attributes = {} } = contentType;
15
+
16
+ // Isolate its polymorphic attributes
17
+ const morphAttributes = Object.entries(attributes).filter(([, attribute]) =>
18
+ isMorphRelation(attribute)
19
+ );
20
+
21
+ // For each one of those polymorphic attribute
22
+ for (const [attributeName, attribute] of morphAttributes) {
23
+ const name = naming.getMorphRelationTypeName(contentType, attributeName);
24
+ const { target } = attribute;
25
+
26
+ // Ignore those whose target is not an array
27
+ if (!Array.isArray(target)) {
28
+ continue;
29
+ }
30
+
31
+ // Transform target UIDs into types names
32
+ const members = target
33
+ // Get content types definitions
34
+ .map(uid => strapi.getModel(uid))
35
+ // Resolve types names
36
+ .map(contentType => naming.getTypeName(contentType));
37
+
38
+ // Register the new polymorphic union type
39
+ registry.register(
40
+ name,
41
+
42
+ unionType({
43
+ name,
44
+
45
+ resolveType(obj) {
46
+ const contentType = strapi.getModel(obj.__type);
47
+
48
+ if (!contentType) {
49
+ return null;
50
+ }
51
+
52
+ if (contentType.modelType === 'component') {
53
+ return naming.getComponentName(contentType);
54
+ }
55
+
56
+ return naming.getTypeName(contentType);
57
+ },
58
+
59
+ definition(t) {
60
+ t.members(...members);
61
+ },
62
+ }),
63
+
64
+ { kind: KINDS.morph, contentType, attributeName }
65
+ );
66
+ }
67
+ };
68
+
69
+ module.exports = { registerPolymorphicContentType };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ const registerScalars = ({ registry, strapi }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { scalars } = getService('internals');
7
+ const { KINDS } = getService('constants');
8
+
9
+ Object.entries(scalars).forEach(([name, definition]) => {
10
+ registry.register(name, definition, { kind: KINDS.scalar });
11
+ });
12
+ };
13
+
14
+ module.exports = { registerScalars };
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const registerSingleType = (contentType, { registry, strapi, builders }) => {
4
+ const { service: getService } = strapi.plugin('graphql');
5
+
6
+ const { naming } = getService('utils');
7
+ const { KINDS } = getService('constants');
8
+
9
+ const extension = getService('extension');
10
+
11
+ const types = {
12
+ base: naming.getTypeName(contentType),
13
+ entity: naming.getEntityName(contentType),
14
+ response: naming.getEntityResponseName(contentType),
15
+ responseCollection: naming.getEntityResponseCollectionName(contentType),
16
+ relationResponseCollection: naming.getRelationResponseCollectionName(contentType),
17
+ queries: naming.getEntityQueriesTypeName(contentType),
18
+ mutations: naming.getEntityMutationsTypeName(contentType),
19
+ };
20
+
21
+ const getConfig = kind => ({ kind, contentType });
22
+
23
+ // Single type's definition
24
+ registry.register(types.base, builders.buildTypeDefinition(contentType), getConfig(KINDS.type));
25
+
26
+ // Higher level entity definition
27
+ registry.register(
28
+ types.entity,
29
+ builders.buildEntityDefinition(contentType),
30
+ getConfig(KINDS.entity)
31
+ );
32
+
33
+ // Responses definition
34
+ registry.register(
35
+ types.response,
36
+ builders.buildResponseDefinition(contentType),
37
+ getConfig(KINDS.entityResponse)
38
+ );
39
+
40
+ // Response collection definition
41
+ registry.register(
42
+ types.responseCollection,
43
+ builders.buildResponseCollectionDefinition(contentType),
44
+ getConfig(KINDS.entityResponseCollection)
45
+ );
46
+
47
+ registry.register(
48
+ types.relationResponseCollection,
49
+ builders.buildRelationResponseCollectionDefinition(contentType),
50
+ getConfig(KINDS.relationResponseCollection)
51
+ );
52
+
53
+ if (extension.shadowCRUD(contentType.uid).areQueriesEnabled()) {
54
+ // Queries
55
+ registry.register(
56
+ types.queries,
57
+ builders.buildSingleTypeQueries(contentType),
58
+ getConfig(KINDS.query)
59
+ );
60
+ }
61
+
62
+ if (extension.shadowCRUD(contentType.uid).areMutationsEnabled()) {
63
+ // Mutations
64
+ registry.register(
65
+ types.mutations,
66
+ builders.buildSingleTypeMutations(contentType),
67
+ getConfig(KINDS.mutation)
68
+ );
69
+ }
70
+ };
71
+
72
+ module.exports = { registerSingleType };