UNPKG

6.75 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
14/**
15 * This transform finds usages of @defer and @stream, validates them, and
16 * converts the using node to specialized IR nodes (Defer/Stream).
17 */
18function relayDeferStreamTransform(context) {
19 return require("./GraphQLIRTransformer").transform(context, {
20 // TODO: type IRTransformer to allow changing result type
21 FragmentSpread: visitFragmentSpread,
22 // TODO: type IRTransformer to allow changing result type
23 InlineFragment: visitInlineFragment,
24 // TODO: type IRTransformer to allow changing result type
25 LinkedField: visitLinkedField,
26 ScalarField: visitScalarField
27 }, function (sourceNode) {
28 return {
29 documentName: sourceNode.name
30 };
31 });
32}
33
34function visitLinkedField(field, state) {
35 var _ref, _ref2;
36
37 var transformedField = this.traverse(field, state);
38 var streamDirective = transformedField.directives.find(function (directive) {
39 return directive.name === 'stream';
40 });
41
42 if (streamDirective == null) {
43 return transformedField;
44 }
45
46 var type = require("./GraphQLSchemaUtils").getNullableType(field.type);
47
48 if (!(type instanceof require("graphql").GraphQLList)) {
49 throw require("./RelayCompilerError").createUserError("Invalid use of @stream on non-plural field '".concat(field.name, "'"), [streamDirective.loc]);
50 }
51
52 transformedField = (0, _objectSpread2["default"])({}, transformedField, {
53 directives: transformedField.directives.filter(function (directive) {
54 return directive.name !== 'stream';
55 })
56 });
57 var ifArg = streamDirective.args.find(function (arg) {
58 return arg.name === 'if';
59 });
60
61 if (isLiteralFalse(ifArg)) {
62 // If a stream is statically known to be disabled, treat as if the node
63 // was not streamed.
64 return transformedField;
65 }
66
67 var initialCount = streamDirective.args.find(function (arg) {
68 return arg.name === 'initial_count';
69 });
70 var label = getLiteralStringArgument(streamDirective, 'label');
71 var transformedLabel = transformLabel(state.documentName, 'stream', label);
72 return {
73 "if": (_ref = ifArg === null || ifArg === void 0 ? void 0 : ifArg.value) !== null && _ref !== void 0 ? _ref : null,
74 initialCount: (_ref2 = initialCount === null || initialCount === void 0 ? void 0 : initialCount.value) !== null && _ref2 !== void 0 ? _ref2 : null,
75 kind: 'Stream',
76 label: transformedLabel,
77 loc: {
78 kind: 'Derived',
79 source: streamDirective.loc
80 },
81 metadata: null,
82 selections: [transformedField]
83 };
84}
85
86function visitScalarField(field, state) {
87 var streamDirective = field.directives.find(function (directive) {
88 return directive.name === 'stream';
89 });
90
91 if (streamDirective != null) {
92 throw require("./RelayCompilerError").createUserError("Invalid use of @stream on scalar field '".concat(field.name, "'"), [streamDirective.loc]);
93 }
94
95 return this.traverse(field, state);
96}
97
98function visitInlineFragment(fragment, state) {
99 var _ref3;
100
101 var transformedFragment = this.traverse(fragment, state);
102 var deferDirective = transformedFragment.directives.find(function (directive) {
103 return directive.name === 'defer';
104 });
105
106 if (deferDirective == null) {
107 return transformedFragment;
108 }
109
110 transformedFragment = (0, _objectSpread2["default"])({}, transformedFragment, {
111 directives: transformedFragment.directives.filter(function (directive) {
112 return directive.name !== 'defer';
113 })
114 });
115 var ifArg = deferDirective.args.find(function (arg) {
116 return arg.name === 'if';
117 });
118
119 if (isLiteralFalse(ifArg)) {
120 // If a defer is statically known to be disabled, treat as if the node
121 // was not deferred.
122 return transformedFragment;
123 }
124
125 var label = getLiteralStringArgument(deferDirective, 'label');
126 var transformedLabel = transformLabel(state.documentName, 'defer', label);
127 return {
128 "if": (_ref3 = ifArg === null || ifArg === void 0 ? void 0 : ifArg.value) !== null && _ref3 !== void 0 ? _ref3 : null,
129 kind: 'Defer',
130 label: transformedLabel,
131 loc: {
132 kind: 'Derived',
133 source: deferDirective.loc
134 },
135 metadata: null,
136 selections: [transformedFragment]
137 };
138}
139
140function visitFragmentSpread(spread, state) {
141 var _ref4;
142
143 var transformedSpread = this.traverse(spread, state);
144 var deferDirective = transformedSpread.directives.find(function (directive) {
145 return directive.name === 'defer';
146 });
147
148 if (deferDirective == null) {
149 return transformedSpread;
150 }
151
152 transformedSpread = (0, _objectSpread2["default"])({}, transformedSpread, {
153 directives: transformedSpread.directives.filter(function (directive) {
154 return directive.name !== 'defer';
155 })
156 });
157 var ifArg = deferDirective.args.find(function (arg) {
158 return arg.name === 'if';
159 });
160
161 if (isLiteralFalse(ifArg)) {
162 // If a defer is statically known to be disabled, treat as if the node
163 // was not deferred.
164 return transformedSpread;
165 }
166
167 var label = getLiteralStringArgument(deferDirective, 'label');
168 var transformedLabel = transformLabel(state.documentName, 'defer', label);
169 return {
170 "if": (_ref4 = ifArg === null || ifArg === void 0 ? void 0 : ifArg.value) !== null && _ref4 !== void 0 ? _ref4 : null,
171 kind: 'Defer',
172 label: transformedLabel,
173 loc: {
174 kind: 'Derived',
175 source: deferDirective.loc
176 },
177 metadata: null,
178 selections: [transformedSpread]
179 };
180}
181
182function getLiteralStringArgument(directive, argName) {
183 // NOTE: can't use getLiteralArgumentValues here because other args
184 // are allowed to be non-literals
185 var arg = directive.args.find(function (_ref6) {
186 var name = _ref6.name;
187 return name === argName;
188 });
189 var value = arg != null && arg.value.kind === 'Literal' ? arg.value.value : null;
190
191 if (typeof value !== 'string') {
192 var _ref5;
193
194 throw require("./RelayCompilerError").createUserError("Expected the '".concat(argName, "' value to @").concat(directive.name, " to be a string literal."), [(_ref5 = arg === null || arg === void 0 ? void 0 : arg.value.loc) !== null && _ref5 !== void 0 ? _ref5 : directive.loc]);
195 }
196
197 return value;
198}
199
200function transformLabel(parentName, directive, label) {
201 return "".concat(parentName, "$").concat(directive, "$").concat(label);
202}
203
204function isLiteralFalse(arg) {
205 return arg != null && arg.value.kind === 'Literal' && arg.value.value === false;
206}
207
208module.exports = {
209 transform: relayDeferStreamTransform
210};
\No newline at end of file