Skip to content
This repository was archived by the owner on Sep 3, 2021. It is now read-only.

Commit c2f4328

Browse files
authored
Merge pull request #339 from michaeldgraham/master
Fixes for generated schema type and default config
2 parents 42f6ca3 + 6615910 commit c2f4328

12 files changed

+427
-351
lines changed

src/augment/augment.js

+51-171
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,14 @@ import {
66
isTypeExtensionNode
77
} from 'graphql';
88
import { makeExecutableSchema } from 'graphql-tools';
9+
import { buildDocument } from './ast';
910
import {
10-
buildDocument,
11-
buildOperationType,
12-
buildSchemaDefinition,
13-
buildName,
14-
buildNamedType,
15-
buildObjectType
16-
} from './ast';
17-
import {
18-
OperationType,
19-
isNodeType,
11+
initializeOperationTypes,
12+
augmentSchemaType,
2013
augmentTypes,
21-
transformNeo4jTypes
14+
transformNeo4jTypes,
15+
regenerateSchemaType
2216
} from './types/types';
23-
import { unwrapNamedType } from './fields';
2417
import { augmentDirectiveDefinitions } from './directives';
2518
import { extractResolversFromSchema, augmentResolvers } from './resolvers';
2619
import { addAuthDirectiveImplementations } from '../auth';
@@ -40,13 +33,15 @@ export const makeAugmentedExecutableSchema = ({
4033
inheritResolversFromInterfaces,
4134
config
4235
}) => {
36+
config = setDefaultConfig({ config });
4337
const definitions = parse(typeDefs).definitions;
4438
let generatedTypeMap = {};
4539
let [
4640
typeDefinitionMap,
4741
typeExtensionDefinitionMap,
4842
directiveDefinitionMap,
49-
operationTypeMap
43+
operationTypeMap,
44+
schemaTypeDefinition
5045
] = mapDefinitions({
5146
definitions,
5247
config
@@ -76,7 +71,8 @@ export const makeAugmentedExecutableSchema = ({
7671
generatedTypeMap,
7772
typeExtensionDefinitionMap,
7873
operationTypeMap,
79-
directiveDefinitionMap
74+
directiveDefinitionMap,
75+
schemaTypeDefinition
8076
});
8177
const transformedDefinitions = transformNeo4jTypes({
8278
definitions: mergedDefinitions,
@@ -109,12 +105,14 @@ export const makeAugmentedExecutableSchema = ({
109105
* The main export for augmnetation a schema
110106
*/
111107
export const augmentedSchema = (schema, config) => {
108+
config = setDefaultConfig({ config });
112109
const definitions = extractSchemaDefinitions({ schema });
113110
let [
114111
typeDefinitionMap,
115112
typeExtensionDefinitionMap,
116113
directiveDefinitionMap,
117-
operationTypeMap
114+
operationTypeMap,
115+
schemaTypeDefinition
118116
] = mapDefinitions({
119117
definitions,
120118
config
@@ -146,7 +144,8 @@ export const augmentedSchema = (schema, config) => {
146144
generatedTypeMap,
147145
typeExtensionDefinitionMap,
148146
operationTypeMap,
149-
directiveDefinitionMap
147+
directiveDefinitionMap,
148+
schemaTypeDefinition
150149
});
151150
const transformedDefinitions = transformNeo4jTypes({
152151
definitions: mergedDefinitions,
@@ -179,11 +178,10 @@ export const mapDefinitions = ({ definitions = [], config = {} }) => {
179178
const typeExtensionDefinitionMap = {};
180179
const directiveDefinitionMap = {};
181180
let typeDefinitionMap = {};
182-
let schemaDefinitionNode = undefined;
181+
let schemaTypeDefinition = undefined;
183182
definitions.forEach(def => {
184183
if (def.kind === Kind.SCHEMA_DEFINITION) {
185-
schemaDefinitionNode = def;
186-
typeDefinitionMap[`schema`] = def;
184+
schemaTypeDefinition = def;
187185
} else if (isTypeDefinitionNode(def)) {
188186
const name = def.name.value;
189187
typeDefinitionMap[name] = def;
@@ -200,14 +198,15 @@ export const mapDefinitions = ({ definitions = [], config = {} }) => {
200198
});
201199
const [typeMap, operationTypeMap] = initializeOperationTypes({
202200
typeDefinitionMap,
203-
schemaDefinitionNode,
201+
schemaTypeDefinition,
204202
config
205203
});
206204
return [
207205
typeMap,
208206
typeExtensionDefinitionMap,
209207
directiveDefinitionMap,
210-
operationTypeMap
208+
operationTypeMap,
209+
schemaTypeDefinition
211210
];
212211
};
213212

@@ -218,7 +217,8 @@ export const mergeDefinitionMaps = ({
218217
generatedTypeMap = {},
219218
typeExtensionDefinitionMap = {},
220219
operationTypeMap = {},
221-
directiveDefinitionMap = {}
220+
directiveDefinitionMap = {},
221+
schemaTypeDefinition
222222
}) => {
223223
const typeExtensions = Object.values(typeExtensionDefinitionMap);
224224
if (typeExtensions) {
@@ -230,12 +230,17 @@ export const mergeDefinitionMaps = ({
230230
[]
231231
);
232232
}
233-
return Object.values({
233+
let definitions = Object.values({
234234
...generatedTypeMap,
235235
...typeExtensionDefinitionMap,
236-
...operationTypeMap,
237236
...directiveDefinitionMap
238237
});
238+
definitions = augmentSchemaType({
239+
definitions,
240+
schemaTypeDefinition,
241+
operationTypeMap
242+
});
243+
return definitions;
239244
};
240245

241246
/**
@@ -271,132 +276,37 @@ export const shouldAugmentRelationshipField = (
271276
);
272277
};
273278

274-
/**
275-
* Prints the AST of a GraphQL SDL Document containing definitions
276-
* extracted from a given schema, along with no loss of directives and a
277-
* regenerated schema type
278-
*/
279-
export const printSchemaDocument = ({ schema }) => {
280-
return print(
281-
buildDocument({
282-
definitions: extractSchemaDefinitions({ schema })
283-
})
284-
);
279+
// An enum containing the names of the augmentation config keys
280+
const APIConfiguration = {
281+
QUERY: 'query',
282+
MUTATION: 'mutation',
283+
TEMPORAL: 'temporal',
284+
SPATIAL: 'spatial'
285285
};
286286

287287
/**
288-
* Builds any operation types that do not exist but should
288+
* Builds the default values in a given configuration object
289289
*/
290-
const initializeOperationTypes = ({
291-
typeDefinitionMap,
292-
schemaDefinitionNode,
293-
config = {}
294-
}) => {
295-
let queryTypeName = OperationType.QUERY;
296-
let mutationTypeName = OperationType.MUTATION;
297-
let subscriptionTypeName = OperationType.SUBSCRIPTION;
298-
if (schemaDefinitionNode) {
299-
const operationTypes = schemaDefinitionNode.operationTypes;
300-
operationTypes.forEach(definition => {
301-
const operation = definition.operation;
302-
const unwrappedType = unwrapNamedType({ type: definition.type });
303-
if (operation === queryTypeName.toLowerCase()) {
304-
queryTypeName = unwrappedType.name;
305-
} else if (operation === mutationTypeName.toLowerCase()) {
306-
mutationTypeName = unwrappedType.name;
307-
} else if (operation === subscriptionTypeName.toLowerCase()) {
308-
subscriptionTypeName = unwrappedType.name;
309-
}
310-
});
311-
}
312-
typeDefinitionMap = initializeOperationType({
313-
typeName: queryTypeName,
314-
typeDefinitionMap,
315-
config
316-
});
317-
typeDefinitionMap = initializeOperationType({
318-
typeName: mutationTypeName,
319-
typeDefinitionMap,
320-
config
321-
});
322-
typeDefinitionMap = initializeOperationType({
323-
typeName: subscriptionTypeName,
324-
typeDefinitionMap,
325-
config
326-
});
327-
return buildAugmentationTypeMaps({
328-
typeDefinitionMap,
329-
queryTypeName,
330-
mutationTypeName,
331-
subscriptionTypeName
332-
});
333-
};
334-
335-
/**
336-
* Builds an operation type if it does not exist but should
337-
*/
338-
const initializeOperationType = ({
339-
typeName = '',
340-
typeDefinitionMap = {},
341-
config = {}
342-
}) => {
343-
const typeNameLower = typeName.toLowerCase();
344-
const types = Object.keys(typeDefinitionMap);
345-
let operationType = typeDefinitionMap[typeName];
346-
if (
347-
hasNonExcludedNodeType(types, typeDefinitionMap, typeNameLower, config) &&
348-
!operationType &&
349-
config[typeNameLower]
350-
) {
351-
operationType = buildObjectType({
352-
name: buildName({ name: typeName })
353-
});
354-
}
355-
if (operationType) typeDefinitionMap[typeName] = operationType;
356-
return typeDefinitionMap;
357-
};
358-
359-
/**
360-
* Ensures that an operation type is only generated if an operation
361-
* field would be generated - should be able to factor out
362-
*/
363-
const hasNonExcludedNodeType = (types, typeMap, rootType, config) => {
364-
return types.find(e => {
365-
const type = typeMap[e];
366-
const typeName = type.name ? type.name.value : '';
367-
if (typeName) {
368-
return (
369-
isNodeType({ definition: type }) &&
370-
shouldAugmentType(config, rootType, typeName)
371-
);
290+
const setDefaultConfig = ({ config = {} }) => {
291+
const configKeys = Object.keys(config);
292+
Object.values(APIConfiguration).forEach(configKey => {
293+
if (!configKeys.find(providedKey => providedKey === configKey)) {
294+
config[configKey] = true;
372295
}
373296
});
297+
return config;
374298
};
375299

376300
/**
377-
* Builds a typeDefinitionMap that excludes operation types, instead placing them
378-
* within an operationTypeMap
301+
* Prints the AST of a GraphQL SDL Document containing definitions
302+
* extracted from a given schema, along with no loss of directives and a
303+
* regenerated schema type
379304
*/
380-
const buildAugmentationTypeMaps = ({
381-
typeDefinitionMap = {},
382-
queryTypeName,
383-
mutationTypeName,
384-
subscriptionTypeName
385-
}) => {
386-
return Object.entries(typeDefinitionMap).reduce(
387-
([augmentationTypeMap, operationTypeMap], [typeName, definition]) => {
388-
if (typeName === queryTypeName) {
389-
operationTypeMap[OperationType.QUERY] = definition;
390-
} else if (typeName === mutationTypeName) {
391-
operationTypeMap[OperationType.MUTATION] = definition;
392-
} else if (typeName === subscriptionTypeName) {
393-
operationTypeMap[OperationType.SUBSCRIPTION] = definition;
394-
} else {
395-
augmentationTypeMap[typeName] = definition;
396-
}
397-
return [augmentationTypeMap, operationTypeMap];
398-
},
399-
[{}, {}]
305+
export const printSchemaDocument = ({ schema }) => {
306+
return print(
307+
buildDocument({
308+
definitions: extractSchemaDefinitions({ schema })
309+
})
400310
);
401311
};
402312

@@ -411,6 +321,7 @@ const extractSchemaDefinitions = ({ schema = {} }) => {
411321
const astNode = definition.astNode;
412322
if (astNode) {
413323
astNodes.push(astNode);
324+
// Extract embedded type extensions
414325
const extensionASTNodes = definition.extensionASTNodes;
415326
if (extensionASTNodes) {
416327
astNodes.push(...extensionASTNodes);
@@ -422,37 +333,6 @@ const extractSchemaDefinitions = ({ schema = {} }) => {
422333
return definitions;
423334
};
424335

425-
/**
426-
* Regenerates the schema type definition using any existing operation types
427-
*/
428-
const regenerateSchemaType = ({ schema = {}, definitions = [] }) => {
429-
const operationTypes = [];
430-
Object.values(OperationType).forEach(name => {
431-
let operationType = undefined;
432-
if (name === OperationType.QUERY) operationType = schema.getQueryType();
433-
else if (name === OperationType.MUTATION)
434-
operationType = schema.getMutationType();
435-
else if (name === OperationType.SUBSCRIPTION)
436-
operationType = schema.getSubscriptionType();
437-
if (operationType) {
438-
operationTypes.push(
439-
buildOperationType({
440-
operation: name.toLowerCase(),
441-
type: buildNamedType({ name: operationType.name })
442-
})
443-
);
444-
}
445-
});
446-
if (operationTypes.length) {
447-
definitions.push(
448-
buildSchemaDefinition({
449-
operationTypes
450-
})
451-
);
452-
}
453-
return definitions;
454-
};
455-
456336
/**
457337
* Getter for an array of type names excludes from an operation type
458338
*/

0 commit comments

Comments
 (0)