UNPKG

17.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.makeDirectiveNodes = exports.makeDirectiveNode = exports.makeDeprecatedDirective = exports.astFromEnumValue = exports.astFromInputField = exports.astFromField = exports.astFromScalarType = exports.astFromEnumType = exports.astFromInputObjectType = exports.astFromUnionType = exports.astFromInterfaceType = exports.astFromObjectType = exports.astFromArg = exports.getDirectiveNodes = exports.astFromDirective = exports.astFromSchema = exports.printSchemaWithDirectives = exports.getDocumentNodeFromSchema = void 0;
4const graphql_1 = require("graphql");
5const astFromType_js_1 = require("./astFromType.js");
6const astFromValue_js_1 = require("./astFromValue.js");
7const astFromValueUntyped_js_1 = require("./astFromValueUntyped.js");
8const descriptionFromObject_js_1 = require("./descriptionFromObject.js");
9const get_directives_js_1 = require("./get-directives.js");
10const helpers_js_1 = require("./helpers.js");
11const rootTypes_js_1 = require("./rootTypes.js");
12function getDocumentNodeFromSchema(schema, options = {}) {
13 const pathToDirectivesInExtensions = options.pathToDirectivesInExtensions;
14 const typesMap = schema.getTypeMap();
15 const schemaNode = astFromSchema(schema, pathToDirectivesInExtensions);
16 const definitions = schemaNode != null ? [schemaNode] : [];
17 const directives = schema.getDirectives();
18 for (const directive of directives) {
19 if ((0, graphql_1.isSpecifiedDirective)(directive)) {
20 continue;
21 }
22 definitions.push(astFromDirective(directive, schema, pathToDirectivesInExtensions));
23 }
24 for (const typeName in typesMap) {
25 const type = typesMap[typeName];
26 const isPredefinedScalar = (0, graphql_1.isSpecifiedScalarType)(type);
27 const isIntrospection = (0, graphql_1.isIntrospectionType)(type);
28 if (isPredefinedScalar || isIntrospection) {
29 continue;
30 }
31 if ((0, graphql_1.isObjectType)(type)) {
32 definitions.push(astFromObjectType(type, schema, pathToDirectivesInExtensions));
33 }
34 else if ((0, graphql_1.isInterfaceType)(type)) {
35 definitions.push(astFromInterfaceType(type, schema, pathToDirectivesInExtensions));
36 }
37 else if ((0, graphql_1.isUnionType)(type)) {
38 definitions.push(astFromUnionType(type, schema, pathToDirectivesInExtensions));
39 }
40 else if ((0, graphql_1.isInputObjectType)(type)) {
41 definitions.push(astFromInputObjectType(type, schema, pathToDirectivesInExtensions));
42 }
43 else if ((0, graphql_1.isEnumType)(type)) {
44 definitions.push(astFromEnumType(type, schema, pathToDirectivesInExtensions));
45 }
46 else if ((0, graphql_1.isScalarType)(type)) {
47 definitions.push(astFromScalarType(type, schema, pathToDirectivesInExtensions));
48 }
49 else {
50 throw new Error(`Unknown type ${type}.`);
51 }
52 }
53 return {
54 kind: graphql_1.Kind.DOCUMENT,
55 definitions,
56 };
57}
58exports.getDocumentNodeFromSchema = getDocumentNodeFromSchema;
59// this approach uses the default schema printer rather than a custom solution, so may be more backwards compatible
60// currently does not allow customization of printSchema options having to do with comments.
61function printSchemaWithDirectives(schema, options = {}) {
62 const documentNode = getDocumentNodeFromSchema(schema, options);
63 return (0, graphql_1.print)(documentNode);
64}
65exports.printSchemaWithDirectives = printSchemaWithDirectives;
66function astFromSchema(schema, pathToDirectivesInExtensions) {
67 const operationTypeMap = new Map([
68 ['query', undefined],
69 ['mutation', undefined],
70 ['subscription', undefined],
71 ]);
72 const nodes = [];
73 if (schema.astNode != null) {
74 nodes.push(schema.astNode);
75 }
76 if (schema.extensionASTNodes != null) {
77 for (const extensionASTNode of schema.extensionASTNodes) {
78 nodes.push(extensionASTNode);
79 }
80 }
81 for (const node of nodes) {
82 if (node.operationTypes) {
83 for (const operationTypeDefinitionNode of node.operationTypes) {
84 operationTypeMap.set(operationTypeDefinitionNode.operation, operationTypeDefinitionNode);
85 }
86 }
87 }
88 const rootTypeMap = (0, rootTypes_js_1.getRootTypeMap)(schema);
89 for (const [operationTypeNode, operationTypeDefinitionNode] of operationTypeMap) {
90 const rootType = rootTypeMap.get(operationTypeNode);
91 if (rootType != null) {
92 const rootTypeAST = (0, astFromType_js_1.astFromType)(rootType);
93 if (operationTypeDefinitionNode != null) {
94 operationTypeDefinitionNode.type = rootTypeAST;
95 }
96 else {
97 operationTypeMap.set(operationTypeNode, {
98 kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
99 operation: operationTypeNode,
100 type: rootTypeAST,
101 });
102 }
103 }
104 }
105 const operationTypes = [...operationTypeMap.values()].filter(helpers_js_1.isSome);
106 const directives = getDirectiveNodes(schema, schema, pathToDirectivesInExtensions);
107 if (!operationTypes.length && !directives.length) {
108 return null;
109 }
110 const schemaNode = {
111 kind: operationTypes != null ? graphql_1.Kind.SCHEMA_DEFINITION : graphql_1.Kind.SCHEMA_EXTENSION,
112 operationTypes,
113 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
114 directives: directives,
115 };
116 const descriptionNode = (0, descriptionFromObject_js_1.getDescriptionNode)(schema);
117 if (descriptionNode) {
118 schemaNode.description = descriptionNode;
119 }
120 return schemaNode;
121}
122exports.astFromSchema = astFromSchema;
123function astFromDirective(directive, schema, pathToDirectivesInExtensions) {
124 return {
125 kind: graphql_1.Kind.DIRECTIVE_DEFINITION,
126 description: (0, descriptionFromObject_js_1.getDescriptionNode)(directive),
127 name: {
128 kind: graphql_1.Kind.NAME,
129 value: directive.name,
130 },
131 arguments: directive.args?.map(arg => astFromArg(arg, schema, pathToDirectivesInExtensions)),
132 repeatable: directive.isRepeatable,
133 locations: directive.locations?.map(location => ({
134 kind: graphql_1.Kind.NAME,
135 value: location,
136 })) || [],
137 };
138}
139exports.astFromDirective = astFromDirective;
140function getDirectiveNodes(entity, schema, pathToDirectivesInExtensions) {
141 let directiveNodesBesidesDeprecatedAndSpecifiedBy = [];
142 const directivesInExtensions = (0, get_directives_js_1.getDirectivesInExtensions)(entity, pathToDirectivesInExtensions);
143 let directives;
144 if (directivesInExtensions != null) {
145 directives = makeDirectiveNodes(schema, directivesInExtensions);
146 }
147 let deprecatedDirectiveNode = null;
148 let specifiedByDirectiveNode = null;
149 if (directives != null) {
150 directiveNodesBesidesDeprecatedAndSpecifiedBy = directives.filter(directive => directive.name.value !== 'deprecated' && directive.name.value !== 'specifiedBy');
151 if (entity.deprecationReason != null) {
152 deprecatedDirectiveNode = directives.filter(directive => directive.name.value === 'deprecated')?.[0];
153 }
154 if (entity.specifiedByUrl != null || entity.specifiedByURL != null) {
155 specifiedByDirectiveNode = directives.filter(directive => directive.name.value === 'specifiedBy')?.[0];
156 }
157 }
158 if (entity.deprecationReason != null && deprecatedDirectiveNode == null) {
159 deprecatedDirectiveNode = makeDeprecatedDirective(entity.deprecationReason);
160 }
161 if (entity.specifiedByUrl != null ||
162 (entity.specifiedByURL != null && specifiedByDirectiveNode == null)) {
163 const specifiedByValue = entity.specifiedByUrl || entity.specifiedByURL;
164 const specifiedByArgs = {
165 url: specifiedByValue,
166 };
167 specifiedByDirectiveNode = makeDirectiveNode('specifiedBy', specifiedByArgs);
168 }
169 if (deprecatedDirectiveNode != null) {
170 directiveNodesBesidesDeprecatedAndSpecifiedBy.push(deprecatedDirectiveNode);
171 }
172 if (specifiedByDirectiveNode != null) {
173 directiveNodesBesidesDeprecatedAndSpecifiedBy.push(specifiedByDirectiveNode);
174 }
175 return directiveNodesBesidesDeprecatedAndSpecifiedBy;
176}
177exports.getDirectiveNodes = getDirectiveNodes;
178function astFromArg(arg, schema, pathToDirectivesInExtensions) {
179 return {
180 kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
181 description: (0, descriptionFromObject_js_1.getDescriptionNode)(arg),
182 name: {
183 kind: graphql_1.Kind.NAME,
184 value: arg.name,
185 },
186 type: (0, astFromType_js_1.astFromType)(arg.type),
187 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
188 defaultValue: arg.defaultValue !== undefined
189 ? ((0, astFromValue_js_1.astFromValue)(arg.defaultValue, arg.type) ?? undefined)
190 : undefined,
191 directives: getDirectiveNodes(arg, schema, pathToDirectivesInExtensions),
192 };
193}
194exports.astFromArg = astFromArg;
195function astFromObjectType(type, schema, pathToDirectivesInExtensions) {
196 return {
197 kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
198 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
199 name: {
200 kind: graphql_1.Kind.NAME,
201 value: type.name,
202 },
203 fields: Object.values(type.getFields()).map(field => astFromField(field, schema, pathToDirectivesInExtensions)),
204 interfaces: Object.values(type.getInterfaces()).map(iFace => (0, astFromType_js_1.astFromType)(iFace)),
205 directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
206 };
207}
208exports.astFromObjectType = astFromObjectType;
209function astFromInterfaceType(type, schema, pathToDirectivesInExtensions) {
210 const node = {
211 kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
212 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
213 name: {
214 kind: graphql_1.Kind.NAME,
215 value: type.name,
216 },
217 fields: Object.values(type.getFields()).map(field => astFromField(field, schema, pathToDirectivesInExtensions)),
218 directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
219 };
220 if ('getInterfaces' in type) {
221 node.interfaces = Object.values(type.getInterfaces()).map(iFace => (0, astFromType_js_1.astFromType)(iFace));
222 }
223 return node;
224}
225exports.astFromInterfaceType = astFromInterfaceType;
226function astFromUnionType(type, schema, pathToDirectivesInExtensions) {
227 return {
228 kind: graphql_1.Kind.UNION_TYPE_DEFINITION,
229 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
230 name: {
231 kind: graphql_1.Kind.NAME,
232 value: type.name,
233 },
234 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
235 directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
236 types: type.getTypes().map(type => (0, astFromType_js_1.astFromType)(type)),
237 };
238}
239exports.astFromUnionType = astFromUnionType;
240function astFromInputObjectType(type, schema, pathToDirectivesInExtensions) {
241 return {
242 kind: graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION,
243 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
244 name: {
245 kind: graphql_1.Kind.NAME,
246 value: type.name,
247 },
248 fields: Object.values(type.getFields()).map(field => astFromInputField(field, schema, pathToDirectivesInExtensions)),
249 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
250 directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
251 };
252}
253exports.astFromInputObjectType = astFromInputObjectType;
254function astFromEnumType(type, schema, pathToDirectivesInExtensions) {
255 return {
256 kind: graphql_1.Kind.ENUM_TYPE_DEFINITION,
257 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
258 name: {
259 kind: graphql_1.Kind.NAME,
260 value: type.name,
261 },
262 values: Object.values(type.getValues()).map(value => astFromEnumValue(value, schema, pathToDirectivesInExtensions)),
263 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
264 directives: getDirectiveNodes(type, schema, pathToDirectivesInExtensions),
265 };
266}
267exports.astFromEnumType = astFromEnumType;
268function astFromScalarType(type, schema, pathToDirectivesInExtensions) {
269 const directivesInExtensions = (0, get_directives_js_1.getDirectivesInExtensions)(type, pathToDirectivesInExtensions);
270 const directives = makeDirectiveNodes(schema, directivesInExtensions);
271 const specifiedByValue = (type['specifiedByUrl'] ||
272 type['specifiedByURL']);
273 if (specifiedByValue &&
274 !directives.some(directiveNode => directiveNode.name.value === 'specifiedBy')) {
275 const specifiedByArgs = {
276 url: specifiedByValue,
277 };
278 directives.push(makeDirectiveNode('specifiedBy', specifiedByArgs));
279 }
280 return {
281 kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
282 description: (0, descriptionFromObject_js_1.getDescriptionNode)(type),
283 name: {
284 kind: graphql_1.Kind.NAME,
285 value: type.name,
286 },
287 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
288 directives: directives,
289 };
290}
291exports.astFromScalarType = astFromScalarType;
292function astFromField(field, schema, pathToDirectivesInExtensions) {
293 return {
294 kind: graphql_1.Kind.FIELD_DEFINITION,
295 description: (0, descriptionFromObject_js_1.getDescriptionNode)(field),
296 name: {
297 kind: graphql_1.Kind.NAME,
298 value: field.name,
299 },
300 arguments: field.args.map(arg => astFromArg(arg, schema, pathToDirectivesInExtensions)),
301 type: (0, astFromType_js_1.astFromType)(field.type),
302 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
303 directives: getDirectiveNodes(field, schema, pathToDirectivesInExtensions),
304 };
305}
306exports.astFromField = astFromField;
307function astFromInputField(field, schema, pathToDirectivesInExtensions) {
308 return {
309 kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
310 description: (0, descriptionFromObject_js_1.getDescriptionNode)(field),
311 name: {
312 kind: graphql_1.Kind.NAME,
313 value: field.name,
314 },
315 type: (0, astFromType_js_1.astFromType)(field.type),
316 // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
317 directives: getDirectiveNodes(field, schema, pathToDirectivesInExtensions),
318 defaultValue: (0, astFromValue_js_1.astFromValue)(field.defaultValue, field.type) ?? undefined,
319 };
320}
321exports.astFromInputField = astFromInputField;
322function astFromEnumValue(value, schema, pathToDirectivesInExtensions) {
323 return {
324 kind: graphql_1.Kind.ENUM_VALUE_DEFINITION,
325 description: (0, descriptionFromObject_js_1.getDescriptionNode)(value),
326 name: {
327 kind: graphql_1.Kind.NAME,
328 value: value.name,
329 },
330 directives: getDirectiveNodes(value, schema, pathToDirectivesInExtensions),
331 };
332}
333exports.astFromEnumValue = astFromEnumValue;
334function makeDeprecatedDirective(deprecationReason) {
335 return makeDirectiveNode('deprecated', { reason: deprecationReason }, graphql_1.GraphQLDeprecatedDirective);
336}
337exports.makeDeprecatedDirective = makeDeprecatedDirective;
338function makeDirectiveNode(name, args, directive) {
339 const directiveArguments = [];
340 for (const argName in args) {
341 const argValue = args[argName];
342 let value;
343 if (directive != null) {
344 const arg = directive.args.find(arg => arg.name === argName);
345 if (arg) {
346 value = (0, astFromValue_js_1.astFromValue)(argValue, arg.type);
347 }
348 }
349 if (value == null) {
350 value = (0, astFromValueUntyped_js_1.astFromValueUntyped)(argValue);
351 }
352 if (value != null) {
353 directiveArguments.push({
354 kind: graphql_1.Kind.ARGUMENT,
355 name: {
356 kind: graphql_1.Kind.NAME,
357 value: argName,
358 },
359 value,
360 });
361 }
362 }
363 return {
364 kind: graphql_1.Kind.DIRECTIVE,
365 name: {
366 kind: graphql_1.Kind.NAME,
367 value: name,
368 },
369 arguments: directiveArguments,
370 };
371}
372exports.makeDirectiveNode = makeDirectiveNode;
373function makeDirectiveNodes(schema, directiveValues) {
374 const directiveNodes = [];
375 for (const { name, args } of directiveValues) {
376 const directive = schema?.getDirective(name);
377 directiveNodes.push(makeDirectiveNode(name, args, directive));
378 }
379 return directiveNodes;
380}
381exports.makeDirectiveNodes = makeDirectiveNodes;