1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const intermediates_1 = require("./intermediates");
|
4 | const extendedIntermediates_1 = require("./extendedIntermediates");
|
5 | const immutable_1 = require("immutable");
|
6 | const normalizableSelectionsFromExtendedFieldType = (type) => {
|
7 | switch (type.kind) {
|
8 | case "InlineSelection":
|
9 | return NormalizableSelections(type);
|
10 | case "Maybe":
|
11 | return normalizableSelectionsFromExtendedFieldType(type.ofType);
|
12 | case "List":
|
13 | return normalizableSelectionsFromExtendedFieldType(type.ofType);
|
14 | default:
|
15 | return immutable_1.Map();
|
16 | }
|
17 | };
|
18 | const selectTypename = (__typename) => (field) => field.type.kind == "Typename"
|
19 | ? { type: intermediates_1.Typename(immutable_1.Set([__typename])), optional: field.optional }
|
20 | : field;
|
21 | const NormalizableSelections = (selection) => selection.fields.reduce((normalizedSelections, fields, __typename) => fields.reduce((normalizedSelections, field) => normalizedSelections.mergeDeep(normalizableSelectionsFromExtendedFieldType(field.type)), isNormalizable(fields)
|
22 | ? normalizedSelections.mergeDeep(immutable_1.Map({
|
23 | [__typename]: immutable_1.List([fields.map(selectTypename(__typename))])
|
24 | }))
|
25 | : normalizedSelections), immutable_1.Map());
|
26 | const normalizeFieldType = (type) => {
|
27 | switch (type.kind) {
|
28 | case "InlineSelection":
|
29 | return normalizeSelection(type);
|
30 | case "Maybe":
|
31 | return intermediates_1.Maybe(normalizeFieldType(type.ofType));
|
32 | case "List":
|
33 | return intermediates_1.List(normalizeFieldType(type.ofType));
|
34 | default:
|
35 | return type;
|
36 | }
|
37 | };
|
38 | const normalizeField = ({ type, optional }) => ({
|
39 | type: normalizeFieldType(type),
|
40 | optional
|
41 | });
|
42 | const normalizeSelection = (selection) => ({
|
43 | kind: "InlineSelection",
|
44 | fields: selection.fields.map(fields => isNormalizable(fields)
|
45 | ? fields.filter((_, fieldName) => fieldName == "__typename" || fieldName == "id")
|
46 | : fields.map(normalizeField))
|
47 | });
|
48 | const returnIfEqual = (__typename, fieldName, lhs, rhs) => {
|
49 | const differentKindsError = Error(`${lhs.kind} is not the same as ${rhs.kind}`);
|
50 | switch (lhs.kind) {
|
51 | case "Typename":
|
52 | if (rhs.kind != "Typename") {
|
53 | throw differentKindsError;
|
54 | }
|
55 | if (!lhs.possibleTypes.equals(rhs.possibleTypes)) {
|
56 | throw Error(`${lhs.possibleTypes} are not the same as ${rhs.possibleTypes}`);
|
57 | }
|
58 | return rhs;
|
59 | case "Enum":
|
60 | if (rhs.kind != "Enum") {
|
61 | throw differentKindsError;
|
62 | }
|
63 | if (lhs.name != rhs.name) {
|
64 | throw Error(`${lhs.name} is different than ${rhs.name}`);
|
65 | }
|
66 | if (lhs.values != rhs.values) {
|
67 | throw Error(`Possible values ${lhs.values} are not the same as ${rhs.values}`);
|
68 | }
|
69 | return rhs;
|
70 | case "Scalar":
|
71 | if (rhs.kind != "Scalar") {
|
72 | throw differentKindsError;
|
73 | }
|
74 | if (lhs.name != rhs.name) {
|
75 | throw Error(`Types ${lhs.name} and ${rhs.name} are not the same`);
|
76 | }
|
77 | return rhs;
|
78 | case "InlineSelection":
|
79 | if (rhs.kind != "InlineSelection") {
|
80 | throw differentKindsError;
|
81 | }
|
82 | if (!extendedIntermediates_1.extendedSelectionsAreEqual(lhs, rhs)) {
|
83 | throw Error(`${__typename} can't be normalized because it has conflicting definitions for "${fieldName}" that could lead to runtime bugs. Either alias the field name or make the selections the same.`);
|
84 | }
|
85 | return rhs;
|
86 | case "List":
|
87 | if (rhs.kind != "List") {
|
88 | throw differentKindsError;
|
89 | }
|
90 | return intermediates_1.List(returnIfEqual(__typename, fieldName, lhs.ofType, rhs.ofType));
|
91 | case "Maybe":
|
92 | if (rhs.kind != "Maybe") {
|
93 | throw differentKindsError;
|
94 | }
|
95 | return intermediates_1.Maybe(returnIfEqual(__typename, fieldName, lhs.ofType, rhs.ofType));
|
96 | }
|
97 | };
|
98 | const mergeExtendedSelections = (lhs, rhs) => {
|
99 | return {
|
100 | kind: "InlineSelection",
|
101 | fields: lhs.fields.mergeWith((lhs, rhs, __typename) => mergeFields(__typename)(lhs, rhs), rhs.fields)
|
102 | };
|
103 | };
|
104 | const isNormalizable = (fields) => fields.has("__typename") && fields.has("id");
|
105 | const mergeField = (__typename) => (lhs, rhs, fieldName) => ({
|
106 | type: lhs.type.kind == "InlineSelection" &&
|
107 | rhs.type.kind == "InlineSelection" &&
|
108 | !lhs.type.fields.some(isNormalizable) &&
|
109 | !rhs.type.fields.some(isNormalizable)
|
110 | ? mergeExtendedSelections(lhs.type, rhs.type)
|
111 | : returnIfEqual(__typename, fieldName, lhs.type, rhs.type),
|
112 | optional: lhs.optional || rhs.optional
|
113 | });
|
114 | const mergeFields = (__typename) => (lhs, rhs) => {
|
115 | const intersection = immutable_1.Set(lhs.keySeq()).intersect(immutable_1.Set(rhs.keySeq()));
|
116 | return lhs
|
117 | .mergeWith(mergeField(__typename), rhs)
|
118 | .map((field, fieldName) => !intersection.contains(fieldName)
|
119 | ? { type: field.type, optional: true }
|
120 | : field);
|
121 | };
|
122 | exports.normalizedTypes = (context) => {
|
123 | const fragments = Object.values(context.fragments).reduce((fragments, fragment) => (Object.assign({}, fragments, { [fragment.fragmentName]: intermediates_1.InlineSelection(fragment.selectionSet) })), {});
|
124 | const extendedSelections = Object.values(context.operations).map(operation => extendedIntermediates_1.ExtendedSelection(intermediates_1.InlineSelection(operation.selectionSet), fragments));
|
125 | const normalizableSelections = extendedSelections.reduce((normalizedSelections, extendedSelection) => normalizedSelections.mergeDeep(NormalizableSelections(extendedSelection)), immutable_1.Map());
|
126 | return normalizableSelections.map((fields, __typename) => fields.reduce(mergeFields(__typename)).map(normalizeField));
|
127 | };
|
128 |
|
\ | No newline at end of file |