@apollo/federation-internals 2.4.0-alpha.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.operationToDocument = exports.parseSelectionSet = exports.parseOperation = exports.operationFromDocument = exports.FragmentSelection = exports.FieldSelection = exports.selectionOfElement = exports.selectionSetOfElement = exports.allFieldDefinitionsInSelectionSet = exports.SelectionSet = exports.NamedFragments = exports.NamedFragmentDefinition = exports.selectionSetOf = exports.Operation = exports.concatOperationPaths = exports.conditionalDirectivesInOperationPath = exports.sameOperationPaths = exports.operationPathToStringPath = exports.FragmentElement = exports.Field = void 0;
3
+ exports.operationToDocument = exports.parseSelectionSet = exports.parseOperation = exports.operationFromDocument = exports.FragmentSelection = exports.FieldSelection = exports.selectionOfElement = exports.selectionSetOfElement = exports.selectionSetOf = exports.allFieldDefinitionsInSelectionSet = exports.MutableSelectionSet = exports.SelectionSetUpdates = exports.SelectionSet = exports.NamedFragments = exports.NamedFragmentDefinition = exports.Operation = exports.concatOperationPaths = exports.conditionalDirectivesInOperationPath = exports.sameOperationPaths = exports.operationPathToStringPath = exports.FragmentElement = exports.Field = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const definitions_1 = require("./definitions");
6
6
  const error_1 = require("./error");
7
7
  const types_1 = require("./types");
8
8
  const utils_1 = require("./utils");
9
9
  const values_1 = require("./values");
10
+ const uuid_1 = require("uuid");
10
11
  function validate(condition, message, sourceAST) {
11
12
  if (!condition) {
12
13
  throw error_1.ERRORS.INVALID_GRAPHQL.err(message(), { nodes: sourceAST });
@@ -16,12 +17,12 @@ function haveSameDirectives(op1, op2) {
16
17
  return (0, definitions_1.sameDirectiveApplications)(op1.appliedDirectives, op2.appliedDirectives);
17
18
  }
18
19
  class AbstractOperationElement extends definitions_1.DirectiveTargetElement {
19
- constructor(schema, variablesInElement) {
20
- super(schema);
21
- this.variablesInElement = variablesInElement;
20
+ constructor(schema, directives) {
21
+ super(schema, directives);
22
22
  }
23
- variables() {
24
- return (0, definitions_1.mergeVariables)(this.variablesInElement, this.variablesInAppliedDirectives());
23
+ collectVariables(collector) {
24
+ this.collectVariablesInElement(collector);
25
+ this.collectVariablesInAppliedDirectives(collector);
25
26
  }
26
27
  addAttachement(key, value) {
27
28
  if (!this.attachements) {
@@ -42,44 +43,76 @@ class AbstractOperationElement extends definitions_1.DirectiveTargetElement {
42
43
  }
43
44
  }
44
45
  class Field extends AbstractOperationElement {
45
- constructor(definition, args = Object.create(null), variableDefinitions = new definitions_1.VariableDefinitions(), alias) {
46
- super(definition.schema(), (0, definitions_1.variablesInArguments)(args));
46
+ constructor(definition, args, directives, alias) {
47
+ super(definition.schema(), directives);
47
48
  this.definition = definition;
48
49
  this.args = args;
49
- this.variableDefinitions = variableDefinitions;
50
50
  this.alias = alias;
51
51
  this.kind = 'Field';
52
52
  }
53
+ collectVariablesInElement(collector) {
54
+ if (this.args) {
55
+ collector.collectInArguments(this.args);
56
+ }
57
+ }
53
58
  get name() {
54
59
  return this.definition.name;
55
60
  }
61
+ argumentValue(name) {
62
+ return this.args ? this.args[name] : undefined;
63
+ }
56
64
  responseName() {
57
65
  return this.alias ? this.alias : this.name;
58
66
  }
67
+ key() {
68
+ return this.responseName();
69
+ }
70
+ asPathElement() {
71
+ return this.responseName();
72
+ }
59
73
  get parentType() {
60
74
  return this.definition.parent;
61
75
  }
76
+ isLeafField() {
77
+ return (0, definitions_1.isLeafType)((0, definitions_1.baseType)(this.definition.type));
78
+ }
62
79
  withUpdatedDefinition(newDefinition) {
63
- const newField = new Field(newDefinition, this.args, this.variableDefinitions, this.alias);
64
- for (const directive of this.appliedDirectives) {
65
- newField.applyDirective(directive.definition, directive.arguments());
66
- }
80
+ const newField = new Field(newDefinition, this.args, this.appliedDirectives, this.alias);
67
81
  this.copyAttachementsTo(newField);
68
82
  return newField;
69
83
  }
70
84
  withUpdatedAlias(newAlias) {
71
- const newField = new Field(this.definition, this.args, this.variableDefinitions, newAlias);
72
- for (const directive of this.appliedDirectives) {
73
- newField.applyDirective(directive.definition, directive.arguments());
74
- }
85
+ const newField = new Field(this.definition, this.args, this.appliedDirectives, newAlias);
86
+ this.copyAttachementsTo(newField);
87
+ return newField;
88
+ }
89
+ withUpdatedDirectives(newDirectives) {
90
+ const newField = new Field(this.definition, this.args, newDirectives, this.alias);
75
91
  this.copyAttachementsTo(newField);
76
92
  return newField;
77
93
  }
94
+ argumentsToNodes() {
95
+ if (!this.args) {
96
+ return undefined;
97
+ }
98
+ const entries = Object.entries(this.args);
99
+ if (entries.length === 0) {
100
+ return undefined;
101
+ }
102
+ return entries.map(([n, v]) => {
103
+ return {
104
+ kind: graphql_1.Kind.ARGUMENT,
105
+ name: { kind: graphql_1.Kind.NAME, value: n },
106
+ value: (0, values_1.valueToAST)(v, this.definition.argument(n).type),
107
+ };
108
+ });
109
+ }
78
110
  appliesTo(type) {
79
111
  const definition = type.field(this.name);
80
112
  return !!definition && this.selects(definition);
81
113
  }
82
- selects(definition, assumeValid = false) {
114
+ selects(definition, assumeValid = false, variableDefinitions) {
115
+ (0, utils_1.assert)(assumeValid || variableDefinitions, 'Must provide variable definitions if validation is needed');
83
116
  if (definition === this.definition) {
84
117
  return true;
85
118
  }
@@ -87,19 +120,19 @@ class Field extends AbstractOperationElement {
87
120
  return false;
88
121
  }
89
122
  for (const argDef of definition.arguments()) {
90
- const appliedValue = this.args[argDef.name];
123
+ const appliedValue = this.argumentValue(argDef.name);
91
124
  if (appliedValue === undefined) {
92
125
  if (argDef.defaultValue === undefined && !(0, definitions_1.isNullableType)(argDef.type)) {
93
126
  return false;
94
127
  }
95
128
  }
96
129
  else {
97
- if (!assumeValid && !(0, values_1.isValidValue)(appliedValue, argDef, this.variableDefinitions)) {
130
+ if (!assumeValid && !(0, values_1.isValidValue)(appliedValue, argDef, variableDefinitions)) {
98
131
  return false;
99
132
  }
100
133
  }
101
134
  }
102
- if (!assumeValid) {
135
+ if (!assumeValid && this.args) {
103
136
  for (const [name, value] of Object.entries(this.args)) {
104
137
  if (value !== null && definition.argument(name) === undefined) {
105
138
  return false;
@@ -108,33 +141,34 @@ class Field extends AbstractOperationElement {
108
141
  }
109
142
  return true;
110
143
  }
111
- validate() {
144
+ validate(variableDefinitions) {
112
145
  validate(this.name === this.definition.name, () => `Field name "${this.name}" cannot select field "${this.definition.coordinate}: name mismatch"`);
113
146
  for (const argDef of this.definition.arguments()) {
114
- const appliedValue = this.args[argDef.name];
147
+ const appliedValue = this.argumentValue(argDef.name);
115
148
  if (appliedValue === undefined) {
116
149
  validate(argDef.defaultValue !== undefined || (0, definitions_1.isNullableType)(argDef.type), () => `Missing mandatory value for argument "${argDef.name}" of field "${this.definition.coordinate}" in selection "${this}"`);
117
150
  }
118
151
  else {
119
- validate((0, values_1.isValidValue)(appliedValue, argDef, this.variableDefinitions), () => `Invalid value ${(0, values_1.valueToString)(appliedValue)} for argument "${argDef.coordinate}" of type ${argDef.type}`);
152
+ validate((0, values_1.isValidValue)(appliedValue, argDef, variableDefinitions), () => `Invalid value ${(0, values_1.valueToString)(appliedValue)} for argument "${argDef.coordinate}" of type ${argDef.type}`);
120
153
  }
121
154
  }
122
- for (const [name, value] of Object.entries(this.args)) {
123
- validate(value === null || this.definition.argument(name) !== undefined, () => `Unknown argument "${name}" in field application of "${this.name}"`);
155
+ if (this.args) {
156
+ for (const [name, value] of Object.entries(this.args)) {
157
+ validate(value === null || this.definition.argument(name) !== undefined, () => `Unknown argument "${name}" in field application of "${this.name}"`);
158
+ }
124
159
  }
125
160
  }
126
- updateForAddingTo(selectionSet) {
127
- const selectionParent = selectionSet.parentType;
161
+ rebaseOn(parentType) {
128
162
  const fieldParent = this.definition.parent;
129
- if (selectionParent === fieldParent) {
163
+ if (parentType === fieldParent) {
130
164
  return this;
131
165
  }
132
166
  if (this.name === definitions_1.typenameFieldName) {
133
- return this.withUpdatedDefinition(selectionParent.typenameField());
167
+ return this.withUpdatedDefinition(parentType.typenameField());
134
168
  }
135
- validate(this.canRebaseOn(selectionParent), () => `Cannot add selection of field "${this.definition.coordinate}" to selection set of parent type "${selectionParent}"`);
136
- const fieldDef = selectionParent.field(this.name);
137
- validate(fieldDef, () => `Cannot add selection of field "${this.definition.coordinate}" to selection set of parent type "${selectionParent}" (that does not declare that field)`);
169
+ validate(this.canRebaseOn(parentType), () => `Cannot add selection of field "${this.definition.coordinate}" to selection set of parent type "${parentType}"`);
170
+ const fieldDef = parentType.field(this.name);
171
+ validate(fieldDef, () => `Cannot add selection of field "${this.definition.coordinate}" to selection set of parent type "${parentType}" (that does not declare that field)`);
138
172
  return this.withUpdatedDefinition(fieldDef);
139
173
  }
140
174
  canRebaseOn(parentType) {
@@ -171,34 +205,56 @@ class Field extends AbstractOperationElement {
171
205
  return that.kind === 'Field'
172
206
  && this.name === that.name
173
207
  && this.alias === that.alias
174
- && (0, values_1.argumentsEquals)(this.args, that.args)
208
+ && (this.args ? that.args && (0, values_1.argumentsEquals)(this.args, that.args) : !that.args)
175
209
  && haveSameDirectives(this, that);
176
210
  }
177
211
  toString() {
178
212
  const alias = this.alias ? this.alias + ': ' : '';
179
- const entries = Object.entries(this.args);
180
- const args = entries.length == 0
213
+ const entries = this.args ? Object.entries(this.args) : [];
214
+ const args = entries.length === 0
181
215
  ? ''
182
216
  : '(' + entries.map(([n, v]) => { var _a; return `${n}: ${(0, values_1.valueToString)(v, (_a = this.definition.argument(n)) === null || _a === void 0 ? void 0 : _a.type)}`; }).join(', ') + ')';
183
217
  return alias + this.name + args + this.appliedDirectivesToString();
184
218
  }
185
219
  }
186
220
  exports.Field = Field;
221
+ function keyForDirective(directive, directivesNeverEqualToThemselves = ['defer']) {
222
+ if (directivesNeverEqualToThemselves.includes(directive.name)) {
223
+ return (0, uuid_1.v1)();
224
+ }
225
+ const entries = Object.entries(directive.arguments()).filter(([_, v]) => v !== undefined);
226
+ entries.sort(([n1], [n2]) => n1.localeCompare(n2));
227
+ const args = entries.length == 0 ? '' : '(' + entries.map(([n, v]) => `${n}: ${(0, values_1.valueToString)(v, directive.argumentType(n))}`).join(', ') + ')';
228
+ return `@${directive.name}${args}`;
229
+ }
187
230
  class FragmentElement extends AbstractOperationElement {
188
- constructor(sourceType, typeCondition) {
189
- super(sourceType.schema(), []);
231
+ constructor(sourceType, typeCondition, directives) {
232
+ super(sourceType.schema(), directives);
190
233
  this.sourceType = sourceType;
191
234
  this.kind = 'FragmentElement';
192
235
  this.typeCondition = typeCondition !== undefined && typeof typeCondition === 'string'
193
236
  ? this.schema().type(typeCondition)
194
237
  : typeCondition;
195
238
  }
239
+ collectVariablesInElement(_) {
240
+ }
196
241
  get parentType() {
197
242
  return this.sourceType;
198
243
  }
244
+ key() {
245
+ if (!this.computedKey) {
246
+ const keyForDirectives = this.appliedDirectives.map((d) => keyForDirective(d)).join(' ');
247
+ this.computedKey = '...' + (this.typeCondition ? ' on ' + this.typeCondition.name : '') + keyForDirectives;
248
+ }
249
+ return this.computedKey;
250
+ }
199
251
  castedType() {
200
252
  return this.typeCondition ? this.typeCondition : this.sourceType;
201
253
  }
254
+ asPathElement() {
255
+ const condition = this.typeCondition;
256
+ return condition ? `... on ${condition}` : undefined;
257
+ }
202
258
  withUpdatedSourceType(newSourceType) {
203
259
  return this.withUpdatedTypes(newSourceType, this.typeCondition);
204
260
  }
@@ -206,23 +262,24 @@ class FragmentElement extends AbstractOperationElement {
206
262
  return this.withUpdatedTypes(this.sourceType, newCondition);
207
263
  }
208
264
  withUpdatedTypes(newSourceType, newCondition) {
209
- const newFragment = new FragmentElement(newSourceType, newCondition === null || newCondition === void 0 ? void 0 : newCondition.name);
210
- for (const directive of this.appliedDirectives) {
211
- newFragment.applyDirective(directive.definition, directive.arguments());
212
- }
265
+ const newFragment = new FragmentElement(newSourceType, newCondition === null || newCondition === void 0 ? void 0 : newCondition.name, this.appliedDirectives);
266
+ this.copyAttachementsTo(newFragment);
267
+ return newFragment;
268
+ }
269
+ withUpdatedDirectives(newDirectives) {
270
+ const newFragment = new FragmentElement(this.sourceType, this.typeCondition, newDirectives);
213
271
  this.copyAttachementsTo(newFragment);
214
272
  return newFragment;
215
273
  }
216
- updateForAddingTo(selectionSet) {
217
- const selectionParent = selectionSet.parentType;
274
+ rebaseOn(parentType) {
218
275
  const fragmentParent = this.parentType;
219
276
  const typeCondition = this.typeCondition;
220
- if (selectionParent === fragmentParent) {
277
+ if (parentType === fragmentParent) {
221
278
  return this;
222
279
  }
223
- const { canRebase, rebasedCondition } = this.canRebaseOn(selectionParent);
224
- validate(canRebase, () => `Cannot add fragment of condition "${typeCondition}" (runtimes: [${(0, definitions_1.possibleRuntimeTypes)(typeCondition)}]) to selection set of parent type "${selectionParent}" (runtimes: ${(0, definitions_1.possibleRuntimeTypes)(selectionParent)})`);
225
- return this.withUpdatedTypes(selectionParent, rebasedCondition);
280
+ const { canRebase, rebasedCondition } = this.canRebaseOn(parentType);
281
+ validate(canRebase, () => `Cannot add fragment of condition "${typeCondition}" (runtimes: [${(0, definitions_1.possibleRuntimeTypes)(typeCondition)}]) to parent type "${parentType}" (runtimes: ${(0, definitions_1.possibleRuntimeTypes)(parentType)})`);
282
+ return this.withUpdatedTypes(parentType, rebasedCondition);
226
283
  }
227
284
  canRebaseOn(parentType) {
228
285
  if (!this.typeCondition) {
@@ -260,9 +317,8 @@ class FragmentElement extends AbstractOperationElement {
260
317
  if (updatedDirectives.length === this.appliedDirectives.length) {
261
318
  return this;
262
319
  }
263
- const updated = new FragmentElement(this.sourceType, this.typeCondition);
320
+ const updated = new FragmentElement(this.sourceType, this.typeCondition, updatedDirectives);
264
321
  this.copyAttachementsTo(updated);
265
- updatedDirectives.forEach((d) => updated.applyDirective(d.definition, d.arguments()));
266
322
  return updated;
267
323
  }
268
324
  withNormalizedDefer(normalizer) {
@@ -307,11 +363,12 @@ class FragmentElement extends AbstractOperationElement {
307
363
  if (!newDeferArgs) {
308
364
  return this;
309
365
  }
310
- const updated = new FragmentElement(this.sourceType, this.typeCondition);
311
- this.copyAttachementsTo(updated);
312
366
  const deferDirective = this.schema().deferDirective();
313
- this.appliedDirectives.filter((d) => d.name !== deferDirective.name).forEach((d) => updated.applyDirective(d.definition, d.arguments()));
314
- updated.applyDirective(this.schema().deferDirective(), newDeferArgs);
367
+ const updatedDirectives = this.appliedDirectives
368
+ .filter((d) => d.name !== deferDirective.name)
369
+ .concat(new definitions_1.Directive(deferDirective.name, newDeferArgs));
370
+ const updated = new FragmentElement(this.sourceType, this.typeCondition, updatedDirectives);
371
+ this.copyAttachementsTo(updated);
315
372
  return updated;
316
373
  }
317
374
  equals(that) {
@@ -389,6 +446,7 @@ class Operation {
389
446
  this.name = name;
390
447
  }
391
448
  optimize(fragments, minUsagesToOptimize = 2) {
449
+ var _a;
392
450
  (0, utils_1.assert)(minUsagesToOptimize >= 1, `Expected 'minUsagesToOptimize' to be at least 1, but got ${minUsagesToOptimize}`);
393
451
  if (!fragments || fragments.isEmpty()) {
394
452
  return this;
@@ -405,16 +463,24 @@ class Operation {
405
463
  }
406
464
  }
407
465
  const toDeoptimize = (0, utils_1.mapEntries)(usages).filter(([_, count]) => count < minUsagesToOptimize).map(([name]) => name);
408
- optimizedSelection = optimizedSelection.expandFragments(toDeoptimize);
466
+ const newFragments = (_a = optimizedSelection.fragments) === null || _a === void 0 ? void 0 : _a.without(toDeoptimize);
467
+ optimizedSelection = optimizedSelection.expandFragments(toDeoptimize, newFragments);
409
468
  return new Operation(this.schema, this.rootKind, optimizedSelection, this.variableDefinitions, this.name);
410
469
  }
411
470
  expandAllFragments() {
412
- const expandedSelections = this.selectionSet.expandFragments();
471
+ const expandedSelections = this.selectionSet.expandAllFragments();
413
472
  if (expandedSelections === this.selectionSet) {
414
473
  return this;
415
474
  }
416
475
  return new Operation(this.schema, this.rootKind, expandedSelections, this.variableDefinitions, this.name);
417
476
  }
477
+ trimUnsatisfiableBranches() {
478
+ const trimmedSelections = this.selectionSet.trimUnsatisfiableBranches(this.selectionSet.parentType);
479
+ if (trimmedSelections === this.selectionSet) {
480
+ return this;
481
+ }
482
+ return new Operation(this.schema, this.rootKind, trimmedSelections, this.variableDefinitions, this.name);
483
+ }
418
484
  withoutDefer(labelsToRemove) {
419
485
  (0, utils_1.assert)(!this.selectionSet.fragments || this.selectionSet.fragments.isEmpty(), 'Removing @defer currently only work on "expanded" selections (no named fragments)');
420
486
  const updated = this.selectionSet.withoutDefer(labelsToRemove);
@@ -452,35 +518,23 @@ class Operation {
452
518
  }
453
519
  }
454
520
  exports.Operation = Operation;
455
- function addDirectiveNodesToElement(directiveNodes, element) {
456
- if (!directiveNodes) {
457
- return;
458
- }
459
- const schema = element.schema();
460
- for (const node of directiveNodes) {
461
- const directiveDef = schema.directive(node.name.value);
462
- validate(directiveDef, () => `Unknown directive "@${node.name.value}" in selection`);
463
- element.applyDirective(directiveDef, (0, values_1.argumentsFromAST)(directiveDef.coordinate, node.arguments, directiveDef));
464
- }
465
- }
466
- function selectionSetOf(parentType, selection) {
467
- const selectionSet = new SelectionSet(parentType);
468
- selectionSet.add(selection);
469
- return selectionSet;
470
- }
471
- exports.selectionSetOf = selectionSetOf;
472
521
  class NamedFragmentDefinition extends definitions_1.DirectiveTargetElement {
473
- constructor(schema, name, typeCondition, selectionSet) {
474
- super(schema);
522
+ constructor(schema, name, typeCondition, directives) {
523
+ super(schema, directives);
475
524
  this.name = name;
476
525
  this.typeCondition = typeCondition;
477
- this.selectionSet = selectionSet;
478
526
  }
479
- withUpdatedSelectionSet(newSelectionSet) {
480
- return new NamedFragmentDefinition(this.schema(), this.name, this.typeCondition, newSelectionSet);
527
+ setSelectionSet(selectionSet) {
528
+ (0, utils_1.assert)(!this._selectionSet, 'Attempting to set the selection set of a fragment definition already built');
529
+ this._selectionSet = selectionSet;
530
+ return this;
531
+ }
532
+ get selectionSet() {
533
+ (0, utils_1.assert)(this._selectionSet, () => `Trying to access fragment definition ${this.name} before it is fully built`);
534
+ return this._selectionSet;
481
535
  }
482
- variables() {
483
- return (0, definitions_1.mergeVariables)(this.variablesInAppliedDirectives(), this.selectionSet.usedVariables());
536
+ withUpdatedSelectionSet(newSelectionSet) {
537
+ return new NamedFragmentDefinition(this.schema(), this.name, this.typeCondition).setSelectionSet(newSelectionSet);
484
538
  }
485
539
  collectUsedFragmentNames(collector) {
486
540
  this.selectionSet.collectUsedFragmentNames(collector);
@@ -517,8 +571,7 @@ class NamedFragmentDefinition extends definitions_1.DirectiveTargetElement {
517
571
  return false;
518
572
  }
519
573
  try {
520
- const rebasedSelection = new SelectionSet(typeInSchema);
521
- rebasedSelection.mergeIn(this.selectionSet);
574
+ this.selectionSet.rebaseOn(typeInSchema);
522
575
  return true;
523
576
  }
524
577
  catch (e) {
@@ -537,13 +590,6 @@ class NamedFragments {
537
590
  isEmpty() {
538
591
  return this.fragments.size === 0;
539
592
  }
540
- variables() {
541
- let variables = [];
542
- for (const fragment of this.fragments.values()) {
543
- variables = (0, definitions_1.mergeVariables)(variables, fragment.variables());
544
- }
545
- return variables;
546
- }
547
593
  names() {
548
594
  return this.fragments.keys();
549
595
  }
@@ -568,14 +614,14 @@ class NamedFragments {
568
614
  const newFragments = new NamedFragments();
569
615
  for (const fragment of this.fragments.values()) {
570
616
  if (!names.includes(fragment.name)) {
571
- const updatedSelection = fragment.selectionSet.expandFragments(names, false);
572
- const newFragment = updatedSelection === fragment.selectionSet
617
+ const updatedSelectionSet = fragment.selectionSet.expandFragments(names, newFragments);
618
+ const newFragment = updatedSelectionSet === fragment.selectionSet
573
619
  ? fragment
574
- : new NamedFragmentDefinition(fragment.schema(), fragment.name, fragment.typeCondition, updatedSelection);
620
+ : fragment.withUpdatedSelectionSet(updatedSelectionSet);
575
621
  newFragments.add(newFragment);
576
622
  }
577
623
  }
578
- return newFragments;
624
+ return newFragments.isEmpty() ? undefined : newFragments;
579
625
  }
580
626
  get(name) {
581
627
  return this.fragments.get(name);
@@ -586,9 +632,16 @@ class NamedFragments {
586
632
  definitions() {
587
633
  return this.fragments.values();
588
634
  }
589
- validate() {
635
+ map(mapper) {
636
+ const mapped = new NamedFragments();
637
+ for (const def of this.fragments.values()) {
638
+ mapped.fragments.set(def.name, mapper(def));
639
+ }
640
+ return mapped;
641
+ }
642
+ validate(variableDefinitions) {
590
643
  for (const fragment of this.fragments.values()) {
591
- fragment.selectionSet.validate();
644
+ fragment.selectionSet.validate(variableDefinitions);
592
645
  }
593
646
  }
594
647
  toFragmentDefinitionNodes() {
@@ -599,24 +652,6 @@ class NamedFragments {
599
652
  }
600
653
  }
601
654
  exports.NamedFragments = NamedFragments;
602
- class Freezable {
603
- constructor() {
604
- this._isFrozen = false;
605
- }
606
- freeze() {
607
- if (!this.isFrozen()) {
608
- this.freezeInternals();
609
- this._isFrozen = true;
610
- }
611
- return this.us();
612
- }
613
- isFrozen() {
614
- return this._isFrozen;
615
- }
616
- cloneIfFrozen() {
617
- return this.isFrozen() ? this.clone() : this.us();
618
- }
619
- }
620
655
  class DeferNormalizer {
621
656
  constructor() {
622
657
  this.index = 0;
@@ -631,7 +666,7 @@ class DeferNormalizer {
631
666
  while (stack.length > 0) {
632
667
  const selection = stack.pop();
633
668
  if (selection.kind === 'FragmentSelection') {
634
- const deferArgs = selection.element().deferDirectiveArgs();
669
+ const deferArgs = selection.element.deferDirectiveArgs();
635
670
  if (deferArgs) {
636
671
  hasDefers = true;
637
672
  if (!deferArgs.label || deferArgs.if !== undefined) {
@@ -663,132 +698,103 @@ class DeferNormalizer {
663
698
  this.deferConditions.add(condition.name, label);
664
699
  }
665
700
  }
666
- class SelectionSet extends Freezable {
667
- constructor(parentType, fragments) {
668
- super();
701
+ class SelectionSet {
702
+ constructor(parentType, keyedSelections = new Map(), fragments) {
669
703
  this.parentType = parentType;
670
704
  this.fragments = fragments;
671
- this._selections = new utils_1.MultiMap();
672
- this._selectionCount = 0;
673
- validate(!(0, definitions_1.isLeafType)(parentType), () => `Cannot have selection on non-leaf type ${parentType}`);
674
- }
675
- us() {
676
- return this;
705
+ this._keyedSelections = keyedSelections;
706
+ this._selections = (0, utils_1.mapValues)(keyedSelections);
677
707
  }
678
- selections(reversedOrder = false) {
679
- if (!this._cachedSelections) {
680
- const selections = new Array(this._selectionCount);
681
- let idx = 0;
682
- for (const byResponseName of this._selections.values()) {
683
- for (const selection of byResponseName) {
684
- selections[idx++] = selection;
685
- }
686
- }
687
- this._cachedSelections = selections;
708
+ selectionsInReverseOrder() {
709
+ const length = this._selections.length;
710
+ const reversed = new Array(length);
711
+ for (let i = 0; i < length; i++) {
712
+ reversed[i] = this._selections[length - i - 1];
688
713
  }
689
- (0, utils_1.assert)(this._cachedSelections, 'Cache should have been populated');
690
- if (reversedOrder && this._cachedSelections.length > 1) {
691
- const reversed = new Array(this._selectionCount);
692
- for (let i = 0; i < this._selectionCount; i++) {
693
- reversed[i] = this._cachedSelections[this._selectionCount - i - 1];
694
- }
695
- return reversed;
696
- }
697
- return this._cachedSelections;
714
+ return reversed;
715
+ }
716
+ selections() {
717
+ return this._selections;
718
+ }
719
+ hasTopLevelTypenameField() {
720
+ return this._keyedSelections.has(definitions_1.typenameFieldName);
698
721
  }
699
722
  fieldsInSet() {
700
723
  const fields = new Array();
701
724
  for (const selection of this.selections()) {
702
725
  if (selection.kind === 'FieldSelection') {
703
- fields.push({ path: [], field: selection, directParent: this });
726
+ fields.push({ path: [], field: selection });
704
727
  }
705
728
  else {
706
- const condition = selection.element().typeCondition;
729
+ const condition = selection.element.typeCondition;
707
730
  const header = condition ? [`... on ${condition}`] : [];
708
- for (const { path, field, directParent } of selection.selectionSet.fieldsInSet()) {
709
- fields.push({ path: header.concat(path), field, directParent });
731
+ for (const { path, field } of selection.selectionSet.fieldsInSet()) {
732
+ fields.push({ path: header.concat(path), field });
710
733
  }
711
734
  }
712
735
  }
713
736
  return fields;
714
737
  }
715
738
  usedVariables() {
716
- let variables = [];
717
- for (const byResponseName of this._selections.values()) {
718
- for (const selection of byResponseName) {
719
- variables = (0, definitions_1.mergeVariables)(variables, selection.usedVariables());
720
- }
721
- }
722
- if (this.fragments) {
723
- variables = (0, definitions_1.mergeVariables)(variables, this.fragments.variables());
739
+ const collector = new definitions_1.VariableCollector();
740
+ this.collectVariables(collector);
741
+ return collector.variables();
742
+ }
743
+ collectVariables(collector) {
744
+ for (const selection of this.selections()) {
745
+ selection.collectVariables(collector);
724
746
  }
725
- return variables;
726
747
  }
727
748
  collectUsedFragmentNames(collector) {
728
- for (const byResponseName of this._selections.values()) {
729
- for (const selection of byResponseName) {
730
- selection.collectUsedFragmentNames(collector);
731
- }
749
+ for (const selection of this.selections()) {
750
+ selection.collectUsedFragmentNames(collector);
732
751
  }
733
752
  }
734
753
  optimize(fragments) {
735
754
  if (!fragments || fragments.isEmpty()) {
736
755
  return this;
737
756
  }
738
- if (this.fragments && this.fragments.definitions().some(def => fragments.get(def.name))) {
739
- return this;
740
- }
741
- const optimized = new SelectionSet(this.parentType, fragments);
742
- for (const selection of this.selections()) {
743
- optimized.add(selection.optimize(fragments));
744
- }
745
- return optimized;
757
+ (0, utils_1.assert)(!this.fragments || this.fragments.isEmpty(), `Should not be called on selection that already has named fragments, but got ${this.fragments}`);
758
+ return this.lazyMap((selection) => selection.optimize(fragments), { fragments });
746
759
  }
747
- expandFragments(names, updateSelectionSetFragments = true) {
748
- var _a;
749
- if (names && names.length === 0) {
760
+ expandAllFragments() {
761
+ return this.lazyMap((selection) => selection.expandAllFragments(), { fragments: null });
762
+ }
763
+ expandFragments(names, updatedFragments) {
764
+ if (names.length === 0) {
750
765
  return this;
751
766
  }
752
- const newFragments = updateSelectionSetFragments
753
- ? (names ? (_a = this.fragments) === null || _a === void 0 ? void 0 : _a.without(names) : undefined)
754
- : this.fragments;
755
- const withExpanded = new SelectionSet(this.parentType, newFragments);
756
- for (const selection of this.selections()) {
757
- const expanded = selection.expandFragments(names, updateSelectionSetFragments);
758
- if (Array.isArray(expanded)) {
759
- withExpanded.addAll(expanded);
760
- }
761
- else {
762
- withExpanded.add(expanded);
763
- }
764
- }
765
- return withExpanded;
767
+ return this.lazyMap((selection) => selection.expandFragments(names, updatedFragments), { fragments: updatedFragments !== null && updatedFragments !== void 0 ? updatedFragments : null });
766
768
  }
767
- lazyMap(mapper) {
768
- let updatedSelections = undefined;
769
+ trimUnsatisfiableBranches(parentType) {
770
+ return this.lazyMap((selection) => selection.trimUnsatisfiableBranches(parentType), { parentType });
771
+ }
772
+ lazyMap(mapper, options) {
773
+ var _a;
769
774
  const selections = this.selections();
775
+ const updatedFragments = options === null || options === void 0 ? void 0 : options.fragments;
776
+ const newFragments = updatedFragments === undefined ? this.fragments : (updatedFragments !== null && updatedFragments !== void 0 ? updatedFragments : undefined);
777
+ let updatedSelections = undefined;
770
778
  for (let i = 0; i < selections.length; i++) {
771
779
  const selection = selections[i];
772
780
  const updated = mapper(selection);
773
781
  if (updated !== selection && !updatedSelections) {
774
- updatedSelections = [];
782
+ updatedSelections = new SelectionSetUpdates();
775
783
  for (let j = 0; j < i; j++) {
776
- updatedSelections.push(selections[j]);
784
+ updatedSelections.add(selections[j]);
777
785
  }
778
786
  }
779
787
  if (!!updated && updatedSelections) {
780
- if (updated instanceof SelectionSet) {
781
- updated.selections().forEach((s) => updatedSelections.push(s));
782
- }
783
- else {
784
- updatedSelections.push(updated);
785
- }
788
+ updatedSelections.add(updated);
786
789
  }
787
790
  }
788
791
  if (!updatedSelections) {
789
- return this;
792
+ return this.withUpdatedFragments(newFragments);
790
793
  }
791
- return new SelectionSet(this.parentType, this.fragments).addAll(updatedSelections);
794
+ return updatedSelections.toSelectionSet((_a = options === null || options === void 0 ? void 0 : options.parentType) !== null && _a !== void 0 ? _a : this.parentType, newFragments);
795
+ }
796
+ withUpdatedFragments(newFragments) {
797
+ return this.fragments === newFragments ? this : new SelectionSet(this.parentType, this._keyedSelections, newFragments);
792
798
  }
793
799
  withoutDefer(labelsToRemove) {
794
800
  (0, utils_1.assert)(!this.fragments, 'Not yet supported');
@@ -798,6 +804,9 @@ class SelectionSet extends Freezable {
798
804
  (0, utils_1.assert)(!this.fragments, 'Not yet supported');
799
805
  return this.lazyMap((selection) => selection.withNormalizedDefer(normalizer));
800
806
  }
807
+ hasDefer() {
808
+ return this.selections().some((s) => s.hasDefer());
809
+ }
801
810
  filter(predicate) {
802
811
  return this.lazyMap((selection) => selection.filter(predicate));
803
812
  }
@@ -805,169 +814,72 @@ class SelectionSet extends Freezable {
805
814
  const updated = this.filter((selection) => { var _a; return ((_a = selection.selectionSet) === null || _a === void 0 ? void 0 : _a.isEmpty()) !== true; });
806
815
  return updated.isEmpty() ? undefined : updated;
807
816
  }
808
- freezeInternals() {
809
- for (const selection of this.selections()) {
810
- selection.freeze();
811
- }
812
- }
813
- mergeIn(selectionSet) {
814
- for (const selection of selectionSet.selections()) {
815
- this.add(selection);
816
- }
817
- }
818
- addAll(selections) {
819
- selections.forEach(s => this.add(s));
820
- return this;
821
- }
822
- add(selection) {
823
- (0, utils_1.assert)(!this.isFrozen(), () => `Cannot add to frozen selection: ${this}`);
824
- const toAdd = selection.updateForAddingTo(this);
825
- const key = toAdd.key();
826
- const existing = this._selections.get(key);
827
- if (existing) {
828
- for (const existingSelection of existing) {
829
- if (existingSelection.kind === toAdd.kind && haveSameDirectives(existingSelection.element(), toAdd.element())) {
830
- if (toAdd.selectionSet) {
831
- existingSelection.selectionSet.mergeIn(toAdd.selectionSet);
832
- }
833
- return existingSelection;
834
- }
835
- }
836
- }
837
- this._selections.add(key, toAdd);
838
- ++this._selectionCount;
839
- this._cachedSelections = undefined;
840
- return toAdd;
841
- }
842
- removeTopLevelField(responseName) {
843
- (0, utils_1.assert)(!this.isFrozen(), () => `Cannot remove from frozen selection: ${this}`);
844
- const wasRemoved = this._selections.delete(responseName);
845
- if (wasRemoved) {
846
- --this._selectionCount;
847
- this._cachedSelections = undefined;
848
- }
849
- return wasRemoved;
850
- }
851
- addPath(path, onPathEnd) {
852
- let previousSelections = this;
853
- let currentSelections = this;
854
- for (const element of path) {
855
- validate(currentSelections, () => `Cannot apply selection ${element} to non-selectable parent type "${previousSelections.parentType}"`);
856
- const mergedSelection = currentSelections.add(selectionOfElement(element));
857
- previousSelections = currentSelections;
858
- currentSelections = mergedSelection.selectionSet;
859
- }
860
- if (onPathEnd) {
861
- onPathEnd(currentSelections);
862
- }
863
- }
864
- addSelectionSetNode(node, variableDefinitions, fieldAccessor = (type, name) => type.field(name)) {
865
- if (!node) {
866
- return;
867
- }
868
- for (const selectionNode of node.selections) {
869
- this.addSelectionNode(selectionNode, variableDefinitions, fieldAccessor);
817
+ rebaseOn(parentType) {
818
+ if (this.parentType === parentType) {
819
+ return this;
870
820
  }
871
- }
872
- addSelectionNode(node, variableDefinitions, fieldAccessor = (type, name) => type.field(name)) {
873
- this.add(this.nodeToSelection(node, variableDefinitions, fieldAccessor));
874
- }
875
- nodeToSelection(node, variableDefinitions, fieldAccessor) {
876
- var _a, _b;
877
- let selection;
878
- switch (node.kind) {
879
- case graphql_1.Kind.FIELD:
880
- const definition = fieldAccessor(this.parentType, node.name.value);
881
- validate(definition, () => `Cannot query field "${node.name.value}" on type "${this.parentType}".`, this.parentType.sourceAST);
882
- const type = (0, definitions_1.baseType)(definition.type);
883
- selection = new FieldSelection(new Field(definition, (0, values_1.argumentsFromAST)(definition.coordinate, node.arguments, definition), variableDefinitions, (_a = node.alias) === null || _a === void 0 ? void 0 : _a.value), (0, definitions_1.isLeafType)(type) ? undefined : new SelectionSet(type, this.fragments));
884
- if (node.selectionSet) {
885
- validate(selection.selectionSet, () => `Unexpected selection set on leaf field "${selection.element()}"`, selection.element().definition.sourceAST);
886
- selection.selectionSet.addSelectionSetNode(node.selectionSet, variableDefinitions, fieldAccessor);
887
- }
888
- break;
889
- case graphql_1.Kind.INLINE_FRAGMENT:
890
- const element = new FragmentElement(this.parentType, (_b = node.typeCondition) === null || _b === void 0 ? void 0 : _b.name.value);
891
- selection = new InlineFragmentSelection(element, new SelectionSet(element.typeCondition ? element.typeCondition : element.parentType, this.fragments));
892
- selection.selectionSet.addSelectionSetNode(node.selectionSet, variableDefinitions, fieldAccessor);
893
- break;
894
- case graphql_1.Kind.FRAGMENT_SPREAD:
895
- const fragmentName = node.name.value;
896
- validate(this.fragments, () => `Cannot find fragment name "${fragmentName}" (no fragments were provided)`);
897
- selection = new FragmentSpreadSelection(this.parentType, this.fragments, fragmentName);
898
- break;
821
+ const newSelections = new Map();
822
+ for (const selection of this.selections()) {
823
+ newSelections.set(selection.key(), selection.rebaseOn(parentType));
899
824
  }
900
- addDirectiveNodesToElement(node.directives, selection.element());
901
- return selection;
825
+ return new SelectionSet(parentType, newSelections, this.fragments);
902
826
  }
903
827
  equals(that) {
904
828
  if (this === that) {
905
829
  return true;
906
830
  }
907
- if (this._selections.size !== that._selections.size) {
831
+ if (this._selections.length !== that._selections.length) {
908
832
  return false;
909
833
  }
910
- for (const [key, thisSelections] of this._selections) {
911
- const thatSelections = that._selections.get(key);
912
- if (!thatSelections
913
- || thisSelections.length !== thatSelections.length
914
- || !thisSelections.every(thisSelection => thatSelections.some(thatSelection => thisSelection.equals(thatSelection)))) {
834
+ for (const [key, thisSelection] of this._keyedSelections) {
835
+ const thatSelection = that._keyedSelections.get(key);
836
+ if (!thatSelection || !thisSelection.equals(thatSelection)) {
915
837
  return false;
916
838
  }
917
839
  }
918
840
  return true;
919
841
  }
920
842
  contains(that) {
921
- if (this._selections.size < that._selections.size) {
843
+ if (this._selections.length < that._selections.length) {
922
844
  return false;
923
845
  }
924
- for (const [key, thatSelections] of that._selections) {
925
- const thisSelections = this._selections.get(key);
926
- if (!thisSelections
927
- || (thisSelections.length < thatSelections.length
928
- || !thatSelections.every(thatSelection => thisSelections.some(thisSelection => thisSelection.contains(thatSelection))))) {
846
+ for (const [key, thatSelection] of that._keyedSelections) {
847
+ const thisSelection = this._keyedSelections.get(key);
848
+ if (!thisSelection || !thisSelection.contains(thatSelection)) {
929
849
  return false;
930
850
  }
931
851
  }
932
852
  return true;
933
853
  }
934
854
  minus(that) {
935
- const updated = new SelectionSet(this.parentType, this.fragments);
936
- for (const [key, thisSelections] of this._selections) {
937
- const thatSelections = that._selections.get(key);
938
- if (!thatSelections) {
939
- updated._selections.set(key, thisSelections);
855
+ const updated = new SelectionSetUpdates();
856
+ for (const [key, thisSelection] of this._keyedSelections) {
857
+ const thatSelection = that._keyedSelections.get(key);
858
+ if (!thatSelection) {
859
+ updated.add(thisSelection);
940
860
  }
941
861
  else {
942
- for (const thisSelection of thisSelections) {
943
- const thatSelection = thatSelections.find((s) => thisSelection.element().equals(s.element()));
944
- if (thatSelection) {
945
- if (thisSelection.selectionSet && thatSelection.selectionSet) {
946
- const updatedSubSelectionSet = thisSelection.selectionSet.minus(thatSelection.selectionSet);
947
- if (!updatedSubSelectionSet.isEmpty()) {
948
- updated._selections.add(key, thisSelection.withUpdatedSubSelection(updatedSubSelectionSet));
949
- }
950
- }
951
- }
952
- else {
953
- updated._selections.add(key, thisSelection);
862
+ if (thisSelection.selectionSet && thatSelection.selectionSet) {
863
+ const updatedSubSelectionSet = thisSelection.selectionSet.minus(thatSelection.selectionSet);
864
+ if (!updatedSubSelectionSet.isEmpty()) {
865
+ updated.add(thisSelection.withUpdatedSelectionSet(updatedSubSelectionSet));
954
866
  }
955
867
  }
956
868
  }
957
869
  }
958
- return updated;
870
+ return updated.toSelectionSet(this.parentType, this.fragments);
959
871
  }
960
872
  canRebaseOn(parentTypeToTest) {
961
873
  return this.selections().every((selection) => selection.canAddTo(parentTypeToTest));
962
874
  }
963
- validate() {
875
+ validate(variableDefinitions) {
964
876
  validate(!this.isEmpty(), () => `Invalid empty selection set`);
965
877
  for (const selection of this.selections()) {
966
- selection.validate();
878
+ selection.validate(variableDefinitions);
967
879
  }
968
880
  }
969
881
  isEmpty() {
970
- return this._selections.size === 0;
882
+ return this._selections.length === 0;
971
883
  }
972
884
  toSelectionSetNode() {
973
885
  if (this.isEmpty()) {
@@ -988,13 +900,13 @@ class SelectionSet extends Freezable {
988
900
  };
989
901
  }
990
902
  selectionsInPrintOrder() {
991
- const typenameSelection = this._selections.get(definitions_1.typenameFieldName);
992
- const isNonAliasedTypenameSelection = (s) => s.kind === 'FieldSelection' && !s.field.alias && s.field.name === definitions_1.typenameFieldName;
903
+ const isNonAliasedTypenameSelection = (s) => s.kind === 'FieldSelection' && !s.element.alias && s.element.name === definitions_1.typenameFieldName;
904
+ const typenameSelection = this._selections.find((s) => isNonAliasedTypenameSelection(s));
993
905
  if (typenameSelection) {
994
- return typenameSelection.concat(this.selections().filter(s => !isNonAliasedTypenameSelection(s)));
906
+ return [typenameSelection].concat(this.selections().filter(s => !isNonAliasedTypenameSelection(s)));
995
907
  }
996
908
  else {
997
- return this.selections();
909
+ return this._selections;
998
910
  }
999
911
  }
1000
912
  toOperationPaths() {
@@ -1002,7 +914,7 @@ class SelectionSet extends Freezable {
1002
914
  }
1003
915
  toOperationPathsInternal(parentPaths) {
1004
916
  return this.selections().flatMap((selection) => {
1005
- const updatedPaths = parentPaths.map(path => path.concat(selection.element()));
917
+ const updatedPaths = parentPaths.map(path => path.concat(selection.element));
1006
918
  return selection.selectionSet
1007
919
  ? selection.selectionSet.toOperationPathsInternal(updatedPaths)
1008
920
  : updatedPaths;
@@ -1010,21 +922,20 @@ class SelectionSet extends Freezable {
1010
922
  }
1011
923
  forEachElement(callback) {
1012
924
  var _a;
1013
- const stack = this.selections().concat();
925
+ const stack = this.selectionsInReverseOrder().concat();
1014
926
  while (stack.length > 0) {
1015
927
  const selection = stack.pop();
1016
- callback(selection.element());
1017
- (_a = selection.selectionSet) === null || _a === void 0 ? void 0 : _a.selections(true).forEach((s) => stack.push(s));
928
+ callback(selection.element);
929
+ (_a = selection.selectionSet) === null || _a === void 0 ? void 0 : _a.selectionsInReverseOrder().forEach((s) => stack.push(s));
1018
930
  }
1019
931
  }
1020
- clone() {
1021
- const cloned = new SelectionSet(this.parentType);
932
+ some(predicate) {
1022
933
  for (const selection of this.selections()) {
1023
- const clonedSelection = selection.clone();
1024
- cloned._selections.add(clonedSelection.key(), clonedSelection);
1025
- ++cloned._selectionCount;
934
+ if (predicate(selection.element) || (selection.selectionSet && selection.selectionSet.some(predicate))) {
935
+ return true;
936
+ }
1026
937
  }
1027
- return cloned;
938
+ return false;
1028
939
  }
1029
940
  toOperationString(rootKind, variableDefinitions, operationName, expandFragments = false, prettyPrint = true) {
1030
941
  const indent = prettyPrint ? '' : undefined;
@@ -1040,6 +951,9 @@ class SelectionSet extends Freezable {
1040
951
  return fragmentsDefinitions + rootKind + nameAndVariables + " " + this.toString(expandFragments, true, indent);
1041
952
  }
1042
953
  toString(expandFragments = true, includeExternalBrackets = true, indent) {
954
+ if (this.isEmpty()) {
955
+ return '{}';
956
+ }
1043
957
  if (indent === undefined) {
1044
958
  const selectionsToString = this.selections().map(s => s.toString(expandFragments)).join(' ');
1045
959
  return includeExternalBrackets ? '{ ' + selectionsToString + ' }' : selectionsToString;
@@ -1054,13 +968,212 @@ class SelectionSet extends Freezable {
1054
968
  }
1055
969
  }
1056
970
  exports.SelectionSet = SelectionSet;
971
+ class SelectionSetUpdates {
972
+ constructor() {
973
+ this.keyedUpdates = new utils_1.MultiMap;
974
+ }
975
+ isEmpty() {
976
+ return this.keyedUpdates.size === 0;
977
+ }
978
+ add(selections) {
979
+ addToKeyedUpdates(this.keyedUpdates, selections);
980
+ return this;
981
+ }
982
+ addAtPath(path, selections) {
983
+ if (path.length === 0) {
984
+ if (selections) {
985
+ addToKeyedUpdates(this.keyedUpdates, selections);
986
+ }
987
+ }
988
+ else {
989
+ if (path.length === 1 && !selections) {
990
+ const element = path[0];
991
+ if (element.kind === 'Field' && element.isLeafField()) {
992
+ const selection = selectionOfElement(element);
993
+ this.keyedUpdates.add(selection.key(), selection);
994
+ return this;
995
+ }
996
+ }
997
+ this.keyedUpdates.add(path[0].key(), { path, selections });
998
+ }
999
+ return this;
1000
+ }
1001
+ clone() {
1002
+ const cloned = new SelectionSetUpdates();
1003
+ for (const [key, values] of this.keyedUpdates.entries()) {
1004
+ cloned.keyedUpdates.set(key, Array.from(values));
1005
+ }
1006
+ return cloned;
1007
+ }
1008
+ clear() {
1009
+ this.keyedUpdates.clear();
1010
+ }
1011
+ toSelectionSet(parentType, fragments) {
1012
+ return makeSelectionSet(parentType, this.keyedUpdates, fragments);
1013
+ }
1014
+ }
1015
+ exports.SelectionSetUpdates = SelectionSetUpdates;
1016
+ function addToKeyedUpdates(keyedUpdates, selections) {
1017
+ if (selections instanceof AbstractSelection) {
1018
+ addOneToKeyedUpdates(keyedUpdates, selections);
1019
+ }
1020
+ else {
1021
+ const toAdd = selections instanceof SelectionSet ? selections.selections() : selections;
1022
+ for (const selection of toAdd) {
1023
+ addOneToKeyedUpdates(keyedUpdates, selection);
1024
+ }
1025
+ }
1026
+ }
1027
+ function addOneToKeyedUpdates(keyedUpdates, selection) {
1028
+ if (selection instanceof FragmentSpreadSelection) {
1029
+ keyedUpdates.set(selection.key(), [selection]);
1030
+ }
1031
+ else {
1032
+ keyedUpdates.add(selection.key(), selection);
1033
+ }
1034
+ }
1035
+ function isUnecessaryFragment(parentType, fragment) {
1036
+ return fragment.element.appliedDirectives.length === 0
1037
+ && (!fragment.element.typeCondition || (0, types_1.sameType)(parentType, fragment.element.typeCondition));
1038
+ }
1039
+ function withUnecessaryFragmentsRemoved(parentType, selections) {
1040
+ if (selections instanceof AbstractSelection) {
1041
+ if (selections.kind !== 'FragmentSelection' || !isUnecessaryFragment(parentType, selections)) {
1042
+ return selections;
1043
+ }
1044
+ return withUnecessaryFragmentsRemoved(parentType, selections.selectionSet);
1045
+ }
1046
+ const toCheck = selections instanceof SelectionSet ? selections.selections() : selections;
1047
+ const filtered = [];
1048
+ for (const selection of toCheck) {
1049
+ if (selection.kind === 'FragmentSelection' && isUnecessaryFragment(parentType, selection)) {
1050
+ const subSelections = withUnecessaryFragmentsRemoved(parentType, selection.selectionSet);
1051
+ if (subSelections instanceof AbstractSelection) {
1052
+ filtered.push(subSelections);
1053
+ }
1054
+ else {
1055
+ for (const subSelection of subSelections) {
1056
+ filtered.push(subSelection);
1057
+ }
1058
+ }
1059
+ }
1060
+ else {
1061
+ filtered.push(selection);
1062
+ }
1063
+ }
1064
+ return filtered;
1065
+ }
1066
+ function makeSelection(parentType, updates, fragments) {
1067
+ (0, utils_1.assert)(updates.length > 0, 'Should not be called without any updates');
1068
+ const first = updates[0];
1069
+ if (updates.length === 1 && first instanceof AbstractSelection) {
1070
+ return first.rebaseOn(parentType);
1071
+ }
1072
+ const element = updateElement(first).rebaseOn(parentType);
1073
+ const subSelectionParentType = element.kind === 'Field' ? (0, definitions_1.baseType)(element.definition.type) : element.castedType();
1074
+ if (!(0, definitions_1.isCompositeType)(subSelectionParentType)) {
1075
+ return selectionOfElement(element);
1076
+ }
1077
+ const subSelectionKeyedUpdates = new utils_1.MultiMap();
1078
+ for (const update of updates) {
1079
+ if (update instanceof AbstractSelection) {
1080
+ if (update.selectionSet) {
1081
+ addToKeyedUpdates(subSelectionKeyedUpdates, update.selectionSet);
1082
+ }
1083
+ }
1084
+ else {
1085
+ addSubpathToKeyUpdates(subSelectionKeyedUpdates, subSelectionParentType, update);
1086
+ }
1087
+ }
1088
+ return selectionOfElement(element, makeSelectionSet(subSelectionParentType, subSelectionKeyedUpdates, fragments));
1089
+ }
1090
+ function updateElement(update) {
1091
+ return update instanceof AbstractSelection ? update.element : update.path[0];
1092
+ }
1093
+ function addSubpathToKeyUpdates(keyedUpdates, subSelectionParentType, pathUpdate) {
1094
+ if (pathUpdate.path.length === 1) {
1095
+ if (!pathUpdate.selections) {
1096
+ return;
1097
+ }
1098
+ addToKeyedUpdates(keyedUpdates, withUnecessaryFragmentsRemoved(subSelectionParentType, pathUpdate.selections));
1099
+ }
1100
+ else {
1101
+ keyedUpdates.add(pathUpdate.path[1].key(), { path: pathUpdate.path.slice(1), selections: pathUpdate.selections });
1102
+ }
1103
+ }
1104
+ function makeSelectionSet(parentType, keyedUpdates, fragments) {
1105
+ const selections = new Map();
1106
+ for (const [key, updates] of keyedUpdates.entries()) {
1107
+ selections.set(key, makeSelection(parentType, updates, fragments));
1108
+ }
1109
+ return new SelectionSet(parentType, selections, fragments);
1110
+ }
1111
+ class MutableSelectionSet {
1112
+ constructor(parentType, _updates, memoizer) {
1113
+ this.parentType = parentType;
1114
+ this._updates = _updates;
1115
+ this.memoizer = memoizer;
1116
+ }
1117
+ static empty(parentType) {
1118
+ return this.emptyWithMemoized(parentType, () => ({}));
1119
+ }
1120
+ static emptyWithMemoized(parentType, memoizer) {
1121
+ return new MutableSelectionSet(parentType, new SelectionSetUpdates(), memoizer);
1122
+ }
1123
+ static of(selectionSet) {
1124
+ return this.ofWithMemoized(selectionSet, () => ({}));
1125
+ }
1126
+ static ofWithMemoized(selectionSet, memoizer) {
1127
+ const s = new MutableSelectionSet(selectionSet.parentType, new SelectionSetUpdates(), memoizer);
1128
+ s._updates.add(selectionSet);
1129
+ s.computed = selectionSet;
1130
+ return s;
1131
+ }
1132
+ isEmpty() {
1133
+ return this._updates.isEmpty();
1134
+ }
1135
+ get() {
1136
+ if (!this.computed) {
1137
+ this.computed = this._updates.toSelectionSet(this.parentType);
1138
+ this._updates.clear();
1139
+ this._updates.add(this.computed);
1140
+ }
1141
+ return this.computed;
1142
+ }
1143
+ updates() {
1144
+ this.computed = undefined;
1145
+ this._memoized = undefined;
1146
+ return this._updates;
1147
+ }
1148
+ clone() {
1149
+ const cloned = new MutableSelectionSet(this.parentType, this._updates.clone(), this.memoizer);
1150
+ cloned.computed = this.computed;
1151
+ cloned._memoized = this._memoized;
1152
+ return cloned;
1153
+ }
1154
+ rebaseOn(parentType) {
1155
+ const rebased = new MutableSelectionSet(parentType, new SelectionSetUpdates(), this.memoizer);
1156
+ rebased._updates.add(this.get());
1157
+ return rebased;
1158
+ }
1159
+ memoized() {
1160
+ if (!this._memoized) {
1161
+ this._memoized = this.memoizer(this.get());
1162
+ }
1163
+ return this._memoized;
1164
+ }
1165
+ toString() {
1166
+ return this.get().toString();
1167
+ }
1168
+ }
1169
+ exports.MutableSelectionSet = MutableSelectionSet;
1057
1170
  function allFieldDefinitionsInSelectionSet(selection) {
1058
1171
  const stack = Array.from(selection.selections());
1059
1172
  const allFields = [];
1060
1173
  while (stack.length > 0) {
1061
1174
  const selection = stack.pop();
1062
1175
  if (selection.kind === 'FieldSelection') {
1063
- allFields.push(selection.field.definition);
1176
+ allFields.push(selection.element.definition);
1064
1177
  }
1065
1178
  if (selection.selectionSet) {
1066
1179
  stack.push(...selection.selectionSet.selections());
@@ -1069,59 +1182,88 @@ function allFieldDefinitionsInSelectionSet(selection) {
1069
1182
  return allFields;
1070
1183
  }
1071
1184
  exports.allFieldDefinitionsInSelectionSet = allFieldDefinitionsInSelectionSet;
1072
- function selectionSetOfElement(element, subSelection) {
1073
- const selectionSet = new SelectionSet(element.parentType);
1074
- selectionSet.add(selectionOfElement(element, subSelection));
1075
- return selectionSet;
1185
+ function selectionSetOf(parentType, selection, fragments) {
1186
+ const map = new Map();
1187
+ map.set(selection.key(), selection);
1188
+ return new SelectionSet(parentType, map, fragments);
1189
+ }
1190
+ exports.selectionSetOf = selectionSetOf;
1191
+ function selectionSetOfElement(element, subSelection, fragments) {
1192
+ return selectionSetOf(element.parentType, selectionOfElement(element, subSelection), fragments);
1076
1193
  }
1077
1194
  exports.selectionSetOfElement = selectionSetOfElement;
1078
1195
  function selectionOfElement(element, subSelection) {
1079
1196
  return element.kind === 'Field' ? new FieldSelection(element, subSelection) : new InlineFragmentSelection(element, subSelection);
1080
1197
  }
1081
1198
  exports.selectionOfElement = selectionOfElement;
1082
- class FieldSelection extends Freezable {
1083
- constructor(field, initialSelectionSet) {
1084
- super();
1085
- this.field = field;
1086
- this.kind = 'FieldSelection';
1087
- const type = (0, definitions_1.baseType)(field.definition.type);
1088
- this.selectionSet = (0, definitions_1.isLeafType)(type) ? undefined : (initialSelectionSet ? initialSelectionSet.cloneIfFrozen() : new SelectionSet(type));
1199
+ class AbstractSelection {
1200
+ constructor(element) {
1201
+ this.element = element;
1089
1202
  }
1090
1203
  get parentType() {
1091
- return this.field.parentType;
1204
+ return this.element.parentType;
1092
1205
  }
1093
- us() {
1094
- return this;
1206
+ collectVariables(collector) {
1207
+ var _a;
1208
+ this.element.collectVariables(collector);
1209
+ (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.collectVariables(collector);
1095
1210
  }
1096
- key() {
1097
- return this.element().responseName();
1211
+ collectUsedFragmentNames(collector) {
1212
+ var _a;
1213
+ (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.collectUsedFragmentNames(collector);
1098
1214
  }
1099
- element() {
1100
- return this.field;
1215
+ namedFragments() {
1216
+ var _a;
1217
+ return (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.fragments;
1101
1218
  }
1102
- usedVariables() {
1103
- var _a, _b;
1104
- return (0, definitions_1.mergeVariables)(this.element().variables(), (_b = (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.usedVariables()) !== null && _b !== void 0 ? _b : []);
1219
+ withUpdatedSelectionSet(selectionSet) {
1220
+ return this.withUpdatedComponents(this.element, selectionSet);
1105
1221
  }
1106
- collectUsedFragmentNames(collector) {
1107
- if (this.selectionSet) {
1108
- this.selectionSet.collectUsedFragmentNames(collector);
1222
+ withUpdatedElement(element) {
1223
+ return this.withUpdatedComponents(element, this.selectionSet);
1224
+ }
1225
+ mapToSelectionSet(mapper) {
1226
+ if (!this.selectionSet) {
1227
+ return this.us();
1109
1228
  }
1229
+ const updatedSelectionSet = mapper(this.selectionSet);
1230
+ return updatedSelectionSet === this.selectionSet
1231
+ ? this.us()
1232
+ : this.withUpdatedSelectionSet(updatedSelectionSet);
1233
+ }
1234
+ }
1235
+ class FieldSelection extends AbstractSelection {
1236
+ constructor(field, _selectionSet) {
1237
+ super(field);
1238
+ this._selectionSet = _selectionSet;
1239
+ this.kind = 'FieldSelection';
1240
+ }
1241
+ get selectionSet() {
1242
+ return this._selectionSet;
1243
+ }
1244
+ us() {
1245
+ return this;
1246
+ }
1247
+ withUpdatedComponents(field, selectionSet) {
1248
+ return new FieldSelection(field, selectionSet);
1249
+ }
1250
+ key() {
1251
+ return this.element.key();
1110
1252
  }
1111
1253
  optimize(fragments) {
1112
1254
  const optimizedSelection = this.selectionSet ? this.selectionSet.optimize(fragments) : undefined;
1113
- const fieldBaseType = (0, definitions_1.baseType)(this.field.definition.type);
1255
+ const fieldBaseType = (0, definitions_1.baseType)(this.element.definition.type);
1114
1256
  if ((0, definitions_1.isCompositeType)(fieldBaseType) && optimizedSelection) {
1115
1257
  for (const candidate of fragments.maybeApplyingAtType(fieldBaseType)) {
1116
1258
  if (optimizedSelection.equals(candidate.selectionSet)) {
1117
- const fragmentSelection = new FragmentSpreadSelection(fieldBaseType, fragments, candidate.name);
1118
- return new FieldSelection(this.field, selectionSetOf(fieldBaseType, fragmentSelection));
1259
+ const fragmentSelection = new FragmentSpreadSelection(fieldBaseType, fragments, candidate, []);
1260
+ return new FieldSelection(this.element, selectionSetOf(fieldBaseType, fragmentSelection));
1119
1261
  }
1120
1262
  }
1121
1263
  }
1122
1264
  return this.selectionSet === optimizedSelection
1123
1265
  ? this
1124
- : new FieldSelection(this.field, optimizedSelection);
1266
+ : new FieldSelection(this.element, optimizedSelection);
1125
1267
  }
1126
1268
  filter(predicate) {
1127
1269
  if (!this.selectionSet) {
@@ -1130,99 +1272,96 @@ class FieldSelection extends Freezable {
1130
1272
  const updatedSelectionSet = this.selectionSet.filter(predicate);
1131
1273
  const thisWithFilteredSelectionSet = this.selectionSet === updatedSelectionSet
1132
1274
  ? this
1133
- : new FieldSelection(this.field, updatedSelectionSet);
1275
+ : new FieldSelection(this.element, updatedSelectionSet);
1134
1276
  return predicate(thisWithFilteredSelectionSet) ? thisWithFilteredSelectionSet : undefined;
1135
1277
  }
1136
- freezeInternals() {
1278
+ validate(variableDefinitions) {
1137
1279
  var _a;
1138
- (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.freeze();
1139
- }
1140
- expandFragments(names, updateSelectionSetFragments = true) {
1141
- const expandedSelection = this.selectionSet ? this.selectionSet.expandFragments(names, updateSelectionSetFragments) : undefined;
1142
- return this.selectionSet === expandedSelection
1143
- ? this
1144
- : new FieldSelection(this.field, expandedSelection);
1280
+ this.element.validate(variableDefinitions);
1281
+ validate(this.element.isLeafField() || (this.selectionSet && !this.selectionSet.isEmpty()), () => `Invalid empty selection set for field "${this.element.definition.coordinate}" of non-leaf type ${this.element.definition.type}`, this.element.definition.sourceAST);
1282
+ (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.validate(variableDefinitions);
1145
1283
  }
1146
- fieldArgumentsToAST() {
1147
- const entries = Object.entries(this.field.args);
1148
- if (entries.length === 0) {
1149
- return undefined;
1284
+ rebaseOn(parentType) {
1285
+ if (this.element.parentType === parentType) {
1286
+ return this;
1150
1287
  }
1151
- return entries.map(([n, v]) => {
1152
- return {
1153
- kind: graphql_1.Kind.ARGUMENT,
1154
- name: { kind: graphql_1.Kind.NAME, value: n },
1155
- value: (0, values_1.valueToAST)(v, this.field.definition.argument(n).type),
1156
- };
1157
- });
1158
- }
1159
- validate() {
1160
- var _a;
1161
- this.field.validate();
1162
- validate(!(this.selectionSet && this.selectionSet.isEmpty()), () => `Invalid empty selection set for field "${this.field.definition.coordinate}" of non-leaf type ${this.field.definition.type}`, this.field.definition.sourceAST);
1163
- (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.validate();
1164
- }
1165
- updateForAddingTo(selectionSet) {
1166
- var _a;
1167
- const updatedField = this.field.updateForAddingTo(selectionSet);
1168
- if (this.field === updatedField) {
1169
- return this.cloneIfFrozen();
1170
- }
1171
- const updatedBaseType = (0, definitions_1.baseType)(updatedField.definition.type);
1172
- let updatedSelectionSet;
1173
- if (this.selectionSet && this.selectionSet.parentType !== updatedBaseType) {
1174
- (0, utils_1.assert)((0, definitions_1.isCompositeType)(updatedBaseType), `Expected ${updatedBaseType.coordinate} to be composite but ${updatedBaseType.kind}`);
1175
- updatedSelectionSet = new SelectionSet(updatedBaseType);
1176
- for (const selection of this.selectionSet.selections()) {
1177
- updatedSelectionSet.add(selection);
1178
- }
1288
+ const rebasedElement = this.element.rebaseOn(parentType);
1289
+ if (!this.selectionSet) {
1290
+ return this.withUpdatedElement(rebasedElement);
1179
1291
  }
1180
- else {
1181
- updatedSelectionSet = (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.cloneIfFrozen();
1292
+ const rebasedBase = (0, definitions_1.baseType)(rebasedElement.definition.type);
1293
+ if (rebasedBase === this.selectionSet.parentType) {
1294
+ return this.withUpdatedElement(rebasedElement);
1182
1295
  }
1183
- return new FieldSelection(updatedField, updatedSelectionSet);
1296
+ validate((0, definitions_1.isCompositeType)(rebasedBase), () => `Cannot rebase field selection ${this} on ${parentType}: rebased field base return type ${rebasedBase} is not composite`);
1297
+ return this.withUpdatedComponents(rebasedElement, this.selectionSet.rebaseOn(rebasedBase));
1184
1298
  }
1185
1299
  canAddTo(parentType) {
1186
- if (this.field.parentType === parentType) {
1300
+ if (this.element.parentType === parentType) {
1187
1301
  return true;
1188
1302
  }
1189
- const type = this.field.typeIfAddedTo(parentType);
1303
+ const type = this.element.typeIfAddedTo(parentType);
1190
1304
  if (!type) {
1191
1305
  return false;
1192
1306
  }
1193
1307
  const base = (0, definitions_1.baseType)(type);
1194
1308
  if (this.selectionSet && this.selectionSet.parentType !== base) {
1195
- (0, utils_1.assert)((0, definitions_1.isCompositeType)(base), () => `${this.field} should have a selection set as it's type is not a composite`);
1309
+ (0, utils_1.assert)((0, definitions_1.isCompositeType)(base), () => `${this.element} should have a selection set as it's type is not a composite`);
1196
1310
  return this.selectionSet.selections().every((s) => s.canAddTo(base));
1197
1311
  }
1198
1312
  return true;
1199
1313
  }
1200
1314
  toSelectionNode() {
1201
1315
  var _a;
1202
- const alias = this.field.alias ? { kind: graphql_1.Kind.NAME, value: this.field.alias, } : undefined;
1316
+ const alias = this.element.alias ? { kind: graphql_1.Kind.NAME, value: this.element.alias, } : undefined;
1203
1317
  return {
1204
1318
  kind: graphql_1.Kind.FIELD,
1205
1319
  name: {
1206
1320
  kind: graphql_1.Kind.NAME,
1207
- value: this.field.name,
1321
+ value: this.element.name,
1208
1322
  },
1209
1323
  alias,
1210
- arguments: this.fieldArgumentsToAST(),
1211
- directives: this.element().appliedDirectivesToDirectiveNodes(),
1324
+ arguments: this.element.argumentsToNodes(),
1325
+ directives: this.element.appliedDirectivesToDirectiveNodes(),
1212
1326
  selectionSet: (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.toSelectionSetNode()
1213
1327
  };
1214
1328
  }
1215
- withUpdatedSubSelection(newSubSelection) {
1216
- return new FieldSelection(this.field, newSubSelection);
1329
+ withoutDefer(labelsToRemove) {
1330
+ return this.mapToSelectionSet((s) => s.withoutDefer(labelsToRemove));
1217
1331
  }
1218
- withUpdatedField(newField) {
1219
- return new FieldSelection(newField, this.selectionSet);
1332
+ withNormalizedDefer(normalizer) {
1333
+ return this.mapToSelectionSet((s) => s.withNormalizedDefer(normalizer));
1334
+ }
1335
+ hasDefer() {
1336
+ var _a;
1337
+ return !!((_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.hasDefer());
1338
+ }
1339
+ expandAllFragments() {
1340
+ return this.mapToSelectionSet((s) => s.expandAllFragments());
1341
+ }
1342
+ trimUnsatisfiableBranches(_) {
1343
+ var _a;
1344
+ if (!this.selectionSet) {
1345
+ return this;
1346
+ }
1347
+ const base = (0, definitions_1.baseType)(this.element.definition.type);
1348
+ (0, utils_1.assert)((0, definitions_1.isCompositeType)(base), () => `Field ${this.element} should not have a sub-selection`);
1349
+ const trimmed = this.mapToSelectionSet((s) => s.trimUnsatisfiableBranches(base));
1350
+ if ((_a = trimmed.selectionSet) === null || _a === void 0 ? void 0 : _a.isEmpty()) {
1351
+ return trimmed.withUpdatedSelectionSet(selectionSetOfElement(new Field(base.typenameField(), undefined, [new definitions_1.Directive('include', { 'if': false })])));
1352
+ }
1353
+ else {
1354
+ return trimmed;
1355
+ }
1356
+ }
1357
+ expandFragments(names, updatedFragments) {
1358
+ return this.mapToSelectionSet((s) => s.expandFragments(names, updatedFragments));
1220
1359
  }
1221
1360
  equals(that) {
1222
1361
  if (this === that) {
1223
1362
  return true;
1224
1363
  }
1225
- if (!(that instanceof FieldSelection) || !this.field.equals(that.field)) {
1364
+ if (!(that instanceof FieldSelection) || !this.element.equals(that.element)) {
1226
1365
  return false;
1227
1366
  }
1228
1367
  if (!this.selectionSet) {
@@ -1231,7 +1370,7 @@ class FieldSelection extends Freezable {
1231
1370
  return !!that.selectionSet && this.selectionSet.equals(that.selectionSet);
1232
1371
  }
1233
1372
  contains(that) {
1234
- if (!(that instanceof FieldSelection) || !this.field.equals(that.field)) {
1373
+ if (!(that instanceof FieldSelection) || !this.element.equals(that.element)) {
1235
1374
  return false;
1236
1375
  }
1237
1376
  if (!that.selectionSet) {
@@ -1239,126 +1378,87 @@ class FieldSelection extends Freezable {
1239
1378
  }
1240
1379
  return !!this.selectionSet && this.selectionSet.contains(that.selectionSet);
1241
1380
  }
1242
- namedFragments() {
1243
- var _a;
1244
- return (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.fragments;
1245
- }
1246
- withoutDefer(labelsToRemove) {
1247
- var _a;
1248
- const updatedSubSelections = (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.withoutDefer(labelsToRemove);
1249
- return updatedSubSelections === this.selectionSet
1250
- ? this
1251
- : new FieldSelection(this.field, updatedSubSelections);
1252
- }
1253
- withNormalizedDefer(normalizer) {
1254
- var _a;
1255
- const updatedSubSelections = (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.withNormalizedDefer(normalizer);
1256
- return updatedSubSelections === this.selectionSet
1257
- ? this
1258
- : new FieldSelection(this.field, updatedSubSelections);
1259
- }
1260
- clone() {
1261
- if (!this.selectionSet) {
1262
- return this;
1263
- }
1264
- return new FieldSelection(this.field, this.selectionSet.clone());
1265
- }
1266
1381
  toString(expandFragments = true, indent) {
1267
- return (indent !== null && indent !== void 0 ? indent : '') + this.field + (this.selectionSet ? ' ' + this.selectionSet.toString(expandFragments, true, indent) : '');
1382
+ return (indent !== null && indent !== void 0 ? indent : '') + this.element + (this.selectionSet ? ' ' + this.selectionSet.toString(expandFragments, true, indent) : '');
1268
1383
  }
1269
1384
  }
1270
1385
  exports.FieldSelection = FieldSelection;
1271
- class FragmentSelection extends Freezable {
1386
+ class FragmentSelection extends AbstractSelection {
1272
1387
  constructor() {
1273
1388
  super(...arguments);
1274
1389
  this.kind = 'FragmentSelection';
1275
1390
  }
1276
- get parentType() {
1277
- return this.element().parentType;
1278
- }
1279
1391
  us() {
1280
1392
  return this;
1281
1393
  }
1282
1394
  validateDeferAndStream() {
1283
- if (this.element().hasDefer() || this.element().hasStream()) {
1284
- const schemaDef = this.element().schema().schemaDefinition;
1285
- const parentType = this.element().parentType;
1395
+ if (this.element.hasDefer() || this.element.hasStream()) {
1396
+ const schemaDef = this.element.schema().schemaDefinition;
1397
+ const parentType = this.parentType;
1286
1398
  validate(schemaDef.rootType('mutation') !== parentType && schemaDef.rootType('subscription') !== parentType, () => { var _a; return `The @defer and @stream directives cannot be used on ${(_a = schemaDef.roots().filter((t) => t.type === parentType).pop()) === null || _a === void 0 ? void 0 : _a.rootKind} root type "${parentType}"`; });
1287
1399
  }
1288
1400
  }
1289
- usedVariables() {
1290
- return (0, definitions_1.mergeVariables)(this.element().variables(), this.selectionSet.usedVariables());
1291
- }
1292
1401
  filter(predicate) {
1293
1402
  const selectionSet = this.selectionSet;
1294
1403
  const updatedSelectionSet = selectionSet.filter(predicate);
1295
1404
  const thisWithFilteredSelectionSet = updatedSelectionSet === selectionSet
1296
1405
  ? this
1297
- : new InlineFragmentSelection(this.element(), updatedSelectionSet);
1406
+ : new InlineFragmentSelection(this.element, updatedSelectionSet);
1298
1407
  return predicate(thisWithFilteredSelectionSet) ? thisWithFilteredSelectionSet : undefined;
1299
1408
  }
1300
- freezeInternals() {
1301
- this.selectionSet.freeze();
1409
+ hasDefer() {
1410
+ return this.element.hasDefer() || this.selectionSet.hasDefer();
1302
1411
  }
1303
1412
  equals(that) {
1304
1413
  if (this === that) {
1305
1414
  return true;
1306
1415
  }
1307
1416
  return (that instanceof FragmentSelection)
1308
- && this.element().equals(that.element())
1417
+ && this.element.equals(that.element)
1309
1418
  && this.selectionSet.equals(that.selectionSet);
1310
1419
  }
1311
1420
  contains(that) {
1312
1421
  return (that instanceof FragmentSelection)
1313
- && this.element().equals(that.element())
1422
+ && this.element.equals(that.element)
1314
1423
  && this.selectionSet.contains(that.selectionSet);
1315
1424
  }
1316
- clone() {
1317
- return new InlineFragmentSelection(this.element(), this.selectionSet.clone());
1318
- }
1319
1425
  }
1320
1426
  exports.FragmentSelection = FragmentSelection;
1321
1427
  class InlineFragmentSelection extends FragmentSelection {
1322
- constructor(fragmentElement, initialSelectionSet) {
1323
- super();
1324
- this.fragmentElement = fragmentElement;
1325
- this._selectionSet = initialSelectionSet
1326
- ? initialSelectionSet.cloneIfFrozen()
1327
- : new SelectionSet(fragmentElement.typeCondition ? fragmentElement.typeCondition : fragmentElement.parentType);
1428
+ constructor(fragment, _selectionSet) {
1429
+ super(fragment);
1430
+ this._selectionSet = _selectionSet;
1431
+ }
1432
+ get selectionSet() {
1433
+ return this._selectionSet;
1328
1434
  }
1329
1435
  key() {
1330
- var _a, _b;
1331
- return (_b = (_a = this.element().typeCondition) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '';
1436
+ return this.element.key();
1332
1437
  }
1333
- validate() {
1438
+ withUpdatedComponents(fragment, selectionSet) {
1439
+ return new InlineFragmentSelection(fragment, selectionSet);
1440
+ }
1441
+ validate(variableDefinitions) {
1334
1442
  this.validateDeferAndStream();
1335
- validate(!this.selectionSet.isEmpty(), () => `Invalid empty selection set for fragment "${this.element()}"`);
1336
- this.selectionSet.validate();
1443
+ validate(!this.selectionSet.isEmpty(), () => `Invalid empty selection set for fragment "${this.element}"`);
1444
+ this.selectionSet.validate(variableDefinitions);
1337
1445
  }
1338
- updateForAddingTo(selectionSet) {
1339
- var _a;
1340
- const updatedFragment = this.element().updateForAddingTo(selectionSet);
1341
- if (this.element() === updatedFragment) {
1342
- return this.cloneIfFrozen();
1343
- }
1344
- const updatedCastedType = updatedFragment.castedType();
1345
- let updatedSelectionSet;
1346
- if (this.selectionSet.parentType !== updatedCastedType) {
1347
- updatedSelectionSet = new SelectionSet(updatedCastedType);
1348
- for (const selection of this.selectionSet.selections()) {
1349
- updatedSelectionSet.add(selection);
1350
- }
1446
+ rebaseOn(parentType) {
1447
+ if (this.parentType === parentType) {
1448
+ return this;
1351
1449
  }
1352
- else {
1353
- updatedSelectionSet = (_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.cloneIfFrozen();
1450
+ const rebasedFragment = this.element.rebaseOn(parentType);
1451
+ const rebasedCastedType = rebasedFragment.castedType();
1452
+ if (rebasedCastedType === this.selectionSet.parentType) {
1453
+ return this.withUpdatedElement(rebasedFragment);
1354
1454
  }
1355
- return new InlineFragmentSelection(updatedFragment, updatedSelectionSet);
1455
+ return this.withUpdatedComponents(rebasedFragment, this.selectionSet.rebaseOn(rebasedCastedType));
1356
1456
  }
1357
1457
  canAddTo(parentType) {
1358
- if (this.element().parentType === parentType) {
1458
+ if (this.element.parentType === parentType) {
1359
1459
  return true;
1360
1460
  }
1361
- const type = this.element().castedTypeIfAddedTo(parentType);
1461
+ const type = this.element.castedTypeIfAddedTo(parentType);
1362
1462
  if (!type) {
1363
1463
  return false;
1364
1464
  }
@@ -1367,17 +1467,8 @@ class InlineFragmentSelection extends FragmentSelection {
1367
1467
  }
1368
1468
  return true;
1369
1469
  }
1370
- get selectionSet() {
1371
- return this._selectionSet;
1372
- }
1373
- namedFragments() {
1374
- return this.selectionSet.fragments;
1375
- }
1376
- element() {
1377
- return this.fragmentElement;
1378
- }
1379
1470
  toSelectionNode() {
1380
- const typeCondition = this.element().typeCondition;
1471
+ const typeCondition = this.element.typeCondition;
1381
1472
  return {
1382
1473
  kind: graphql_1.Kind.INLINE_FRAGMENT,
1383
1474
  typeCondition: typeCondition
@@ -1389,103 +1480,161 @@ class InlineFragmentSelection extends FragmentSelection {
1389
1480
  },
1390
1481
  }
1391
1482
  : undefined,
1392
- directives: this.element().appliedDirectivesToDirectiveNodes(),
1483
+ directives: this.element.appliedDirectivesToDirectiveNodes(),
1393
1484
  selectionSet: this.selectionSet.toSelectionSetNode()
1394
1485
  };
1395
1486
  }
1396
1487
  optimize(fragments) {
1397
1488
  let optimizedSelection = this.selectionSet.optimize(fragments);
1398
- const typeCondition = this.element().typeCondition;
1489
+ const typeCondition = this.element.typeCondition;
1399
1490
  if (typeCondition) {
1400
1491
  for (const candidate of fragments.maybeApplyingAtType(typeCondition)) {
1401
1492
  if (optimizedSelection.equals(candidate.selectionSet)) {
1402
- const spread = new FragmentSpreadSelection(this.element().parentType, fragments, candidate.name);
1493
+ let spreadDirectives = [];
1494
+ if (this.element.appliedDirectives) {
1495
+ const { isSubset, difference } = diffDirectives(this.element.appliedDirectives, candidate.appliedDirectives);
1496
+ if (!isSubset) {
1497
+ continue;
1498
+ }
1499
+ spreadDirectives = difference;
1500
+ }
1501
+ const newSelection = new FragmentSpreadSelection(this.parentType, fragments, candidate, spreadDirectives);
1403
1502
  if ((0, types_1.sameType)(typeCondition, candidate.typeCondition)) {
1404
- this.fragmentElement.appliedDirectives.forEach((directive) => {
1405
- spread.element().applyDirective(directive.definition, directive.arguments());
1406
- });
1407
- return spread;
1503
+ return newSelection;
1408
1504
  }
1409
- optimizedSelection = selectionSetOf(spread.element().parentType, spread);
1505
+ optimizedSelection = selectionSetOf(this.parentType, newSelection);
1410
1506
  break;
1411
1507
  }
1412
1508
  }
1413
1509
  }
1414
1510
  return this.selectionSet === optimizedSelection
1415
1511
  ? this
1416
- : new InlineFragmentSelection(this.fragmentElement, optimizedSelection);
1417
- }
1418
- expandFragments(names, updateSelectionSetFragments = true) {
1419
- const expandedSelection = this.selectionSet.expandFragments(names, updateSelectionSetFragments);
1420
- return this.selectionSet === expandedSelection
1421
- ? this
1422
- : new InlineFragmentSelection(this.element(), expandedSelection);
1423
- }
1424
- collectUsedFragmentNames(collector) {
1425
- this.selectionSet.collectUsedFragmentNames(collector);
1512
+ : new InlineFragmentSelection(this.element, optimizedSelection);
1426
1513
  }
1427
1514
  withoutDefer(labelsToRemove) {
1428
- const updatedSubSelections = this.selectionSet.withoutDefer(labelsToRemove);
1429
- const deferArgs = this.fragmentElement.deferDirectiveArgs();
1515
+ const newSelection = this.selectionSet.withoutDefer(labelsToRemove);
1516
+ const deferArgs = this.element.deferDirectiveArgs();
1430
1517
  const hasDeferToRemove = deferArgs && (!labelsToRemove || (deferArgs.label && labelsToRemove.has(deferArgs.label)));
1431
- if (updatedSubSelections === this.selectionSet && !hasDeferToRemove) {
1518
+ if (newSelection === this.selectionSet && !hasDeferToRemove) {
1432
1519
  return this;
1433
1520
  }
1434
- const newFragment = hasDeferToRemove ? this.fragmentElement.withoutDefer() : this.fragmentElement;
1435
- if (!newFragment) {
1436
- return updatedSubSelections;
1521
+ const newElement = hasDeferToRemove ? this.element.withoutDefer() : this.element;
1522
+ if (!newElement) {
1523
+ return newSelection;
1437
1524
  }
1438
- return new InlineFragmentSelection(newFragment, updatedSubSelections);
1525
+ return this.withUpdatedComponents(newElement, newSelection);
1439
1526
  }
1440
1527
  withNormalizedDefer(normalizer) {
1441
- const newFragment = this.fragmentElement.withNormalizedDefer(normalizer);
1442
- const updatedSubSelections = this.selectionSet.withNormalizedDefer(normalizer);
1443
- if (!newFragment) {
1444
- return updatedSubSelections;
1528
+ const newElement = this.element.withNormalizedDefer(normalizer);
1529
+ const newSelection = this.selectionSet.withNormalizedDefer(normalizer);
1530
+ if (!newElement) {
1531
+ return newSelection;
1445
1532
  }
1446
- return newFragment === this.fragmentElement && updatedSubSelections === this.selectionSet
1533
+ return newElement === this.element && newSelection === this.selectionSet
1447
1534
  ? this
1448
- : new InlineFragmentSelection(newFragment, updatedSubSelections);
1535
+ : this.withUpdatedComponents(newElement, newSelection);
1536
+ }
1537
+ trimUnsatisfiableBranches(currentType) {
1538
+ var _a, _b;
1539
+ const thisCondition = this.element.typeCondition;
1540
+ if (this.element.appliedDirectives.length === 0) {
1541
+ if (!thisCondition || currentType === this.element.typeCondition) {
1542
+ const trimmed = this.selectionSet.trimUnsatisfiableBranches(currentType);
1543
+ return trimmed.isEmpty() ? undefined : trimmed;
1544
+ }
1545
+ if ((0, definitions_1.isObjectType)(currentType)) {
1546
+ if ((0, definitions_1.isObjectType)(thisCondition)) {
1547
+ return undefined;
1548
+ }
1549
+ else {
1550
+ const trimmed = this.selectionSet.trimUnsatisfiableBranches(currentType);
1551
+ return trimmed.isEmpty() ? undefined : trimmed;
1552
+ }
1553
+ }
1554
+ }
1555
+ const trimmedSelectionSet = this.selectionSet.trimUnsatisfiableBranches((_a = this.element.typeCondition) !== null && _a !== void 0 ? _a : this.parentType);
1556
+ if (trimmedSelectionSet.isEmpty()) {
1557
+ if (this.element.appliedDirectives.length === 0) {
1558
+ return undefined;
1559
+ }
1560
+ else {
1561
+ return this.withUpdatedSelectionSet(selectionSetOfElement(new Field(((_b = this.element.typeCondition) !== null && _b !== void 0 ? _b : this.parentType).typenameField(), undefined, [new definitions_1.Directive('include', { 'if': false })])));
1562
+ }
1563
+ }
1564
+ if (this.element.appliedDirectives.length === 0 && (0, definitions_1.isAbstractType)(thisCondition)) {
1565
+ (0, utils_1.assert)(!(0, definitions_1.isObjectType)(currentType), () => `Should not have got here if ${currentType} is an object type`);
1566
+ const currentRuntimes = (0, definitions_1.possibleRuntimeTypes)(currentType);
1567
+ const liftableSelections = [];
1568
+ for (const selection of trimmedSelectionSet.selections()) {
1569
+ if (selection.kind === 'FragmentSelection'
1570
+ && selection.element.typeCondition
1571
+ && (0, definitions_1.isObjectType)(selection.element.typeCondition)
1572
+ && currentRuntimes.includes(selection.element.typeCondition)) {
1573
+ liftableSelections.push(selection);
1574
+ }
1575
+ }
1576
+ if (liftableSelections.length === trimmedSelectionSet.selections().length) {
1577
+ return trimmedSelectionSet;
1578
+ }
1579
+ if (liftableSelections.length > 0) {
1580
+ const newSet = new SelectionSetUpdates();
1581
+ newSet.add(liftableSelections);
1582
+ newSet.add(this.withUpdatedSelectionSet(trimmedSelectionSet.filter((s) => !liftableSelections.includes(s))));
1583
+ return newSet.toSelectionSet(this.parentType);
1584
+ }
1585
+ }
1586
+ return this.selectionSet === trimmedSelectionSet ? this : this.withUpdatedSelectionSet(trimmedSelectionSet);
1587
+ }
1588
+ expandAllFragments() {
1589
+ return this.mapToSelectionSet((s) => s.expandAllFragments());
1449
1590
  }
1450
- withUpdatedSubSelection(newSubSelection) {
1451
- return new InlineFragmentSelection(this.fragmentElement, newSubSelection);
1591
+ expandFragments(names, updatedFragments) {
1592
+ return this.mapToSelectionSet((s) => s.expandFragments(names, updatedFragments));
1452
1593
  }
1453
1594
  toString(expandFragments = true, indent) {
1454
- return (indent !== null && indent !== void 0 ? indent : '') + this.fragmentElement + ' ' + this.selectionSet.toString(expandFragments, true, indent);
1595
+ return (indent !== null && indent !== void 0 ? indent : '') + this.element + ' ' + this.selectionSet.toString(expandFragments, true, indent);
1596
+ }
1597
+ }
1598
+ function diffDirectives(superset, maybeSubset) {
1599
+ if (maybeSubset.every((d) => superset.some((s) => (0, definitions_1.sameDirectiveApplication)(d, s)))) {
1600
+ return { isSubset: true, difference: superset.filter((s) => !maybeSubset.some((d) => (0, definitions_1.sameDirectiveApplication)(d, s))) };
1601
+ }
1602
+ else {
1603
+ return { isSubset: false, difference: [] };
1455
1604
  }
1456
1605
  }
1457
1606
  class FragmentSpreadSelection extends FragmentSelection {
1458
- constructor(sourceType, fragments, fragmentName) {
1459
- super();
1607
+ constructor(sourceType, fragments, namedFragment, spreadDirectives) {
1608
+ super(new FragmentElement(sourceType, namedFragment.typeCondition, namedFragment.appliedDirectives.concat(spreadDirectives)));
1460
1609
  this.fragments = fragments;
1461
- const fragmentDefinition = fragments.get(fragmentName);
1462
- validate(fragmentDefinition, () => `Unknown fragment "...${fragmentName}"`);
1463
- this.namedFragment = fragmentDefinition;
1464
- this._element = new FragmentElement(sourceType, fragmentDefinition.typeCondition);
1465
- for (const directive of fragmentDefinition.appliedDirectives) {
1466
- this._element.applyDirective(directive.definition, directive.arguments());
1467
- }
1610
+ this.namedFragment = namedFragment;
1611
+ this.spreadDirectives = spreadDirectives;
1612
+ }
1613
+ get selectionSet() {
1614
+ return this.namedFragment.selectionSet;
1468
1615
  }
1469
1616
  key() {
1470
- return '...' + this.namedFragment.name;
1617
+ if (!this.computedKey) {
1618
+ this.computedKey = '...' + this.namedFragment.name + (this.spreadDirectives.length === 0 ? '' : ' ' + this.spreadDirectives.join(' '));
1619
+ }
1620
+ return this.computedKey;
1621
+ }
1622
+ withUpdatedComponents(_fragment, _selectionSet) {
1623
+ (0, utils_1.assert)(false, `Unsupported`);
1471
1624
  }
1472
- element() {
1473
- return this._element;
1625
+ trimUnsatisfiableBranches(_) {
1626
+ return this;
1474
1627
  }
1475
1628
  namedFragments() {
1476
1629
  return this.fragments;
1477
1630
  }
1478
- get selectionSet() {
1479
- return this.namedFragment.selectionSet;
1480
- }
1481
1631
  validate() {
1482
1632
  this.validateDeferAndStream();
1483
1633
  }
1484
1634
  toSelectionNode() {
1485
- const spreadDirectives = this.spreadDirectives();
1486
- const directiveNodes = spreadDirectives.length === 0
1635
+ const directiveNodes = this.spreadDirectives.length === 0
1487
1636
  ? undefined
1488
- : spreadDirectives.map(directive => {
1637
+ : this.spreadDirectives.map(directive => {
1489
1638
  return {
1490
1639
  kind: graphql_1.Kind.DIRECTIVE,
1491
1640
  name: {
@@ -1504,20 +1653,26 @@ class FragmentSpreadSelection extends FragmentSelection {
1504
1653
  optimize(_) {
1505
1654
  return this;
1506
1655
  }
1507
- updateForAddingTo(_selectionSet) {
1656
+ rebaseOn(_parentType) {
1508
1657
  return this;
1509
1658
  }
1510
1659
  canAddTo(_) {
1511
1660
  return true;
1512
1661
  }
1513
- expandFragments(names, updateSelectionSetFragments = true) {
1514
- if (names && !names.includes(this.namedFragment.name)) {
1662
+ expandAllFragments() {
1663
+ const expandedSubSelections = this.selectionSet.expandAllFragments();
1664
+ return (0, types_1.sameType)(this.parentType, this.namedFragment.typeCondition) && this.element.appliedDirectives.length === 0
1665
+ ? expandedSubSelections.selections()
1666
+ : new InlineFragmentSelection(this.element, expandedSubSelections);
1667
+ }
1668
+ expandFragments(names, updatedFragments) {
1669
+ if (!names.includes(this.namedFragment.name)) {
1515
1670
  return this;
1516
1671
  }
1517
- const expandedSubSelections = this.selectionSet.expandFragments(names, updateSelectionSetFragments);
1518
- return (0, types_1.sameType)(this._element.parentType, this.namedFragment.typeCondition) && this._element.appliedDirectives.length === 0
1672
+ const expandedSubSelections = this.selectionSet.expandFragments(names, updatedFragments);
1673
+ return (0, types_1.sameType)(this.parentType, this.namedFragment.typeCondition) && this.element.appliedDirectives.length === 0
1519
1674
  ? expandedSubSelections.selections()
1520
- : new InlineFragmentSelection(this._element, expandedSubSelections);
1675
+ : new InlineFragmentSelection(this.element, expandedSubSelections);
1521
1676
  }
1522
1677
  collectUsedFragmentNames(collector) {
1523
1678
  this.selectionSet.collectUsedFragmentNames(collector);
@@ -1525,28 +1680,69 @@ class FragmentSpreadSelection extends FragmentSelection {
1525
1680
  collector.set(this.namedFragment.name, usageCount === undefined ? 1 : usageCount + 1);
1526
1681
  }
1527
1682
  withoutDefer(_labelsToRemove) {
1528
- (0, utils_1.assert)(false, 'Unsupported, see `Operation.withoutDefer`');
1529
- }
1530
- withNormalizedDefer(_normalizezr) {
1531
1683
  (0, utils_1.assert)(false, 'Unsupported, see `Operation.withAllDeferLabelled`');
1532
1684
  }
1533
- spreadDirectives() {
1534
- return this._element.appliedDirectives.slice(this.namedFragment.appliedDirectives.length);
1535
- }
1536
- withUpdatedSubSelection(_) {
1537
- (0, utils_1.assert)(false, `Unssupported`);
1685
+ withNormalizedDefer(_normalizer) {
1686
+ (0, utils_1.assert)(false, 'Unsupported, see `Operation.withAllDeferLabelled`');
1538
1687
  }
1539
1688
  toString(expandFragments = true, indent) {
1540
1689
  if (expandFragments) {
1541
- return (indent !== null && indent !== void 0 ? indent : '') + this._element + ' ' + this.selectionSet.toString(true, true, indent);
1690
+ return (indent !== null && indent !== void 0 ? indent : '') + this.element + ' ' + this.selectionSet.toString(true, true, indent);
1542
1691
  }
1543
1692
  else {
1544
- const directives = this.spreadDirectives();
1693
+ const directives = this.spreadDirectives;
1545
1694
  const directiveString = directives.length == 0 ? '' : ' ' + directives.join(' ');
1546
1695
  return (indent !== null && indent !== void 0 ? indent : '') + '...' + this.namedFragment.name + directiveString;
1547
1696
  }
1548
1697
  }
1549
1698
  }
1699
+ function selectionSetOfNode(parentType, node, variableDefinitions, fragments, fieldAccessor = (type, name) => type.field(name)) {
1700
+ if (node.selections.length === 1) {
1701
+ return selectionSetOf(parentType, selectionOfNode(parentType, node.selections[0], variableDefinitions, fragments, fieldAccessor), fragments);
1702
+ }
1703
+ const selections = new SelectionSetUpdates();
1704
+ for (const selectionNode of node.selections) {
1705
+ selections.add(selectionOfNode(parentType, selectionNode, variableDefinitions, fragments, fieldAccessor));
1706
+ }
1707
+ return selections.toSelectionSet(parentType, fragments);
1708
+ }
1709
+ function directiveOfNode(schema, node) {
1710
+ const directiveDef = schema.directive(node.name.value);
1711
+ validate(directiveDef, () => `Unknown directive "@${node.name.value}"`);
1712
+ return new definitions_1.Directive(directiveDef.name, (0, values_1.argumentsFromAST)(directiveDef.coordinate, node.arguments, directiveDef));
1713
+ }
1714
+ function directivesOfNodes(schema, nodes) {
1715
+ var _a;
1716
+ return (_a = nodes === null || nodes === void 0 ? void 0 : nodes.map((n) => directiveOfNode(schema, n))) !== null && _a !== void 0 ? _a : [];
1717
+ }
1718
+ function selectionOfNode(parentType, node, variableDefinitions, fragments, fieldAccessor = (type, name) => type.field(name)) {
1719
+ var _a, _b;
1720
+ let selection;
1721
+ const directives = directivesOfNodes(parentType.schema(), node.directives);
1722
+ switch (node.kind) {
1723
+ case graphql_1.Kind.FIELD:
1724
+ const definition = fieldAccessor(parentType, node.name.value);
1725
+ validate(definition, () => `Cannot query field "${node.name.value}" on type "${parentType}".`, parentType.sourceAST);
1726
+ const type = (0, definitions_1.baseType)(definition.type);
1727
+ const selectionSet = node.selectionSet
1728
+ ? selectionSetOfNode(type, node.selectionSet, variableDefinitions, fragments, fieldAccessor)
1729
+ : undefined;
1730
+ selection = new FieldSelection(new Field(definition, (0, values_1.argumentsFromAST)(definition.coordinate, node.arguments, definition), directives, (_a = node.alias) === null || _a === void 0 ? void 0 : _a.value), selectionSet);
1731
+ break;
1732
+ case graphql_1.Kind.INLINE_FRAGMENT:
1733
+ const element = new FragmentElement(parentType, (_b = node.typeCondition) === null || _b === void 0 ? void 0 : _b.name.value, directives);
1734
+ selection = new InlineFragmentSelection(element, selectionSetOfNode(element.typeCondition ? element.typeCondition : element.parentType, node.selectionSet, variableDefinitions, fragments, fieldAccessor));
1735
+ break;
1736
+ case graphql_1.Kind.FRAGMENT_SPREAD:
1737
+ const fragmentName = node.name.value;
1738
+ validate(fragments, () => `Cannot find fragment name "${fragmentName}" (no fragments were provided)`);
1739
+ const fragment = fragments.get(fragmentName);
1740
+ validate(fragment, () => `Cannot find fragment name "${fragmentName}" (provided fragments are: [${fragments.names().join(', ')}])`);
1741
+ selection = new FragmentSpreadSelection(parentType, fragments, fragment, directives);
1742
+ break;
1743
+ }
1744
+ return selection;
1745
+ }
1550
1746
  function operationFromDocument(schema, document, options) {
1551
1747
  let operation;
1552
1748
  const operationName = options === null || options === void 0 ? void 0 : options.operationName;
@@ -1569,9 +1765,7 @@ function operationFromDocument(schema, document, options) {
1569
1765
  if (!(0, definitions_1.isCompositeType)(typeCondition)) {
1570
1766
  throw error_1.ERRORS.INVALID_GRAPHQL.err(`Invalid fragment "${name}" on non-composite type "${typeName}"`, { nodes: definition });
1571
1767
  }
1572
- const fragment = new NamedFragmentDefinition(schema, name, typeCondition, new SelectionSet(typeCondition, fragments));
1573
- addDirectiveNodesToElement(definition.directives, fragment);
1574
- fragments.add(fragment);
1768
+ fragments.add(new NamedFragmentDefinition(schema, name, typeCondition, directivesOfNodes(schema, definition.directives)));
1575
1769
  break;
1576
1770
  }
1577
1771
  });
@@ -1583,11 +1777,11 @@ function operationFromDocument(schema, document, options) {
1583
1777
  switch (definition.kind) {
1584
1778
  case graphql_1.Kind.FRAGMENT_DEFINITION:
1585
1779
  const fragment = fragments.get(definition.name.value);
1586
- fragment.selectionSet.addSelectionSetNode(definition.selectionSet, variableDefinitions);
1780
+ fragment.setSelectionSet(selectionSetOfNode(fragment.typeCondition, definition.selectionSet, variableDefinitions, fragments));
1587
1781
  break;
1588
1782
  }
1589
1783
  });
1590
- fragments.validate();
1784
+ fragments.validate(variableDefinitions);
1591
1785
  return operationFromAST({ schema, operation, variableDefinitions, fragments, validateInput: options === null || options === void 0 ? void 0 : options.validate });
1592
1786
  }
1593
1787
  exports.operationFromDocument = operationFromDocument;
@@ -1599,7 +1793,7 @@ function operationFromAST({ schema, operation, variableDefinitions, fragments, v
1599
1793
  parentType: rootType.type,
1600
1794
  source: operation.selectionSet,
1601
1795
  variableDefinitions,
1602
- fragments,
1796
+ fragments: fragments.isEmpty() ? undefined : fragments,
1603
1797
  validate: validateInput,
1604
1798
  }), variableDefinitions, (_a = operation.name) === null || _a === void 0 ? void 0 : _a.value);
1605
1799
  }
@@ -1607,14 +1801,13 @@ function parseOperation(schema, operation, options) {
1607
1801
  return operationFromDocument(schema, (0, graphql_1.parse)(operation), options);
1608
1802
  }
1609
1803
  exports.parseOperation = parseOperation;
1610
- function parseSelectionSet({ parentType, source, variableDefinitions, fragments, fieldAccessor, validate = true, }) {
1804
+ function parseSelectionSet({ parentType, source, variableDefinitions = new definitions_1.VariableDefinitions(), fragments, fieldAccessor, validate = true, }) {
1611
1805
  const node = typeof source === 'string'
1612
1806
  ? parseOperationAST(source.trim().startsWith('{') ? source : `{${source}}`).selectionSet
1613
1807
  : source;
1614
- const selectionSet = new SelectionSet(parentType, fragments);
1615
- selectionSet.addSelectionSetNode(node, variableDefinitions !== null && variableDefinitions !== void 0 ? variableDefinitions : new definitions_1.VariableDefinitions(), fieldAccessor);
1808
+ const selectionSet = selectionSetOfNode(parentType, node, variableDefinitions !== null && variableDefinitions !== void 0 ? variableDefinitions : new definitions_1.VariableDefinitions(), fragments, fieldAccessor);
1616
1809
  if (validate)
1617
- selectionSet.validate();
1810
+ selectionSet.validate(variableDefinitions);
1618
1811
  return selectionSet;
1619
1812
  }
1620
1813
  exports.parseSelectionSet = parseSelectionSet;