@strapi/plugin-graphql 4.0.0-next.8 → 4.0.2

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 (122) hide show
  1. package/README.md +1 -1
  2. package/admin/src/index.js +0 -8
  3. package/package.json +43 -35
  4. package/server/bootstrap.js +148 -0
  5. package/server/config/default-config.js +13 -0
  6. package/server/config/index.js +7 -0
  7. package/server/format-graphql-error.js +50 -0
  8. package/server/services/builders/dynamic-zones.js +97 -0
  9. package/server/services/builders/entity-meta.js +7 -0
  10. package/server/services/builders/entity.js +43 -0
  11. package/server/services/builders/enums.js +24 -0
  12. package/server/services/builders/filters/content-type.js +93 -0
  13. package/server/services/builders/filters/index.js +7 -0
  14. package/server/services/builders/filters/operators/and.js +15 -0
  15. package/server/services/builders/filters/operators/between.js +15 -0
  16. package/server/services/builders/filters/operators/contains.js +13 -0
  17. package/server/services/builders/filters/operators/containsi.js +13 -0
  18. package/server/services/builders/filters/operators/ends-with.js +13 -0
  19. package/server/services/builders/filters/operators/eq.js +23 -0
  20. package/server/services/builders/filters/operators/gt.js +13 -0
  21. package/server/services/builders/filters/operators/gte.js +13 -0
  22. package/server/services/builders/filters/operators/in.js +15 -0
  23. package/server/services/builders/filters/operators/index.js +38 -0
  24. package/server/services/builders/filters/operators/lt.js +13 -0
  25. package/server/services/builders/filters/operators/lte.js +13 -0
  26. package/server/services/builders/filters/operators/ne.js +13 -0
  27. package/server/services/builders/filters/operators/not-contains.js +13 -0
  28. package/server/services/builders/filters/operators/not-containsi.js +13 -0
  29. package/server/services/builders/filters/operators/not-in.js +15 -0
  30. package/server/services/builders/filters/operators/not-null.js +13 -0
  31. package/server/services/builders/filters/operators/not.js +19 -0
  32. package/server/services/builders/filters/operators/null.js +13 -0
  33. package/server/services/builders/filters/operators/or.js +15 -0
  34. package/server/services/builders/filters/operators/starts-with.js +13 -0
  35. package/server/services/builders/generic-morph.js +41 -0
  36. package/server/services/builders/index.js +92 -0
  37. package/server/services/builders/input.js +121 -0
  38. package/server/services/builders/mutations/collection-type.js +191 -0
  39. package/server/services/builders/mutations/index.js +9 -0
  40. package/server/services/builders/mutations/single-type.js +141 -0
  41. package/server/services/builders/queries/collection-type.js +120 -0
  42. package/server/services/builders/queries/index.js +9 -0
  43. package/server/services/builders/queries/single-type.js +70 -0
  44. package/server/services/builders/relation-response-collection.js +35 -0
  45. package/server/services/builders/resolvers/association.js +85 -0
  46. package/server/services/builders/resolvers/component.js +18 -0
  47. package/server/services/builders/resolvers/dynamic-zone.js +9 -0
  48. package/server/services/builders/resolvers/index.js +18 -0
  49. package/server/services/builders/resolvers/mutation.js +33 -0
  50. package/server/services/builders/resolvers/query.js +19 -0
  51. package/server/services/builders/response-collection.js +43 -0
  52. package/server/services/builders/response.js +32 -0
  53. package/server/services/builders/type.js +364 -0
  54. package/server/services/builders/utils.js +134 -0
  55. package/server/services/constants.js +149 -0
  56. package/server/services/content-api/index.js +179 -0
  57. package/server/services/content-api/policy.js +60 -0
  58. package/server/services/content-api/register-functions/collection-type.js +72 -0
  59. package/server/services/content-api/register-functions/component.js +15 -0
  60. package/server/services/content-api/register-functions/content-type/dynamic-zones.js +36 -0
  61. package/server/services/content-api/register-functions/content-type/enums.js +33 -0
  62. package/server/services/content-api/register-functions/content-type/filters.js +15 -0
  63. package/server/services/content-api/register-functions/content-type/index.js +13 -0
  64. package/server/services/content-api/register-functions/content-type/inputs.js +21 -0
  65. package/server/services/content-api/register-functions/index.js +22 -0
  66. package/server/services/content-api/register-functions/internals.js +13 -0
  67. package/server/services/content-api/register-functions/polymorphic.js +69 -0
  68. package/server/services/content-api/register-functions/scalars.js +14 -0
  69. package/server/services/content-api/register-functions/single-type.js +72 -0
  70. package/server/services/content-api/wrap-resolvers.js +144 -0
  71. package/server/services/extension/extension.js +95 -0
  72. package/server/services/extension/index.js +5 -0
  73. package/server/services/extension/shadow-crud-manager.js +159 -0
  74. package/server/services/format/index.js +7 -0
  75. package/server/services/format/return-types.js +27 -0
  76. package/server/services/index.js +21 -0
  77. package/server/services/internals/args/index.js +11 -0
  78. package/server/services/internals/args/pagination.js +19 -0
  79. package/server/services/internals/args/publication-state.js +12 -0
  80. package/server/services/internals/args/sort.js +10 -0
  81. package/server/services/internals/helpers/get-enabled-scalars.js +15 -0
  82. package/server/services/internals/helpers/index.js +7 -0
  83. package/server/services/internals/index.js +13 -0
  84. package/server/services/internals/scalars/index.js +18 -0
  85. package/server/services/internals/scalars/time.js +36 -0
  86. package/server/services/internals/types/error.js +34 -0
  87. package/server/services/internals/types/filters.js +39 -0
  88. package/server/services/internals/types/index.js +29 -0
  89. package/server/services/internals/types/pagination.js +24 -0
  90. package/server/services/internals/types/publication-state.js +24 -0
  91. package/server/services/internals/types/response-collection-meta.js +39 -0
  92. package/server/services/type-registry.js +104 -0
  93. package/server/services/utils/attributes.js +84 -0
  94. package/server/services/utils/index.js +11 -0
  95. package/server/services/utils/mappers/entity-to-response-entity.js +12 -0
  96. package/server/services/utils/mappers/graphql-filters-to-strapi-query.js +109 -0
  97. package/server/services/utils/mappers/graphql-scalar-to-operators.js +17 -0
  98. package/server/services/utils/mappers/index.js +13 -0
  99. package/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.js +25 -0
  100. package/server/services/utils/naming.js +287 -0
  101. package/strapi-admin.js +3 -0
  102. package/strapi-server.js +7 -9
  103. package/admin/src/assets/images/logo.svg +0 -38
  104. package/config/routes.json +0 -3
  105. package/config/schema.graphql +0 -1
  106. package/config/settings.json +0 -12
  107. package/controllers/GraphQL.js +0 -9
  108. package/hooks/graphql/defaults.json +0 -5
  109. package/hooks/graphql/index.js +0 -174
  110. package/hooks/graphql/load-config.js +0 -42
  111. package/services/build-aggregation.js +0 -565
  112. package/services/data-loaders.js +0 -55
  113. package/services/naming.js +0 -15
  114. package/services/resolvers-builder.js +0 -204
  115. package/services/schema-definitions.js +0 -131
  116. package/services/schema-generator.js +0 -178
  117. package/services/shadow-crud.js +0 -612
  118. package/services/type-builder.js +0 -311
  119. package/services/utils.js +0 -200
  120. package/types/dynamiczoneScalar.js +0 -40
  121. package/types/publication-state.js +0 -16
  122. package/types/time.js +0 -26
@@ -1,311 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Types.js service
5
- *
6
- * @description: A set of functions to make the schema easier to build.
7
- */
8
-
9
- const _ = require('lodash');
10
- const { GraphQLUpload } = require('graphql-upload');
11
- const graphql = require('graphql');
12
- const { GraphQLJSON } = require('graphql-type-json');
13
- const { GraphQLDate, GraphQLDateTime } = require('graphql-iso-date');
14
- const GraphQLLong = require('graphql-type-long');
15
-
16
- const Time = require('../types/time');
17
- const { toSingular, toInputName } = require('./naming');
18
-
19
- const isScalarAttribute = ({ type }) => type && !['component', 'dynamiczone'].includes(type);
20
- const isTypeAttributeEnabled = (model, attr) =>
21
- _.get(strapi.plugins.graphql, `config._schema.graphql.type.${model.globalId}.${attr}`) !== false;
22
-
23
- module.exports = {
24
- /**
25
- * Convert Strapi type to GraphQL type.
26
- * @param {Object} attribute Information about the attribute.
27
- * @param {Object} attribute.definition Definition of the attribute.
28
- * @param {String} attribute.modelName Name of the model which owns the attribute.
29
- * @param {String} attribute.attributeName Name of the attribute.
30
- * @return String
31
- */
32
-
33
- convertType({
34
- attribute = {},
35
- modelName = '',
36
- attributeName = '',
37
- rootType = 'query',
38
- action = '',
39
- }) {
40
- // Type
41
- if (isScalarAttribute(attribute)) {
42
- let type = 'String';
43
-
44
- switch (attribute.type) {
45
- case 'boolean':
46
- type = 'Boolean';
47
- break;
48
- case 'integer':
49
- type = 'Int';
50
- break;
51
- case 'biginteger':
52
- type = 'Long';
53
- break;
54
- case 'float':
55
- case 'decimal':
56
- type = 'Float';
57
- break;
58
- case 'json':
59
- type = 'JSON';
60
- break;
61
- case 'date':
62
- type = 'Date';
63
- break;
64
- case 'time':
65
- type = 'Time';
66
- break;
67
- case 'datetime':
68
- case 'timestamp':
69
- type = 'DateTime';
70
- break;
71
- case 'enumeration':
72
- type = this.convertEnumType(attribute, modelName, attributeName);
73
- break;
74
- }
75
-
76
- if (attribute.required) {
77
- if (rootType !== 'mutation' || (action !== 'update' && attribute.default === undefined)) {
78
- type += '!';
79
- }
80
- }
81
-
82
- return type;
83
- }
84
-
85
- if (attribute.type === 'component') {
86
- const { required, repeatable, component } = attribute;
87
-
88
- const globalId = strapi.components[component].globalId;
89
-
90
- let typeName = required === true ? `${globalId}` : globalId;
91
-
92
- if (rootType === 'mutation') {
93
- typeName =
94
- action === 'update'
95
- ? `edit${_.upperFirst(toSingular(globalId))}Input`
96
- : `${_.upperFirst(toSingular(globalId))}Input${required ? '!' : ''}`;
97
- }
98
-
99
- if (repeatable === true) {
100
- return `[${typeName}]`;
101
- }
102
- return `${typeName}`;
103
- }
104
-
105
- if (attribute.type === 'dynamiczone') {
106
- const { required } = attribute;
107
-
108
- const unionName = `${modelName}${_.upperFirst(_.camelCase(attributeName))}DynamicZone`;
109
-
110
- let typeName = unionName;
111
-
112
- if (rootType === 'mutation') {
113
- typeName = `${unionName}Input!`;
114
- }
115
-
116
- return `[${typeName}]${required ? '!' : ''}`;
117
- }
118
-
119
- const ref = attribute.target;
120
-
121
- // Association
122
- if (ref && ref !== '*') {
123
- // Add bracket or not
124
- const globalId = strapi.getModel(ref).globalId;
125
- const plural = !_.isEmpty(attribute.collection);
126
-
127
- if (plural) {
128
- if (rootType === 'mutation') {
129
- return '[ID]';
130
- }
131
-
132
- return `[${globalId}]`;
133
- }
134
-
135
- if (rootType === 'mutation') {
136
- return 'ID';
137
- }
138
-
139
- return globalId;
140
- }
141
-
142
- if (rootType === 'mutation') {
143
- return attribute.model ? 'ID' : '[ID]';
144
- }
145
-
146
- return attribute.model ? 'Morph' : '[Morph]';
147
- },
148
-
149
- /**
150
- * Convert Strapi enumeration to GraphQL Enum.
151
- * @param {Object} definition Definition of the attribute.
152
- * @param {String} model Name of the model which owns the attribute.
153
- * @param {String} field Name of the attribute.
154
- * @return String
155
- */
156
-
157
- convertEnumType(definition, model, field) {
158
- return definition.enumName
159
- ? definition.enumName
160
- : `ENUM_${model.toUpperCase()}_${field.toUpperCase()}`;
161
- },
162
-
163
- /**
164
- * Add custom scalar type such as JSON.
165
- *
166
- * @return void
167
- */
168
-
169
- getScalars() {
170
- return {
171
- JSON: GraphQLJSON,
172
- DateTime: GraphQLDateTime,
173
- Time,
174
- Date: GraphQLDate,
175
- Long: GraphQLLong,
176
- Upload: GraphQLUpload,
177
- };
178
- },
179
-
180
- /**
181
- * Add Union Type that contains the types defined by the user.
182
- *
183
- * @return string
184
- */
185
-
186
- addPolymorphicUnionType(definition) {
187
- const types = graphql
188
- .parse(definition)
189
- .definitions.filter(def => def.kind === 'ObjectTypeDefinition' && def.name.value !== 'Query')
190
- .map(def => def.name.value);
191
-
192
- if (types.length > 0) {
193
- return {
194
- definition: `union Morph = ${types.join(' | ')}`,
195
- resolvers: {
196
- Morph: {
197
- __resolveType(obj) {
198
- return obj.kind || obj.__contentType || null;
199
- },
200
- },
201
- },
202
- };
203
- }
204
-
205
- return {
206
- definition: '',
207
- resolvers: {},
208
- };
209
- },
210
-
211
- addInput() {
212
- return `
213
- input InputID { id: ID!}
214
- `;
215
- },
216
-
217
- generateInputModel(model, name, { allowIds = false } = {}) {
218
- const globalId = model.globalId;
219
- const inputName = `${_.upperFirst(toSingular(name))}Input`;
220
- const hasAllAttributesDisabled = Object.keys(model.attributes).every(
221
- attr => !isTypeAttributeEnabled(model, attr)
222
- );
223
-
224
- if (_.isEmpty(model.attributes) || hasAllAttributesDisabled) {
225
- return `
226
- input ${inputName} {
227
- _: String
228
- }
229
-
230
- input edit${inputName} {
231
- ${allowIds ? 'id: ID' : '_: String'}
232
- }
233
- `;
234
- }
235
-
236
- const inputs = `
237
- input ${inputName} {
238
-
239
- ${Object.keys(model.attributes)
240
- .filter(attributeName => isTypeAttributeEnabled(model, attributeName))
241
- .map(attributeName => {
242
- return `${attributeName}: ${this.convertType({
243
- attribute: model.attributes[attributeName],
244
- modelName: globalId,
245
- attributeName,
246
- rootType: 'mutation',
247
- })}`;
248
- })
249
- .join('\n')}
250
- }
251
-
252
- input edit${inputName} {
253
- ${allowIds ? 'id: ID' : ''}
254
- ${Object.keys(model.attributes)
255
- .filter(attributeName => isTypeAttributeEnabled(model, attributeName))
256
- .map(attributeName => {
257
- return `${attributeName}: ${this.convertType({
258
- attribute: model.attributes[attributeName],
259
- modelName: globalId,
260
- attributeName,
261
- rootType: 'mutation',
262
- action: 'update',
263
- })}`;
264
- })
265
- .join('\n')}
266
- }
267
- `;
268
-
269
- return inputs;
270
- },
271
-
272
- generateInputPayloadArguments({ model, name, mutationName, action }) {
273
- const singularName = toSingular(name);
274
- const inputName = toInputName(name);
275
-
276
- const { kind } = model;
277
-
278
- switch (action) {
279
- case 'create':
280
- return `
281
- input ${mutationName}Input { data: ${inputName} }
282
- type ${mutationName}Payload { ${singularName}: ${model.globalId} }
283
- `;
284
- case 'update':
285
- if (kind === 'singleType') {
286
- return `
287
- input ${mutationName}Input { data: edit${inputName} }
288
- type ${mutationName}Payload { ${singularName}: ${model.globalId} }
289
- `;
290
- }
291
-
292
- return `
293
- input ${mutationName}Input { where: InputID, data: edit${inputName} }
294
- type ${mutationName}Payload { ${singularName}: ${model.globalId} }
295
- `;
296
- case 'delete':
297
- if (kind === 'singleType') {
298
- return `
299
- type ${mutationName}Payload { ${singularName}: ${model.globalId} }
300
- `;
301
- }
302
-
303
- return `
304
- input ${mutationName}Input { where: InputID }
305
- type ${mutationName}Payload { ${singularName}: ${model.globalId} }
306
- `;
307
- default:
308
- // Nothing
309
- }
310
- },
311
- };
package/services/utils.js DELETED
@@ -1,200 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const { QUERY_OPERATORS } = require('@strapi/utils');
5
-
6
- /**
7
- * @typedef {object} Schema
8
- * @property {object} resolvers
9
- * @property {object} mutation
10
- * @property {object} query
11
- * @property {string} definition
12
- */
13
-
14
- /**
15
- * Merges strapi graphql schema together
16
- * @param {Schema} object - destination object
17
- * @param {Schema[]} sources - source objects to merge into the destination object
18
- * @returns {Schema}
19
- */
20
- const mergeSchemas = (object, ...sources) => {
21
- sources.forEach(sub => {
22
- if (_.isEmpty(sub)) return;
23
- const { definition = '', query = {}, mutation = {}, resolvers = {} } = sub;
24
-
25
- object.definition += '\n' + definition;
26
- _.merge(object, {
27
- query,
28
- mutation,
29
- resolvers,
30
- });
31
- });
32
-
33
- return object;
34
- };
35
-
36
- /**
37
- * Returns an empty schema
38
- * @returns {Schema}
39
- */
40
- const createDefaultSchema = () => ({
41
- definition: '',
42
- query: {},
43
- mutation: {},
44
- resolvers: {},
45
- });
46
-
47
- const diffResolvers = (object, base) => {
48
- let newObj = {};
49
-
50
- Object.keys(object).forEach(type => {
51
- Object.keys(object[type]).forEach(resolver => {
52
- if (type === 'Query' || type === 'Mutation') {
53
- if (!_.has(base, [type, resolver])) {
54
- _.set(newObj, [type, resolver], _.get(object, [type, resolver]));
55
- }
56
- } else {
57
- _.set(newObj, [type, resolver], _.get(object, [type, resolver]));
58
- }
59
- });
60
- });
61
-
62
- return newObj;
63
- };
64
-
65
- const convertToParams = params => {
66
- return Object.keys(params).reduce((acc, current) => {
67
- const key = current === 'id' ? 'id' : `_${current}`;
68
- acc[key] = params[current];
69
- return acc;
70
- }, {});
71
- };
72
-
73
- const convertToQuery = params => {
74
- const result = {};
75
-
76
- _.forEach(params, (value, key) => {
77
- if (QUERY_OPERATORS.includes(key)) {
78
- result[key] = _.isArray(value) ? value.map(convertToQuery) : convertToQuery(value);
79
- } else if (_.isPlainObject(value)) {
80
- const flatObject = convertToQuery(value);
81
- _.forEach(flatObject, (_value, _key) => {
82
- result[`${key}.${_key}`] = _value;
83
- });
84
- } else {
85
- result[key] = value;
86
- }
87
- });
88
-
89
- return result;
90
- };
91
-
92
- const amountLimiting = (params = {}) => {
93
- const { amountLimit } = strapi.plugins.graphql.config;
94
-
95
- if (!amountLimit) return params;
96
-
97
- if (_.isNil(params.limit) || params.limit === -1 || params.limit > amountLimit) {
98
- params.limit = amountLimit;
99
- } else if (params.limit < 0) {
100
- params.limit = 0;
101
- }
102
-
103
- return params;
104
- };
105
-
106
- const nonRequired = type => type.replace('!', '');
107
-
108
- const actionExists = ({ resolver, resolverOf }) => {
109
- if (isResolvablePath(resolverOf)) {
110
- return true;
111
- } else if (_.isFunction(resolver)) {
112
- return true;
113
- } else if (_.isString(resolver)) {
114
- return _.isFunction(getActionFn(getActionDetails(resolver)));
115
- } else {
116
- throw new Error(
117
- `Error building query. Expected \`resolver\` as string or a function, or \`resolverOf\` as a string. got ${{
118
- resolver,
119
- resolverOf,
120
- }}`
121
- );
122
- }
123
- };
124
-
125
- const getAction = resolver => {
126
- if (!_.isString(resolver)) {
127
- throw new Error(`Error building query. Expected a string, got ${resolver}`);
128
- }
129
-
130
- const actionDetails = getActionDetails(resolver);
131
- const actionFn = getActionFn(actionDetails);
132
-
133
- if (!actionFn) {
134
- throw new Error(
135
- `[GraphQL] Cannot find action "${resolver}". Check your graphql configurations.`
136
- );
137
- }
138
-
139
- return actionFn;
140
- };
141
-
142
- const getActionFn = details => {
143
- const { controller, action, plugin, api } = details;
144
-
145
- if (plugin) {
146
- return _.get(strapi.plugins, [_.toLower(plugin), 'controllers', _.toLower(controller), action]);
147
- }
148
-
149
- return _.get(strapi.api, [_.toLower(api), 'controllers', _.toLower(controller), action]);
150
- };
151
-
152
- const getActionDetails = resolver => {
153
- if (resolver.startsWith('plugin::')) {
154
- const [, path] = resolver.split('::');
155
- const [plugin, controller, action] = path.split('.');
156
-
157
- return { plugin, controller, action };
158
- }
159
-
160
- if (resolver.startsWith('api::')) {
161
- const [, path] = resolver.split('::');
162
- const [api, controller, action] = path.split('.');
163
-
164
- return { api, controller, action };
165
- }
166
-
167
- const args = resolver.split('.');
168
-
169
- if (args.length === 3) {
170
- const [api, controller, action] = args;
171
- return { api, controller, action };
172
- }
173
-
174
- // if direct api access
175
- if (args.length === 2) {
176
- const [controller, action] = args;
177
- return { api: controller, controller, action };
178
- }
179
-
180
- throw new Error(
181
- `[GraphQL] Could not find action for resolver "${resolver}". Check your graphql configurations.`
182
- );
183
- };
184
-
185
- const isResolvablePath = path => _.isString(path) && !_.isEmpty(path);
186
-
187
- module.exports = {
188
- diffResolvers,
189
- mergeSchemas,
190
- createDefaultSchema,
191
- convertToParams,
192
- convertToQuery,
193
- amountLimiting,
194
- nonRequired,
195
- actionExists,
196
- getAction,
197
- getActionDetails,
198
- getActionFn,
199
- isResolvablePath,
200
- };
@@ -1,40 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash');
4
- const { Kind, GraphQLScalarType, valueFromASTUntyped, GraphQLError } = require('graphql');
5
-
6
- module.exports = function DynamicZoneScalar({ name, attribute, globalId, components }) {
7
- const parseData = value => {
8
- const compo = Object.values(strapi.components).find(
9
- compo => compo.globalId === value.__typename
10
- );
11
-
12
- if (!compo) {
13
- throw new GraphQLError(
14
- `Component not found. expected one of: ${components
15
- .map(uid => strapi.components[uid].globalId)
16
- .join(', ')}`
17
- );
18
- }
19
-
20
- const finalValue = {
21
- __component: compo.uid,
22
- ..._.omit(value, ['__typename']),
23
- };
24
-
25
- return finalValue;
26
- };
27
-
28
- return new GraphQLScalarType({
29
- name: name,
30
- description: `Input type for dynamic zone ${attribute} of ${globalId}`,
31
- serialize: value => value,
32
- parseValue: value => parseData(value),
33
- parseLiteral: (ast, variables) => {
34
- if (ast.kind !== Kind.OBJECT) return undefined;
35
-
36
- const value = valueFromASTUntyped(ast, variables);
37
- return parseData(value);
38
- },
39
- });
40
- };
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- definition: `
5
- enum PublicationState {
6
- LIVE
7
- PREVIEW
8
- }
9
- `,
10
- resolver: {
11
- PublicationState: {
12
- LIVE: 'live',
13
- PREVIEW: 'preview',
14
- },
15
- },
16
- };
package/types/time.js DELETED
@@ -1,26 +0,0 @@
1
- 'use strict';
2
-
3
- const { parseType } = require('@strapi/utils');
4
-
5
- const { Kind, GraphQLScalarType } = require('graphql');
6
-
7
- const Time = new GraphQLScalarType({
8
- name: 'Time',
9
- description: 'A time string with format: HH:mm:ss.SSS',
10
- serialize(value) {
11
- return parseType({ type: 'time', value });
12
- },
13
- parseValue(value) {
14
- return parseType({ type: 'time', value });
15
- },
16
- parseLiteral(ast) {
17
- if (ast.kind !== Kind.STRING) {
18
- throw new TypeError(`Time cannot represent non string type`);
19
- }
20
-
21
- const value = ast.value;
22
- return parseType({ type: 'time', value });
23
- },
24
- });
25
-
26
- module.exports = Time;