UNPKG

3.69 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * strict-local
8 * @format
9 */
10'use strict';
11
12var _objectSpread2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/objectSpread"));
13
14var _toConsumableArray2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/toConsumableArray"));
15
16var ID = 'id';
17var ID_TYPE = 'ID';
18var NODE_TYPE = 'Node';
19
20/**
21 * A transform that adds an `id` field on any type that has an id field but
22 * where there is no unaliased `id` selection.
23 */
24function relayGenerateIDFieldTransform(context) {
25 var idType = require("graphql").assertLeafType(context.serverSchema.getType(ID_TYPE));
26
27 var idField = {
28 kind: 'ScalarField',
29 alias: null,
30 args: [],
31 directives: [],
32 handles: null,
33 loc: {
34 kind: 'Generated'
35 },
36 metadata: null,
37 name: ID,
38 type: idType
39 };
40 var state = {
41 idField: idField
42 };
43 return require("./GraphQLIRTransformer").transform(context, {
44 LinkedField: visitLinkedOrMatchField,
45 MatchField: visitLinkedOrMatchField
46 }, function () {
47 return state;
48 });
49}
50
51function visitLinkedOrMatchField(field, state) {
52 var transformedNode = this.traverse(field, state); // If the field already has an unaliased `id` field, do nothing
53
54 if (require("./RelayTransformUtils").hasUnaliasedSelection(field, ID)) {
55 return transformedNode;
56 }
57
58 var context = this.getContext();
59 var schema = context.serverSchema;
60
61 var unmodifiedType = require("graphql").assertCompositeType(require("./GraphQLSchemaUtils").getRawType(field.type)); // If the field type has an `id` subfield add an `id` selection
62
63
64 if (require("./GraphQLSchemaUtils").canHaveSelections(unmodifiedType) && require("./GraphQLSchemaUtils").hasID(schema, unmodifiedType)) {
65 return (0, _objectSpread2["default"])({}, transformedNode, {
66 selections: (0, _toConsumableArray2["default"])(transformedNode.selections).concat([state.idField])
67 });
68 } // If the field type is abstract, then generate a `... on Node { id }`
69 // fragment if *any* concrete type implements Node. Then generate a
70 // `... on PossibleType { id }` for every concrete type that does *not*
71 // implement `Node`
72
73
74 if (require("./GraphQLSchemaUtils").isAbstractType(unmodifiedType)) {
75 var selections = (0, _toConsumableArray2["default"])(transformedNode.selections);
76
77 if (require("./GraphQLSchemaUtils").mayImplement(schema, unmodifiedType, NODE_TYPE)) {
78 var nodeType = require("graphql").assertCompositeType(schema.getType(NODE_TYPE));
79
80 selections.push(buildIDFragment(nodeType, state.idField));
81 }
82
83 var abstractType = require("graphql").assertAbstractType(unmodifiedType);
84
85 schema.getPossibleTypes(abstractType).forEach(function (possibleType) {
86 if (!require("./GraphQLSchemaUtils").implementsInterface(possibleType, NODE_TYPE) && require("./GraphQLSchemaUtils").hasID(schema, possibleType)) {
87 selections.push(buildIDFragment(possibleType, state.idField));
88 }
89 });
90 return (0, _objectSpread2["default"])({}, transformedNode, {
91 selections: selections
92 });
93 }
94
95 return transformedNode;
96}
97/**
98 * @internal
99 *
100 * Returns IR for `... on FRAGMENT_TYPE { id }`
101 */
102
103
104function buildIDFragment(fragmentType, idField) {
105 return {
106 kind: 'InlineFragment',
107 directives: [],
108 loc: {
109 kind: 'Generated'
110 },
111 metadata: null,
112 typeCondition: fragmentType,
113 selections: [idField]
114 };
115}
116
117module.exports = {
118 transform: relayGenerateIDFieldTransform
119};
\No newline at end of file