execute.js 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true,
  4. });
  5. exports.assertValidExecutionArguments = assertValidExecutionArguments;
  6. exports.buildExecutionContext = buildExecutionContext;
  7. exports.buildResolveInfo = buildResolveInfo;
  8. exports.defaultTypeResolver = exports.defaultFieldResolver = void 0;
  9. exports.execute = execute;
  10. exports.executeSync = executeSync;
  11. exports.getFieldDef = getFieldDef;
  12. var _devAssert = require('../jsutils/devAssert.js');
  13. var _inspect = require('../jsutils/inspect.js');
  14. var _invariant = require('../jsutils/invariant.js');
  15. var _isIterableObject = require('../jsutils/isIterableObject.js');
  16. var _isObjectLike = require('../jsutils/isObjectLike.js');
  17. var _isPromise = require('../jsutils/isPromise.js');
  18. var _memoize = require('../jsutils/memoize3.js');
  19. var _Path = require('../jsutils/Path.js');
  20. var _promiseForObject = require('../jsutils/promiseForObject.js');
  21. var _promiseReduce = require('../jsutils/promiseReduce.js');
  22. var _GraphQLError = require('../error/GraphQLError.js');
  23. var _locatedError = require('../error/locatedError.js');
  24. var _ast = require('../language/ast.js');
  25. var _kinds = require('../language/kinds.js');
  26. var _definition = require('../type/definition.js');
  27. var _introspection = require('../type/introspection.js');
  28. var _validate = require('../type/validate.js');
  29. var _collectFields = require('./collectFields.js');
  30. var _values = require('./values.js');
  31. /**
  32. * A memoized collection of relevant subfields with regard to the return
  33. * type. Memoizing ensures the subfields are not repeatedly calculated, which
  34. * saves overhead when resolving lists of values.
  35. */
  36. const collectSubfields = (0, _memoize.memoize3)(
  37. (exeContext, returnType, fieldNodes) =>
  38. (0, _collectFields.collectSubfields)(
  39. exeContext.schema,
  40. exeContext.fragments,
  41. exeContext.variableValues,
  42. returnType,
  43. fieldNodes,
  44. ),
  45. );
  46. /**
  47. * Terminology
  48. *
  49. * "Definitions" are the generic name for top-level statements in the document.
  50. * Examples of this include:
  51. * 1) Operations (such as a query)
  52. * 2) Fragments
  53. *
  54. * "Operations" are a generic name for requests in the document.
  55. * Examples of this include:
  56. * 1) query,
  57. * 2) mutation
  58. *
  59. * "Selections" are the definitions that can appear legally and at
  60. * single level of the query. These include:
  61. * 1) field references e.g `a`
  62. * 2) fragment "spreads" e.g. `...c`
  63. * 3) inline fragment "spreads" e.g. `...on Type { a }`
  64. */
  65. /**
  66. * Data that must be available at all points during query execution.
  67. *
  68. * Namely, schema of the type system that is currently executing,
  69. * and the fragments defined in the query document
  70. */
  71. /**
  72. * Implements the "Executing requests" section of the GraphQL specification.
  73. *
  74. * Returns either a synchronous ExecutionResult (if all encountered resolvers
  75. * are synchronous), or a Promise of an ExecutionResult that will eventually be
  76. * resolved and never rejected.
  77. *
  78. * If the arguments to this function do not result in a legal execution context,
  79. * a GraphQLError will be thrown immediately explaining the invalid input.
  80. */
  81. function execute(args) {
  82. // Temporary for v15 to v16 migration. Remove in v17
  83. arguments.length < 2 ||
  84. (0, _devAssert.devAssert)(
  85. false,
  86. 'graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.',
  87. );
  88. const { schema, document, variableValues, rootValue } = args; // If arguments are missing or incorrect, throw an error.
  89. assertValidExecutionArguments(schema, document, variableValues); // If a valid execution context cannot be created due to incorrect arguments,
  90. // a "Response" with only errors is returned.
  91. const exeContext = buildExecutionContext(args); // Return early errors if execution context failed.
  92. if (!('schema' in exeContext)) {
  93. return {
  94. errors: exeContext,
  95. };
  96. } // Return a Promise that will eventually resolve to the data described by
  97. // The "Response" section of the GraphQL specification.
  98. //
  99. // If errors are encountered while executing a GraphQL field, only that
  100. // field and its descendants will be omitted, and sibling fields will still
  101. // be executed. An execution which encounters errors will still result in a
  102. // resolved Promise.
  103. //
  104. // Errors from sub-fields of a NonNull type may propagate to the top level,
  105. // at which point we still log the error and null the parent field, which
  106. // in this case is the entire response.
  107. try {
  108. const { operation } = exeContext;
  109. const result = executeOperation(exeContext, operation, rootValue);
  110. if ((0, _isPromise.isPromise)(result)) {
  111. return result.then(
  112. (data) => buildResponse(data, exeContext.errors),
  113. (error) => {
  114. exeContext.errors.push(error);
  115. return buildResponse(null, exeContext.errors);
  116. },
  117. );
  118. }
  119. return buildResponse(result, exeContext.errors);
  120. } catch (error) {
  121. exeContext.errors.push(error);
  122. return buildResponse(null, exeContext.errors);
  123. }
  124. }
  125. /**
  126. * Also implements the "Executing requests" section of the GraphQL specification.
  127. * However, it guarantees to complete synchronously (or throw an error) assuming
  128. * that all field resolvers are also synchronous.
  129. */
  130. function executeSync(args) {
  131. const result = execute(args); // Assert that the execution was synchronous.
  132. if ((0, _isPromise.isPromise)(result)) {
  133. throw new Error('GraphQL execution failed to complete synchronously.');
  134. }
  135. return result;
  136. }
  137. /**
  138. * Given a completed execution context and data, build the `{ errors, data }`
  139. * response defined by the "Response" section of the GraphQL specification.
  140. */
  141. function buildResponse(data, errors) {
  142. return errors.length === 0
  143. ? {
  144. data,
  145. }
  146. : {
  147. errors,
  148. data,
  149. };
  150. }
  151. /**
  152. * Essential assertions before executing to provide developer feedback for
  153. * improper use of the GraphQL library.
  154. *
  155. * @internal
  156. */
  157. function assertValidExecutionArguments(schema, document, rawVariableValues) {
  158. document || (0, _devAssert.devAssert)(false, 'Must provide document.'); // If the schema used for execution is invalid, throw an error.
  159. (0, _validate.assertValidSchema)(schema); // Variables, if provided, must be an object.
  160. rawVariableValues == null ||
  161. (0, _isObjectLike.isObjectLike)(rawVariableValues) ||
  162. (0, _devAssert.devAssert)(
  163. false,
  164. 'Variables must be provided as an Object where each property is a variable value. Perhaps look to see if an unparsed JSON string was provided.',
  165. );
  166. }
  167. /**
  168. * Constructs a ExecutionContext object from the arguments passed to
  169. * execute, which we will pass throughout the other execution methods.
  170. *
  171. * Throws a GraphQLError if a valid execution context cannot be created.
  172. *
  173. * @internal
  174. */
  175. function buildExecutionContext(args) {
  176. var _definition$name, _operation$variableDe;
  177. const {
  178. schema,
  179. document,
  180. rootValue,
  181. contextValue,
  182. variableValues: rawVariableValues,
  183. operationName,
  184. fieldResolver,
  185. typeResolver,
  186. subscribeFieldResolver,
  187. } = args;
  188. let operation;
  189. const fragments = Object.create(null);
  190. for (const definition of document.definitions) {
  191. switch (definition.kind) {
  192. case _kinds.Kind.OPERATION_DEFINITION:
  193. if (operationName == null) {
  194. if (operation !== undefined) {
  195. return [
  196. new _GraphQLError.GraphQLError(
  197. 'Must provide operation name if query contains multiple operations.',
  198. ),
  199. ];
  200. }
  201. operation = definition;
  202. } else if (
  203. ((_definition$name = definition.name) === null ||
  204. _definition$name === void 0
  205. ? void 0
  206. : _definition$name.value) === operationName
  207. ) {
  208. operation = definition;
  209. }
  210. break;
  211. case _kinds.Kind.FRAGMENT_DEFINITION:
  212. fragments[definition.name.value] = definition;
  213. break;
  214. default: // ignore non-executable definitions
  215. }
  216. }
  217. if (!operation) {
  218. if (operationName != null) {
  219. return [
  220. new _GraphQLError.GraphQLError(
  221. `Unknown operation named "${operationName}".`,
  222. ),
  223. ];
  224. }
  225. return [new _GraphQLError.GraphQLError('Must provide an operation.')];
  226. } // FIXME: https://github.com/graphql/graphql-js/issues/2203
  227. /* c8 ignore next */
  228. const variableDefinitions =
  229. (_operation$variableDe = operation.variableDefinitions) !== null &&
  230. _operation$variableDe !== void 0
  231. ? _operation$variableDe
  232. : [];
  233. const coercedVariableValues = (0, _values.getVariableValues)(
  234. schema,
  235. variableDefinitions,
  236. rawVariableValues !== null && rawVariableValues !== void 0
  237. ? rawVariableValues
  238. : {},
  239. {
  240. maxErrors: 50,
  241. },
  242. );
  243. if (coercedVariableValues.errors) {
  244. return coercedVariableValues.errors;
  245. }
  246. return {
  247. schema,
  248. fragments,
  249. rootValue,
  250. contextValue,
  251. operation,
  252. variableValues: coercedVariableValues.coerced,
  253. fieldResolver:
  254. fieldResolver !== null && fieldResolver !== void 0
  255. ? fieldResolver
  256. : defaultFieldResolver,
  257. typeResolver:
  258. typeResolver !== null && typeResolver !== void 0
  259. ? typeResolver
  260. : defaultTypeResolver,
  261. subscribeFieldResolver:
  262. subscribeFieldResolver !== null && subscribeFieldResolver !== void 0
  263. ? subscribeFieldResolver
  264. : defaultFieldResolver,
  265. errors: [],
  266. };
  267. }
  268. /**
  269. * Implements the "Executing operations" section of the spec.
  270. */
  271. function executeOperation(exeContext, operation, rootValue) {
  272. const rootType = exeContext.schema.getRootType(operation.operation);
  273. if (rootType == null) {
  274. throw new _GraphQLError.GraphQLError(
  275. `Schema is not configured to execute ${operation.operation} operation.`,
  276. {
  277. nodes: operation,
  278. },
  279. );
  280. }
  281. const rootFields = (0, _collectFields.collectFields)(
  282. exeContext.schema,
  283. exeContext.fragments,
  284. exeContext.variableValues,
  285. rootType,
  286. operation.selectionSet,
  287. );
  288. const path = undefined;
  289. switch (operation.operation) {
  290. case _ast.OperationTypeNode.QUERY:
  291. return executeFields(exeContext, rootType, rootValue, path, rootFields);
  292. case _ast.OperationTypeNode.MUTATION:
  293. return executeFieldsSerially(
  294. exeContext,
  295. rootType,
  296. rootValue,
  297. path,
  298. rootFields,
  299. );
  300. case _ast.OperationTypeNode.SUBSCRIPTION:
  301. // TODO: deprecate `subscribe` and move all logic here
  302. // Temporary solution until we finish merging execute and subscribe together
  303. return executeFields(exeContext, rootType, rootValue, path, rootFields);
  304. }
  305. }
  306. /**
  307. * Implements the "Executing selection sets" section of the spec
  308. * for fields that must be executed serially.
  309. */
  310. function executeFieldsSerially(
  311. exeContext,
  312. parentType,
  313. sourceValue,
  314. path,
  315. fields,
  316. ) {
  317. return (0, _promiseReduce.promiseReduce)(
  318. fields.entries(),
  319. (results, [responseName, fieldNodes]) => {
  320. const fieldPath = (0, _Path.addPath)(path, responseName, parentType.name);
  321. const result = executeField(
  322. exeContext,
  323. parentType,
  324. sourceValue,
  325. fieldNodes,
  326. fieldPath,
  327. );
  328. if (result === undefined) {
  329. return results;
  330. }
  331. if ((0, _isPromise.isPromise)(result)) {
  332. return result.then((resolvedResult) => {
  333. results[responseName] = resolvedResult;
  334. return results;
  335. });
  336. }
  337. results[responseName] = result;
  338. return results;
  339. },
  340. Object.create(null),
  341. );
  342. }
  343. /**
  344. * Implements the "Executing selection sets" section of the spec
  345. * for fields that may be executed in parallel.
  346. */
  347. function executeFields(exeContext, parentType, sourceValue, path, fields) {
  348. const results = Object.create(null);
  349. let containsPromise = false;
  350. try {
  351. for (const [responseName, fieldNodes] of fields.entries()) {
  352. const fieldPath = (0, _Path.addPath)(path, responseName, parentType.name);
  353. const result = executeField(
  354. exeContext,
  355. parentType,
  356. sourceValue,
  357. fieldNodes,
  358. fieldPath,
  359. );
  360. if (result !== undefined) {
  361. results[responseName] = result;
  362. if ((0, _isPromise.isPromise)(result)) {
  363. containsPromise = true;
  364. }
  365. }
  366. }
  367. } catch (error) {
  368. if (containsPromise) {
  369. // Ensure that any promises returned by other fields are handled, as they may also reject.
  370. return (0, _promiseForObject.promiseForObject)(results).finally(() => {
  371. throw error;
  372. });
  373. }
  374. throw error;
  375. } // If there are no promises, we can just return the object
  376. if (!containsPromise) {
  377. return results;
  378. } // Otherwise, results is a map from field name to the result of resolving that
  379. // field, which is possibly a promise. Return a promise that will return this
  380. // same map, but with any promises replaced with the values they resolved to.
  381. return (0, _promiseForObject.promiseForObject)(results);
  382. }
  383. /**
  384. * Implements the "Executing fields" section of the spec
  385. * In particular, this function figures out the value that the field returns by
  386. * calling its resolve function, then calls completeValue to complete promises,
  387. * serialize scalars, or execute the sub-selection-set for objects.
  388. */
  389. function executeField(exeContext, parentType, source, fieldNodes, path) {
  390. var _fieldDef$resolve;
  391. const fieldDef = getFieldDef(exeContext.schema, parentType, fieldNodes[0]);
  392. if (!fieldDef) {
  393. return;
  394. }
  395. const returnType = fieldDef.type;
  396. const resolveFn =
  397. (_fieldDef$resolve = fieldDef.resolve) !== null &&
  398. _fieldDef$resolve !== void 0
  399. ? _fieldDef$resolve
  400. : exeContext.fieldResolver;
  401. const info = buildResolveInfo(
  402. exeContext,
  403. fieldDef,
  404. fieldNodes,
  405. parentType,
  406. path,
  407. ); // Get the resolve function, regardless of if its result is normal or abrupt (error).
  408. try {
  409. // Build a JS object of arguments from the field.arguments AST, using the
  410. // variables scope to fulfill any variable references.
  411. // TODO: find a way to memoize, in case this field is within a List type.
  412. const args = (0, _values.getArgumentValues)(
  413. fieldDef,
  414. fieldNodes[0],
  415. exeContext.variableValues,
  416. ); // The resolve function's optional third argument is a context value that
  417. // is provided to every resolve function within an execution. It is commonly
  418. // used to represent an authenticated user, or request-specific caches.
  419. const contextValue = exeContext.contextValue;
  420. const result = resolveFn(source, args, contextValue, info);
  421. let completed;
  422. if ((0, _isPromise.isPromise)(result)) {
  423. completed = result.then((resolved) =>
  424. completeValue(exeContext, returnType, fieldNodes, info, path, resolved),
  425. );
  426. } else {
  427. completed = completeValue(
  428. exeContext,
  429. returnType,
  430. fieldNodes,
  431. info,
  432. path,
  433. result,
  434. );
  435. }
  436. if ((0, _isPromise.isPromise)(completed)) {
  437. // Note: we don't rely on a `catch` method, but we do expect "thenable"
  438. // to take a second callback for the error case.
  439. return completed.then(undefined, (rawError) => {
  440. const error = (0, _locatedError.locatedError)(
  441. rawError,
  442. fieldNodes,
  443. (0, _Path.pathToArray)(path),
  444. );
  445. return handleFieldError(error, returnType, exeContext);
  446. });
  447. }
  448. return completed;
  449. } catch (rawError) {
  450. const error = (0, _locatedError.locatedError)(
  451. rawError,
  452. fieldNodes,
  453. (0, _Path.pathToArray)(path),
  454. );
  455. return handleFieldError(error, returnType, exeContext);
  456. }
  457. }
  458. /**
  459. * @internal
  460. */
  461. function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) {
  462. // The resolve function's optional fourth argument is a collection of
  463. // information about the current execution state.
  464. return {
  465. fieldName: fieldDef.name,
  466. fieldNodes,
  467. returnType: fieldDef.type,
  468. parentType,
  469. path,
  470. schema: exeContext.schema,
  471. fragments: exeContext.fragments,
  472. rootValue: exeContext.rootValue,
  473. operation: exeContext.operation,
  474. variableValues: exeContext.variableValues,
  475. };
  476. }
  477. function handleFieldError(error, returnType, exeContext) {
  478. // If the field type is non-nullable, then it is resolved without any
  479. // protection from errors, however it still properly locates the error.
  480. if ((0, _definition.isNonNullType)(returnType)) {
  481. throw error;
  482. } // Otherwise, error protection is applied, logging the error and resolving
  483. // a null value for this field if one is encountered.
  484. exeContext.errors.push(error);
  485. return null;
  486. }
  487. /**
  488. * Implements the instructions for completeValue as defined in the
  489. * "Value Completion" section of the spec.
  490. *
  491. * If the field type is Non-Null, then this recursively completes the value
  492. * for the inner type. It throws a field error if that completion returns null,
  493. * as per the "Nullability" section of the spec.
  494. *
  495. * If the field type is a List, then this recursively completes the value
  496. * for the inner type on each item in the list.
  497. *
  498. * If the field type is a Scalar or Enum, ensures the completed value is a legal
  499. * value of the type by calling the `serialize` method of GraphQL type
  500. * definition.
  501. *
  502. * If the field is an abstract type, determine the runtime type of the value
  503. * and then complete based on that type
  504. *
  505. * Otherwise, the field type expects a sub-selection set, and will complete the
  506. * value by executing all sub-selections.
  507. */
  508. function completeValue(exeContext, returnType, fieldNodes, info, path, result) {
  509. // If result is an Error, throw a located error.
  510. if (result instanceof Error) {
  511. throw result;
  512. } // If field type is NonNull, complete for inner type, and throw field error
  513. // if result is null.
  514. if ((0, _definition.isNonNullType)(returnType)) {
  515. const completed = completeValue(
  516. exeContext,
  517. returnType.ofType,
  518. fieldNodes,
  519. info,
  520. path,
  521. result,
  522. );
  523. if (completed === null) {
  524. throw new Error(
  525. `Cannot return null for non-nullable field ${info.parentType.name}.${info.fieldName}.`,
  526. );
  527. }
  528. return completed;
  529. } // If result value is null or undefined then return null.
  530. if (result == null) {
  531. return null;
  532. } // If field type is List, complete each item in the list with the inner type
  533. if ((0, _definition.isListType)(returnType)) {
  534. return completeListValue(
  535. exeContext,
  536. returnType,
  537. fieldNodes,
  538. info,
  539. path,
  540. result,
  541. );
  542. } // If field type is a leaf type, Scalar or Enum, serialize to a valid value,
  543. // returning null if serialization is not possible.
  544. if ((0, _definition.isLeafType)(returnType)) {
  545. return completeLeafValue(returnType, result);
  546. } // If field type is an abstract type, Interface or Union, determine the
  547. // runtime Object type and complete for that type.
  548. if ((0, _definition.isAbstractType)(returnType)) {
  549. return completeAbstractValue(
  550. exeContext,
  551. returnType,
  552. fieldNodes,
  553. info,
  554. path,
  555. result,
  556. );
  557. } // If field type is Object, execute and complete all sub-selections.
  558. if ((0, _definition.isObjectType)(returnType)) {
  559. return completeObjectValue(
  560. exeContext,
  561. returnType,
  562. fieldNodes,
  563. info,
  564. path,
  565. result,
  566. );
  567. }
  568. /* c8 ignore next 6 */
  569. // Not reachable, all possible output types have been considered.
  570. false ||
  571. (0, _invariant.invariant)(
  572. false,
  573. 'Cannot complete value of unexpected output type: ' +
  574. (0, _inspect.inspect)(returnType),
  575. );
  576. }
  577. /**
  578. * Complete a list value by completing each item in the list with the
  579. * inner type
  580. */
  581. function completeListValue(
  582. exeContext,
  583. returnType,
  584. fieldNodes,
  585. info,
  586. path,
  587. result,
  588. ) {
  589. if (!(0, _isIterableObject.isIterableObject)(result)) {
  590. throw new _GraphQLError.GraphQLError(
  591. `Expected Iterable, but did not find one for field "${info.parentType.name}.${info.fieldName}".`,
  592. );
  593. } // This is specified as a simple map, however we're optimizing the path
  594. // where the list contains no Promises by avoiding creating another Promise.
  595. const itemType = returnType.ofType;
  596. let containsPromise = false;
  597. const completedResults = Array.from(result, (item, index) => {
  598. // No need to modify the info object containing the path,
  599. // since from here on it is not ever accessed by resolver functions.
  600. const itemPath = (0, _Path.addPath)(path, index, undefined);
  601. try {
  602. let completedItem;
  603. if ((0, _isPromise.isPromise)(item)) {
  604. completedItem = item.then((resolved) =>
  605. completeValue(
  606. exeContext,
  607. itemType,
  608. fieldNodes,
  609. info,
  610. itemPath,
  611. resolved,
  612. ),
  613. );
  614. } else {
  615. completedItem = completeValue(
  616. exeContext,
  617. itemType,
  618. fieldNodes,
  619. info,
  620. itemPath,
  621. item,
  622. );
  623. }
  624. if ((0, _isPromise.isPromise)(completedItem)) {
  625. containsPromise = true; // Note: we don't rely on a `catch` method, but we do expect "thenable"
  626. // to take a second callback for the error case.
  627. return completedItem.then(undefined, (rawError) => {
  628. const error = (0, _locatedError.locatedError)(
  629. rawError,
  630. fieldNodes,
  631. (0, _Path.pathToArray)(itemPath),
  632. );
  633. return handleFieldError(error, itemType, exeContext);
  634. });
  635. }
  636. return completedItem;
  637. } catch (rawError) {
  638. const error = (0, _locatedError.locatedError)(
  639. rawError,
  640. fieldNodes,
  641. (0, _Path.pathToArray)(itemPath),
  642. );
  643. return handleFieldError(error, itemType, exeContext);
  644. }
  645. });
  646. return containsPromise ? Promise.all(completedResults) : completedResults;
  647. }
  648. /**
  649. * Complete a Scalar or Enum by serializing to a valid value, returning
  650. * null if serialization is not possible.
  651. */
  652. function completeLeafValue(returnType, result) {
  653. const serializedResult = returnType.serialize(result);
  654. if (serializedResult == null) {
  655. throw new Error(
  656. `Expected \`${(0, _inspect.inspect)(returnType)}.serialize(${(0,
  657. _inspect.inspect)(result)})\` to ` +
  658. `return non-nullable value, returned: ${(0, _inspect.inspect)(
  659. serializedResult,
  660. )}`,
  661. );
  662. }
  663. return serializedResult;
  664. }
  665. /**
  666. * Complete a value of an abstract type by determining the runtime object type
  667. * of that value, then complete the value for that type.
  668. */
  669. function completeAbstractValue(
  670. exeContext,
  671. returnType,
  672. fieldNodes,
  673. info,
  674. path,
  675. result,
  676. ) {
  677. var _returnType$resolveTy;
  678. const resolveTypeFn =
  679. (_returnType$resolveTy = returnType.resolveType) !== null &&
  680. _returnType$resolveTy !== void 0
  681. ? _returnType$resolveTy
  682. : exeContext.typeResolver;
  683. const contextValue = exeContext.contextValue;
  684. const runtimeType = resolveTypeFn(result, contextValue, info, returnType);
  685. if ((0, _isPromise.isPromise)(runtimeType)) {
  686. return runtimeType.then((resolvedRuntimeType) =>
  687. completeObjectValue(
  688. exeContext,
  689. ensureValidRuntimeType(
  690. resolvedRuntimeType,
  691. exeContext,
  692. returnType,
  693. fieldNodes,
  694. info,
  695. result,
  696. ),
  697. fieldNodes,
  698. info,
  699. path,
  700. result,
  701. ),
  702. );
  703. }
  704. return completeObjectValue(
  705. exeContext,
  706. ensureValidRuntimeType(
  707. runtimeType,
  708. exeContext,
  709. returnType,
  710. fieldNodes,
  711. info,
  712. result,
  713. ),
  714. fieldNodes,
  715. info,
  716. path,
  717. result,
  718. );
  719. }
  720. function ensureValidRuntimeType(
  721. runtimeTypeName,
  722. exeContext,
  723. returnType,
  724. fieldNodes,
  725. info,
  726. result,
  727. ) {
  728. if (runtimeTypeName == null) {
  729. throw new _GraphQLError.GraphQLError(
  730. `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`,
  731. fieldNodes,
  732. );
  733. } // releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType`
  734. // TODO: remove in 17.0.0 release
  735. if ((0, _definition.isObjectType)(runtimeTypeName)) {
  736. throw new _GraphQLError.GraphQLError(
  737. 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.',
  738. );
  739. }
  740. if (typeof runtimeTypeName !== 'string') {
  741. throw new _GraphQLError.GraphQLError(
  742. `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}" with ` +
  743. `value ${(0, _inspect.inspect)(result)}, received "${(0,
  744. _inspect.inspect)(runtimeTypeName)}".`,
  745. );
  746. }
  747. const runtimeType = exeContext.schema.getType(runtimeTypeName);
  748. if (runtimeType == null) {
  749. throw new _GraphQLError.GraphQLError(
  750. `Abstract type "${returnType.name}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`,
  751. {
  752. nodes: fieldNodes,
  753. },
  754. );
  755. }
  756. if (!(0, _definition.isObjectType)(runtimeType)) {
  757. throw new _GraphQLError.GraphQLError(
  758. `Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeTypeName}".`,
  759. {
  760. nodes: fieldNodes,
  761. },
  762. );
  763. }
  764. if (!exeContext.schema.isSubType(returnType, runtimeType)) {
  765. throw new _GraphQLError.GraphQLError(
  766. `Runtime Object type "${runtimeType.name}" is not a possible type for "${returnType.name}".`,
  767. {
  768. nodes: fieldNodes,
  769. },
  770. );
  771. }
  772. return runtimeType;
  773. }
  774. /**
  775. * Complete an Object value by executing all sub-selections.
  776. */
  777. function completeObjectValue(
  778. exeContext,
  779. returnType,
  780. fieldNodes,
  781. info,
  782. path,
  783. result,
  784. ) {
  785. // Collect sub-fields to execute to complete this value.
  786. const subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes); // If there is an isTypeOf predicate function, call it with the
  787. // current result. If isTypeOf returns false, then raise an error rather
  788. // than continuing execution.
  789. if (returnType.isTypeOf) {
  790. const isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info);
  791. if ((0, _isPromise.isPromise)(isTypeOf)) {
  792. return isTypeOf.then((resolvedIsTypeOf) => {
  793. if (!resolvedIsTypeOf) {
  794. throw invalidReturnTypeError(returnType, result, fieldNodes);
  795. }
  796. return executeFields(
  797. exeContext,
  798. returnType,
  799. result,
  800. path,
  801. subFieldNodes,
  802. );
  803. });
  804. }
  805. if (!isTypeOf) {
  806. throw invalidReturnTypeError(returnType, result, fieldNodes);
  807. }
  808. }
  809. return executeFields(exeContext, returnType, result, path, subFieldNodes);
  810. }
  811. function invalidReturnTypeError(returnType, result, fieldNodes) {
  812. return new _GraphQLError.GraphQLError(
  813. `Expected value of type "${returnType.name}" but got: ${(0,
  814. _inspect.inspect)(result)}.`,
  815. {
  816. nodes: fieldNodes,
  817. },
  818. );
  819. }
  820. /**
  821. * If a resolveType function is not given, then a default resolve behavior is
  822. * used which attempts two strategies:
  823. *
  824. * First, See if the provided value has a `__typename` field defined, if so, use
  825. * that value as name of the resolved type.
  826. *
  827. * Otherwise, test each possible type for the abstract type by calling
  828. * isTypeOf for the object being coerced, returning the first type that matches.
  829. */
  830. const defaultTypeResolver = function (value, contextValue, info, abstractType) {
  831. // First, look for `__typename`.
  832. if (
  833. (0, _isObjectLike.isObjectLike)(value) &&
  834. typeof value.__typename === 'string'
  835. ) {
  836. return value.__typename;
  837. } // Otherwise, test each possible type.
  838. const possibleTypes = info.schema.getPossibleTypes(abstractType);
  839. const promisedIsTypeOfResults = [];
  840. for (let i = 0; i < possibleTypes.length; i++) {
  841. const type = possibleTypes[i];
  842. if (type.isTypeOf) {
  843. const isTypeOfResult = type.isTypeOf(value, contextValue, info);
  844. if ((0, _isPromise.isPromise)(isTypeOfResult)) {
  845. promisedIsTypeOfResults[i] = isTypeOfResult;
  846. } else if (isTypeOfResult) {
  847. return type.name;
  848. }
  849. }
  850. }
  851. if (promisedIsTypeOfResults.length) {
  852. return Promise.all(promisedIsTypeOfResults).then((isTypeOfResults) => {
  853. for (let i = 0; i < isTypeOfResults.length; i++) {
  854. if (isTypeOfResults[i]) {
  855. return possibleTypes[i].name;
  856. }
  857. }
  858. });
  859. }
  860. };
  861. /**
  862. * If a resolve function is not given, then a default resolve behavior is used
  863. * which takes the property of the source object of the same name as the field
  864. * and returns it as the result, or if it's a function, returns the result
  865. * of calling that function while passing along args and context value.
  866. */
  867. exports.defaultTypeResolver = defaultTypeResolver;
  868. const defaultFieldResolver = function (source, args, contextValue, info) {
  869. // ensure source is a value for which property access is acceptable.
  870. if ((0, _isObjectLike.isObjectLike)(source) || typeof source === 'function') {
  871. const property = source[info.fieldName];
  872. if (typeof property === 'function') {
  873. return source[info.fieldName](args, contextValue, info);
  874. }
  875. return property;
  876. }
  877. };
  878. /**
  879. * This method looks up the field on the given type definition.
  880. * It has special casing for the three introspection fields,
  881. * __schema, __type and __typename. __typename is special because
  882. * it can always be queried as a field, even in situations where no
  883. * other fields are allowed, like on a Union. __schema and __type
  884. * could get automatically added to the query type, but that would
  885. * require mutating type definitions, which would cause issues.
  886. *
  887. * @internal
  888. */
  889. exports.defaultFieldResolver = defaultFieldResolver;
  890. function getFieldDef(schema, parentType, fieldNode) {
  891. const fieldName = fieldNode.name.value;
  892. if (
  893. fieldName === _introspection.SchemaMetaFieldDef.name &&
  894. schema.getQueryType() === parentType
  895. ) {
  896. return _introspection.SchemaMetaFieldDef;
  897. } else if (
  898. fieldName === _introspection.TypeMetaFieldDef.name &&
  899. schema.getQueryType() === parentType
  900. ) {
  901. return _introspection.TypeMetaFieldDef;
  902. } else if (fieldName === _introspection.TypeNameMetaFieldDef.name) {
  903. return _introspection.TypeNameMetaFieldDef;
  904. }
  905. return parentType.getFields()[fieldName];
  906. }