1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.buildServiceDefinition = void 0;
|
4 | const graphql_1 = require("graphql");
|
5 | const graphql_2 = require("./utilities/graphql");
|
6 | const predicates_1 = require("./utilities/predicates");
|
7 | function flattened(arr) {
|
8 | return new Array().concat(...arr);
|
9 | }
|
10 | function buildServiceDefinition(modules) {
|
11 | const errors = [];
|
12 | const typeDefinitionsMap = Object.create(null);
|
13 | const typeExtensionsMap = Object.create(null);
|
14 | const directivesMap = Object.create(null);
|
15 | const schemaDefinitions = [];
|
16 | const schemaExtensions = [];
|
17 | for (let module of modules) {
|
18 | if ((0, graphql_2.isNode)(module) && (0, graphql_2.isDocumentNode)(module)) {
|
19 | module = { typeDefs: module };
|
20 | }
|
21 | for (const definition of module.typeDefs.definitions) {
|
22 | if ((0, graphql_1.isTypeDefinitionNode)(definition)) {
|
23 | const typeName = definition.name.value;
|
24 | if (typeDefinitionsMap[typeName]) {
|
25 | typeDefinitionsMap[typeName].push(definition);
|
26 | }
|
27 | else {
|
28 | typeDefinitionsMap[typeName] = [definition];
|
29 | }
|
30 | }
|
31 | else if ((0, graphql_1.isTypeExtensionNode)(definition)) {
|
32 | const typeName = definition.name.value;
|
33 | if (typeExtensionsMap[typeName]) {
|
34 | typeExtensionsMap[typeName].push(definition);
|
35 | }
|
36 | else {
|
37 | typeExtensionsMap[typeName] = [definition];
|
38 | }
|
39 | }
|
40 | else if (definition.kind === graphql_1.Kind.DIRECTIVE_DEFINITION) {
|
41 | const directiveName = definition.name.value;
|
42 | if (directivesMap[directiveName]) {
|
43 | directivesMap[directiveName].push(definition);
|
44 | }
|
45 | else {
|
46 | directivesMap[directiveName] = [definition];
|
47 | }
|
48 | }
|
49 | else if (definition.kind === graphql_1.Kind.SCHEMA_DEFINITION) {
|
50 | schemaDefinitions.push(definition);
|
51 | }
|
52 | else if (definition.kind === graphql_1.Kind.SCHEMA_EXTENSION) {
|
53 | schemaExtensions.push(definition);
|
54 | }
|
55 | }
|
56 | }
|
57 | for (const [typeName, typeDefinitions] of Object.entries(typeDefinitionsMap)) {
|
58 | if (typeDefinitions.length > 1) {
|
59 | errors.push(new graphql_1.GraphQLError(`Type "${typeName}" was defined more than once.`, typeDefinitions));
|
60 | }
|
61 | }
|
62 | for (const [directiveName, directives] of Object.entries(directivesMap)) {
|
63 | if (directives.length > 1) {
|
64 | errors.push(new graphql_1.GraphQLError(`Directive "${directiveName}" was defined more than once.`, directives));
|
65 | }
|
66 | }
|
67 | let operationTypeMap;
|
68 | if (schemaDefinitions.length > 0 || schemaExtensions.length > 0) {
|
69 | operationTypeMap = {};
|
70 | const schemaDefinition = schemaDefinitions[schemaDefinitions.length - 1];
|
71 | const operationTypes = flattened([schemaDefinition, ...schemaExtensions]
|
72 | .map((node) => node.operationTypes)
|
73 | .filter(predicates_1.isNotNullOrUndefined));
|
74 | for (const operationType of operationTypes) {
|
75 | const typeName = operationType.type.name.value;
|
76 | const operation = operationType.operation;
|
77 | if (operationTypeMap[operation]) {
|
78 | throw new graphql_1.GraphQLError(`Must provide only one ${operation} type in schema.`, [schemaDefinition]);
|
79 | }
|
80 | if (!(typeDefinitionsMap[typeName] || typeExtensionsMap[typeName])) {
|
81 | throw new graphql_1.GraphQLError(`Specified ${operation} type "${typeName}" not found in document.`, [schemaDefinition]);
|
82 | }
|
83 | operationTypeMap[operation] = typeName;
|
84 | }
|
85 | }
|
86 | else {
|
87 | operationTypeMap = {
|
88 | query: "Query",
|
89 | mutation: "Mutation",
|
90 | subscription: "Subscription",
|
91 | };
|
92 | }
|
93 | for (const [typeName, typeExtensions] of Object.entries(typeExtensionsMap)) {
|
94 | if (!typeDefinitionsMap[typeName]) {
|
95 | if (Object.values(operationTypeMap).includes(typeName)) {
|
96 | typeDefinitionsMap[typeName] = [
|
97 | {
|
98 | kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
|
99 | name: {
|
100 | kind: graphql_1.Kind.NAME,
|
101 | value: typeName,
|
102 | },
|
103 | },
|
104 | ];
|
105 | }
|
106 | else {
|
107 | errors.push(new graphql_1.GraphQLError(`Cannot extend type "${typeName}" because it does not exist in the existing schema.`, typeExtensions));
|
108 | }
|
109 | }
|
110 | }
|
111 | if (errors.length > 0) {
|
112 | return { errors };
|
113 | }
|
114 | try {
|
115 | const typeDefinitions = flattened(Object.values(typeDefinitionsMap));
|
116 | const directives = flattened(Object.values(directivesMap));
|
117 | let schema = (0, graphql_1.buildASTSchema)({
|
118 | kind: graphql_1.Kind.DOCUMENT,
|
119 | definitions: [...typeDefinitions, ...directives],
|
120 | });
|
121 | const typeExtensions = flattened(Object.values(typeExtensionsMap));
|
122 | if (typeExtensions.length > 0) {
|
123 | schema = (0, graphql_1.extendSchema)(schema, {
|
124 | kind: graphql_1.Kind.DOCUMENT,
|
125 | definitions: typeExtensions,
|
126 | });
|
127 | }
|
128 | for (const module of modules) {
|
129 | if ("kind" in module || !module.resolvers)
|
130 | continue;
|
131 | addResolversToSchema(schema, module.resolvers);
|
132 | }
|
133 | return { schema };
|
134 | }
|
135 | catch (error) {
|
136 | return { errors: [error] };
|
137 | }
|
138 | }
|
139 | exports.buildServiceDefinition = buildServiceDefinition;
|
140 | function addResolversToSchema(schema, resolvers) {
|
141 | for (const [typeName, fieldConfigs] of Object.entries(resolvers)) {
|
142 | const type = schema.getType(typeName);
|
143 | if (!(0, graphql_1.isObjectType)(type))
|
144 | continue;
|
145 | const fieldMap = type.getFields();
|
146 | for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
|
147 | if (fieldName.startsWith("__")) {
|
148 | type[fieldName.substring(2)] = fieldConfig;
|
149 | continue;
|
150 | }
|
151 | const field = fieldMap[fieldName];
|
152 | if (!field)
|
153 | continue;
|
154 | if (typeof fieldConfig === "function") {
|
155 | field.resolve = fieldConfig;
|
156 | }
|
157 | else {
|
158 | if (fieldConfig.resolve) {
|
159 | field.resolve = fieldConfig.resolve;
|
160 | }
|
161 | if (fieldConfig.subscribe) {
|
162 | field.subscribe = fieldConfig.subscribe;
|
163 | }
|
164 | }
|
165 | }
|
166 | }
|
167 | }
|
168 |
|
\ | No newline at end of file |