UNPKG

4.04 kBPlain TextView Raw
1import {
2 InlineSelection,
3 FragmentOrSelection,
4 Field,
5 OutputType,
6 Typename,
7 List,
8 Maybe,
9 Type,
10 Leaf
11} from "./intermediates";
12import { Set, Map } from "immutable";
13import { every } from "lodash";
14
15export type Fragments = {
16 [fragment: string]: InlineSelection;
17};
18
19type Curry<T, U, V> = (t: T) => (u: U) => V;
20
21export type ExtendedFieldType = Type<ExtendedSelection | Leaf | Typename>;
22
23const ExtendedFieldType: Curry<
24 Fragments,
25 OutputType | Typename,
26 ExtendedFieldType
27> = fragments => type => {
28 switch (type.kind) {
29 case "FragmentReference":
30 case "InlineSelection":
31 return ExtendedFragmentOrSelection(fragments)(type);
32 case "List":
33 return List(ExtendedFieldType(fragments)(type.ofType));
34 case "Maybe":
35 return Maybe(ExtendedFieldType(fragments)(type.ofType));
36 default:
37 return type;
38 }
39};
40
41const typesAreEqual = (
42 lhs: ExtendedFieldType,
43 rhs: ExtendedFieldType
44): boolean => {
45 switch (lhs.kind) {
46 case "Enum":
47 return lhs.kind == rhs.kind && lhs.name == rhs.name;
48 case "Typename":
49 return (
50 lhs.kind == rhs.kind && lhs.possibleTypes.equals(rhs.possibleTypes)
51 );
52 case "Scalar":
53 return lhs.kind == rhs.kind && lhs.name == rhs.name;
54 case "InlineSelection":
55 return lhs.kind == rhs.kind && extendedSelectionsAreEqual(lhs, rhs);
56 case "Maybe":
57 return lhs.kind == rhs.kind && typesAreEqual(lhs.ofType, rhs.ofType);
58 case "List":
59 return lhs.kind == rhs.kind && typesAreEqual(lhs.ofType, rhs.ofType);
60 }
61};
62
63export type ExtendedField = { type: ExtendedFieldType; optional: boolean };
64
65const nameAndField: Curry<
66 Fragments,
67 Field,
68 [fieldName, ExtendedField]
69> = fragments => field => [
70 field.name,
71 { type: ExtendedFieldType(fragments)(field.type), optional: false }
72];
73
74export type __typename = string;
75export type fieldName = string;
76export type ByTypename<T> = Map<__typename, T>;
77export type ExtendedFields = Map<fieldName, ExtendedField>;
78
79export type ExtendedSelection = {
80 kind: "InlineSelection";
81 fields: ByTypename<ExtendedFields>;
82};
83
84export const ExtendedSelection = (
85 inlineSelection: InlineSelection,
86 fragments: Fragments
87): ExtendedSelection => {
88 return {
89 kind: inlineSelection.kind,
90 fields: Map(
91 inlineSelection.possibleTypes.map(
92 (
93 type
94 ): [
95 __typename,
96 Map<fieldName, { type: ExtendedFieldType; optional: boolean }>
97 ] => [type, Map(inlineSelection.fields.map(nameAndField(fragments)))]
98 )
99 ).mergeDeep(
100 ...inlineSelection.intersections
101 .map(ExtendedFragmentOrSelection(fragments))
102 .map(selection => selection.fields),
103 ...inlineSelection.typeConditions
104 .map(ExtendedFragmentOrSelection(fragments))
105 .map(selection => selection.fields),
106 ...inlineSelection.booleanConditions
107 .map(ExtendedFragmentOrSelection(fragments))
108 .map(selection => selection.fields)
109 )
110 };
111};
112
113export const ExtendedFragmentOrSelection: Curry<
114 Fragments,
115 FragmentOrSelection,
116 ExtendedSelection
117> = fragments => fragmentOrSelection =>
118 fragmentOrSelection.kind == "InlineSelection"
119 ? ExtendedSelection(fragmentOrSelection, fragments)
120 : ExtendedSelection(fragments[fragmentOrSelection.name], fragments);
121
122const mapsAreEqual = <V>(
123 lhs: Map<string, V>,
124 rhs: Map<string, V>,
125 compareValues: (lhs: V, rhs: V) => boolean
126): boolean =>
127 Set(lhs.keySeq()).equals(Set(rhs.keySeq())) &&
128 every(lhs.keySeq().toArray(), key =>
129 compareValues(lhs.get(key)!, rhs.get(key)!)
130 );
131
132const extendedFieldsAreEqual = (
133 lhs: ByTypename<ExtendedFields>,
134 rhs: ByTypename<ExtendedFields>
135): boolean =>
136 mapsAreEqual(lhs, rhs, (lhs, rhs) =>
137 mapsAreEqual(
138 lhs,
139 rhs,
140 (lhs, rhs) =>
141 lhs.optional == rhs.optional && typesAreEqual(lhs.type, rhs.type)
142 )
143 );
144
145export const extendedSelectionsAreEqual = (
146 lhs: ExtendedSelection,
147 rhs: ExtendedSelection
148): boolean => extendedFieldsAreEqual(lhs.fields, rhs.fields);