forked from neo4j-graphql/neo4j-graphql-js
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathschemaAssert.js
79 lines (75 loc) · 2.53 KB
/
schemaAssert.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { getFieldDirective } from './utils';
import { DirectiveDefinition } from './augment/directives';
import { isNodeType, isUnionTypeDefinition } from './augment/types/types';
import { getKeyFields } from './augment/types/node/selection';
export const schemaAssert = ({
schema,
indexLabels,
constraintLabels,
dropExisting = true
}) => {
if (!indexLabels) indexLabels = `{}`;
if (!constraintLabels) constraintLabels = `{}`;
if (schema) {
const indexFieldTypeMap = buildKeyTypeMap({
schema,
directives: [DirectiveDefinition.INDEX]
});
indexLabels = cypherMap({
typeMap: indexFieldTypeMap
});
const uniqueFieldTypeMap = buildKeyTypeMap({
schema,
directives: [DirectiveDefinition.ID, DirectiveDefinition.UNIQUE]
});
constraintLabels = cypherMap({
typeMap: uniqueFieldTypeMap
});
}
return `CALL apoc.schema.assert(${indexLabels}, ${constraintLabels}${
dropExisting === false ? `, ${dropExisting}` : ''
})`;
};
const buildKeyTypeMap = ({ schema, directives = [] }) => {
const typeMap = schema ? schema.getTypeMap() : {};
return Object.entries(typeMap).reduce(
(mapped, [typeName, { astNode: definition }]) => {
if (
isNodeType({ definition }) &&
!isUnionTypeDefinition({ definition })
) {
const type = schema.getType(typeName);
const fieldMap = type.getFields();
const fields = Object.values(fieldMap).map(field => field.astNode);
const keyFields = getKeyFields({ fields });
if (keyFields.length && directives.length) {
const directiveFields = keyFields.filter(field => {
// there exists at least one directive on this field
// matching a directive we want to map
return directives.some(directive =>
getFieldDirective(field, directive)
);
});
if (directiveFields.length) {
mapped[typeName] = {
...definition,
fields: directiveFields
};
}
}
}
return mapped;
},
{}
);
};
const cypherMap = ({ typeMap = {} }) => {
// The format of a Cypher map is close to JSON but does not quote keys
const cypherMapFormat = Object.entries(typeMap).map(([typeName, astNode]) => {
const fields = astNode.fields || [];
const fieldNames = fields.map(field => field.name.value);
return `${typeName}:${cypherList({ values: fieldNames })}`;
});
return `{${cypherMapFormat}}`;
};
const cypherList = ({ values = [] }) => JSON.stringify(values);