@depup/apollo__server 5.5.0-depup.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.
Files changed (557) hide show
  1. package/README.md +40 -0
  2. package/changes.json +46 -0
  3. package/dist/cjs/ApolloServer.d.ts +126 -0
  4. package/dist/cjs/ApolloServer.d.ts.map +1 -0
  5. package/dist/cjs/ApolloServer.js +726 -0
  6. package/dist/cjs/ApolloServer.js.map +1 -0
  7. package/dist/cjs/cachePolicy.d.ts +3 -0
  8. package/dist/cjs/cachePolicy.d.ts.map +1 -0
  9. package/dist/cjs/cachePolicy.js +33 -0
  10. package/dist/cjs/cachePolicy.js.map +1 -0
  11. package/dist/cjs/determineApolloConfig.d.ts +4 -0
  12. package/dist/cjs/determineApolloConfig.d.ts.map +1 -0
  13. package/dist/cjs/determineApolloConfig.js +58 -0
  14. package/dist/cjs/determineApolloConfig.js.map +1 -0
  15. package/dist/cjs/errorNormalize.d.ts +12 -0
  16. package/dist/cjs/errorNormalize.d.ts.map +1 -0
  17. package/dist/cjs/errorNormalize.js +71 -0
  18. package/dist/cjs/errorNormalize.js.map +1 -0
  19. package/dist/cjs/errors/index.d.ts +16 -0
  20. package/dist/cjs/errors/index.d.ts.map +1 -0
  21. package/dist/cjs/errors/index.js +28 -0
  22. package/dist/cjs/errors/index.js.map +1 -0
  23. package/dist/cjs/externalTypes/constructor.d.ts +78 -0
  24. package/dist/cjs/externalTypes/constructor.d.ts.map +1 -0
  25. package/dist/cjs/externalTypes/constructor.js +3 -0
  26. package/dist/cjs/externalTypes/constructor.js.map +1 -0
  27. package/dist/cjs/externalTypes/context.d.ts +4 -0
  28. package/dist/cjs/externalTypes/context.d.ts.map +1 -0
  29. package/dist/cjs/externalTypes/context.js +3 -0
  30. package/dist/cjs/externalTypes/context.js.map +1 -0
  31. package/dist/cjs/externalTypes/graphql.d.ts +41 -0
  32. package/dist/cjs/externalTypes/graphql.d.ts.map +1 -0
  33. package/dist/cjs/externalTypes/graphql.js +3 -0
  34. package/dist/cjs/externalTypes/graphql.js.map +1 -0
  35. package/dist/cjs/externalTypes/http.d.ts +22 -0
  36. package/dist/cjs/externalTypes/http.d.ts.map +1 -0
  37. package/dist/cjs/externalTypes/http.js +3 -0
  38. package/dist/cjs/externalTypes/http.js.map +1 -0
  39. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts +28 -0
  40. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts.map +1 -0
  41. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.js +3 -0
  42. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.js.map +1 -0
  43. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts +43 -0
  44. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts.map +1 -0
  45. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.js +3 -0
  46. package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.js.map +1 -0
  47. package/dist/cjs/externalTypes/index.d.ts +9 -0
  48. package/dist/cjs/externalTypes/index.d.ts.map +1 -0
  49. package/dist/cjs/externalTypes/index.js +3 -0
  50. package/dist/cjs/externalTypes/index.js.map +1 -0
  51. package/dist/cjs/externalTypes/plugins.d.ts +75 -0
  52. package/dist/cjs/externalTypes/plugins.d.ts.map +1 -0
  53. package/dist/cjs/externalTypes/plugins.js +3 -0
  54. package/dist/cjs/externalTypes/plugins.js.map +1 -0
  55. package/dist/cjs/externalTypes/requestPipeline.d.ts +50 -0
  56. package/dist/cjs/externalTypes/requestPipeline.d.ts.map +1 -0
  57. package/dist/cjs/externalTypes/requestPipeline.js +3 -0
  58. package/dist/cjs/externalTypes/requestPipeline.js.map +1 -0
  59. package/dist/cjs/generated/packageVersion.d.ts +2 -0
  60. package/dist/cjs/generated/packageVersion.d.ts.map +1 -0
  61. package/dist/cjs/generated/packageVersion.js +5 -0
  62. package/dist/cjs/generated/packageVersion.js.map +1 -0
  63. package/dist/cjs/httpBatching.d.ts +4 -0
  64. package/dist/cjs/httpBatching.d.ts.map +1 -0
  65. package/dist/cjs/httpBatching.js +58 -0
  66. package/dist/cjs/httpBatching.js.map +1 -0
  67. package/dist/cjs/incrementalDeliveryPolyfill.d.ts +82 -0
  68. package/dist/cjs/incrementalDeliveryPolyfill.d.ts.map +1 -0
  69. package/dist/cjs/incrementalDeliveryPolyfill.js +74 -0
  70. package/dist/cjs/incrementalDeliveryPolyfill.js.map +1 -0
  71. package/dist/cjs/index.d.ts +4 -0
  72. package/dist/cjs/index.d.ts.map +1 -0
  73. package/dist/cjs/index.js +23 -0
  74. package/dist/cjs/index.js.map +1 -0
  75. package/dist/cjs/internalErrorClasses.d.ts +28 -0
  76. package/dist/cjs/internalErrorClasses.d.ts.map +1 -0
  77. package/dist/cjs/internalErrorClasses.js +91 -0
  78. package/dist/cjs/internalErrorClasses.js.map +1 -0
  79. package/dist/cjs/internalPlugin.d.ts +9 -0
  80. package/dist/cjs/internalPlugin.d.ts.map +1 -0
  81. package/dist/cjs/internalPlugin.js +11 -0
  82. package/dist/cjs/internalPlugin.js.map +1 -0
  83. package/dist/cjs/package.json +1 -0
  84. package/dist/cjs/plugin/cacheControl/index.d.ts +9 -0
  85. package/dist/cjs/plugin/cacheControl/index.d.ts.map +1 -0
  86. package/dist/cjs/plugin/cacheControl/index.js +223 -0
  87. package/dist/cjs/plugin/cacheControl/index.js.map +1 -0
  88. package/dist/cjs/plugin/disableSuggestions/index.d.ts +3 -0
  89. package/dist/cjs/plugin/disableSuggestions/index.d.ts.map +1 -0
  90. package/dist/cjs/plugin/disableSuggestions/index.js +22 -0
  91. package/dist/cjs/plugin/disableSuggestions/index.js.map +1 -0
  92. package/dist/cjs/plugin/disabled/index.d.ts +7 -0
  93. package/dist/cjs/plugin/disabled/index.d.ts.map +1 -0
  94. package/dist/cjs/plugin/disabled/index.js +30 -0
  95. package/dist/cjs/plugin/disabled/index.js.map +1 -0
  96. package/dist/cjs/plugin/drainHttpServer/index.d.ts +8 -0
  97. package/dist/cjs/plugin/drainHttpServer/index.d.ts.map +1 -0
  98. package/dist/cjs/plugin/drainHttpServer/index.js +19 -0
  99. package/dist/cjs/plugin/drainHttpServer/index.js.map +1 -0
  100. package/dist/cjs/plugin/drainHttpServer/stoppable.d.ts +10 -0
  101. package/dist/cjs/plugin/drainHttpServer/stoppable.d.ts.map +1 -0
  102. package/dist/cjs/plugin/drainHttpServer/stoppable.js +54 -0
  103. package/dist/cjs/plugin/drainHttpServer/stoppable.js.map +1 -0
  104. package/dist/cjs/plugin/inlineTrace/index.d.ts +8 -0
  105. package/dist/cjs/plugin/inlineTrace/index.d.ts.map +1 -0
  106. package/dist/cjs/plugin/inlineTrace/index.js +70 -0
  107. package/dist/cjs/plugin/inlineTrace/index.js.map +1 -0
  108. package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.d.ts +4 -0
  109. package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.d.ts.map +1 -0
  110. package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.js +143 -0
  111. package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.js.map +1 -0
  112. package/dist/cjs/plugin/landingPage/default/index.d.ts +9 -0
  113. package/dist/cjs/plugin/landingPage/default/index.d.ts.map +1 -0
  114. package/dist/cjs/plugin/landingPage/default/index.js +146 -0
  115. package/dist/cjs/plugin/landingPage/default/index.js.map +1 -0
  116. package/dist/cjs/plugin/landingPage/default/types.d.ts +56 -0
  117. package/dist/cjs/plugin/landingPage/default/types.d.ts.map +1 -0
  118. package/dist/cjs/plugin/landingPage/default/types.js +3 -0
  119. package/dist/cjs/plugin/landingPage/default/types.js.map +1 -0
  120. package/dist/cjs/plugin/schemaIsSubgraph.d.ts +3 -0
  121. package/dist/cjs/plugin/schemaIsSubgraph.d.ts.map +1 -0
  122. package/dist/cjs/plugin/schemaIsSubgraph.js +23 -0
  123. package/dist/cjs/plugin/schemaIsSubgraph.js.map +1 -0
  124. package/dist/cjs/plugin/schemaReporting/index.d.ts +10 -0
  125. package/dist/cjs/plugin/schemaReporting/index.d.ts.map +1 -0
  126. package/dist/cjs/plugin/schemaReporting/index.js +104 -0
  127. package/dist/cjs/plugin/schemaReporting/index.js.map +1 -0
  128. package/dist/cjs/plugin/schemaReporting/schemaReporter.d.ts +33 -0
  129. package/dist/cjs/plugin/schemaReporting/schemaReporter.d.ts.map +1 -0
  130. package/dist/cjs/plugin/schemaReporting/schemaReporter.js +147 -0
  131. package/dist/cjs/plugin/schemaReporting/schemaReporter.js.map +1 -0
  132. package/dist/cjs/plugin/subscriptionCallback/index.d.ts +12 -0
  133. package/dist/cjs/plugin/subscriptionCallback/index.d.ts.map +1 -0
  134. package/dist/cjs/plugin/subscriptionCallback/index.js +434 -0
  135. package/dist/cjs/plugin/subscriptionCallback/index.js.map +1 -0
  136. package/dist/cjs/plugin/traceTreeBuilder.d.ts +25 -0
  137. package/dist/cjs/plugin/traceTreeBuilder.d.ts.map +1 -0
  138. package/dist/cjs/plugin/traceTreeBuilder.js +201 -0
  139. package/dist/cjs/plugin/traceTreeBuilder.js.map +1 -0
  140. package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts +3 -0
  141. package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts.map +1 -0
  142. package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.js +44 -0
  143. package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.js.map +1 -0
  144. package/dist/cjs/plugin/usageReporting/durationHistogram.d.ts +16 -0
  145. package/dist/cjs/plugin/usageReporting/durationHistogram.d.ts.map +1 -0
  146. package/dist/cjs/plugin/usageReporting/durationHistogram.js +68 -0
  147. package/dist/cjs/plugin/usageReporting/durationHistogram.js.map +1 -0
  148. package/dist/cjs/plugin/usageReporting/index.d.ts +3 -0
  149. package/dist/cjs/plugin/usageReporting/index.d.ts.map +1 -0
  150. package/dist/cjs/plugin/usageReporting/index.js +6 -0
  151. package/dist/cjs/plugin/usageReporting/index.js.map +1 -0
  152. package/dist/cjs/plugin/usageReporting/iterateOverTrace.d.ts +7 -0
  153. package/dist/cjs/plugin/usageReporting/iterateOverTrace.d.ts.map +1 -0
  154. package/dist/cjs/plugin/usageReporting/iterateOverTrace.js +81 -0
  155. package/dist/cjs/plugin/usageReporting/iterateOverTrace.js.map +1 -0
  156. package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.d.ts +12 -0
  157. package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.d.ts.map +1 -0
  158. package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.js +33 -0
  159. package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.js.map +1 -0
  160. package/dist/cjs/plugin/usageReporting/options.d.ts +60 -0
  161. package/dist/cjs/plugin/usageReporting/options.d.ts.map +1 -0
  162. package/dist/cjs/plugin/usageReporting/options.js +3 -0
  163. package/dist/cjs/plugin/usageReporting/options.js.map +1 -0
  164. package/dist/cjs/plugin/usageReporting/plugin.d.ts +7 -0
  165. package/dist/cjs/plugin/usageReporting/plugin.d.ts.map +1 -0
  166. package/dist/cjs/plugin/usageReporting/plugin.js +494 -0
  167. package/dist/cjs/plugin/usageReporting/plugin.js.map +1 -0
  168. package/dist/cjs/plugin/usageReporting/stats.d.ts +96 -0
  169. package/dist/cjs/plugin/usageReporting/stats.d.ts.map +1 -0
  170. package/dist/cjs/plugin/usageReporting/stats.js +289 -0
  171. package/dist/cjs/plugin/usageReporting/stats.js.map +1 -0
  172. package/dist/cjs/plugin/usageReporting/traceDetails.d.ts +4 -0
  173. package/dist/cjs/plugin/usageReporting/traceDetails.d.ts.map +1 -0
  174. package/dist/cjs/plugin/usageReporting/traceDetails.js +63 -0
  175. package/dist/cjs/plugin/usageReporting/traceDetails.js.map +1 -0
  176. package/dist/cjs/preventCsrf.d.ts +4 -0
  177. package/dist/cjs/preventCsrf.d.ts.map +1 -0
  178. package/dist/cjs/preventCsrf.js +41 -0
  179. package/dist/cjs/preventCsrf.js.map +1 -0
  180. package/dist/cjs/requestPipeline.d.ts +9 -0
  181. package/dist/cjs/requestPipeline.d.ts.map +1 -0
  182. package/dist/cjs/requestPipeline.js +371 -0
  183. package/dist/cjs/requestPipeline.js.map +1 -0
  184. package/dist/cjs/runHttpQuery.d.ts +15 -0
  185. package/dist/cjs/runHttpQuery.d.ts.map +1 -0
  186. package/dist/cjs/runHttpQuery.js +230 -0
  187. package/dist/cjs/runHttpQuery.js.map +1 -0
  188. package/dist/cjs/standalone/index.d.ts +25 -0
  189. package/dist/cjs/standalone/index.d.ts.map +1 -0
  190. package/dist/cjs/standalone/index.js +97 -0
  191. package/dist/cjs/standalone/index.js.map +1 -0
  192. package/dist/cjs/utils/HeaderMap.d.ts +8 -0
  193. package/dist/cjs/utils/HeaderMap.d.ts.map +1 -0
  194. package/dist/cjs/utils/HeaderMap.js +20 -0
  195. package/dist/cjs/utils/HeaderMap.js.map +1 -0
  196. package/dist/cjs/utils/UnreachableCaseError.d.ts +4 -0
  197. package/dist/cjs/utils/UnreachableCaseError.d.ts.map +1 -0
  198. package/dist/cjs/utils/UnreachableCaseError.js +10 -0
  199. package/dist/cjs/utils/UnreachableCaseError.js.map +1 -0
  200. package/dist/cjs/utils/computeCoreSchemaHash.d.ts +2 -0
  201. package/dist/cjs/utils/computeCoreSchemaHash.d.ts.map +1 -0
  202. package/dist/cjs/utils/computeCoreSchemaHash.js +8 -0
  203. package/dist/cjs/utils/computeCoreSchemaHash.js.map +1 -0
  204. package/dist/cjs/utils/invokeHooks.d.ts +7 -0
  205. package/dist/cjs/utils/invokeHooks.d.ts.map +1 -0
  206. package/dist/cjs/utils/invokeHooks.js +36 -0
  207. package/dist/cjs/utils/invokeHooks.js.map +1 -0
  208. package/dist/cjs/utils/isDefined.d.ts +2 -0
  209. package/dist/cjs/utils/isDefined.d.ts.map +1 -0
  210. package/dist/cjs/utils/isDefined.js +7 -0
  211. package/dist/cjs/utils/isDefined.js.map +1 -0
  212. package/dist/cjs/utils/makeGatewayGraphQLRequestContext.d.ts +5 -0
  213. package/dist/cjs/utils/makeGatewayGraphQLRequestContext.d.ts.map +1 -0
  214. package/dist/cjs/utils/makeGatewayGraphQLRequestContext.js +96 -0
  215. package/dist/cjs/utils/makeGatewayGraphQLRequestContext.js.map +1 -0
  216. package/dist/cjs/utils/resolvable.d.ts +7 -0
  217. package/dist/cjs/utils/resolvable.d.ts.map +1 -0
  218. package/dist/cjs/utils/resolvable.js +14 -0
  219. package/dist/cjs/utils/resolvable.js.map +1 -0
  220. package/dist/cjs/utils/schemaInstrumentation.d.ts +16 -0
  221. package/dist/cjs/utils/schemaInstrumentation.d.ts.map +1 -0
  222. package/dist/cjs/utils/schemaInstrumentation.js +75 -0
  223. package/dist/cjs/utils/schemaInstrumentation.js.map +1 -0
  224. package/dist/cjs/utils/schemaManager.d.ts +31 -0
  225. package/dist/cjs/utils/schemaManager.d.ts.map +1 -0
  226. package/dist/cjs/utils/schemaManager.js +103 -0
  227. package/dist/cjs/utils/schemaManager.js.map +1 -0
  228. package/dist/cjs/utils/urlForHttpServer.d.ts +3 -0
  229. package/dist/cjs/utils/urlForHttpServer.d.ts.map +1 -0
  230. package/dist/cjs/utils/urlForHttpServer.js +15 -0
  231. package/dist/cjs/utils/urlForHttpServer.js.map +1 -0
  232. package/dist/cjs/validationRules/NoIntrospection.d.ts +3 -0
  233. package/dist/cjs/validationRules/NoIntrospection.d.ts.map +1 -0
  234. package/dist/cjs/validationRules/NoIntrospection.js +19 -0
  235. package/dist/cjs/validationRules/NoIntrospection.js.map +1 -0
  236. package/dist/cjs/validationRules/RecursiveSelectionsLimit.d.ts +4 -0
  237. package/dist/cjs/validationRules/RecursiveSelectionsLimit.d.ts.map +1 -0
  238. package/dist/cjs/validationRules/RecursiveSelectionsLimit.js +150 -0
  239. package/dist/cjs/validationRules/RecursiveSelectionsLimit.js.map +1 -0
  240. package/dist/cjs/validationRules/index.d.ts +3 -0
  241. package/dist/cjs/validationRules/index.d.ts.map +1 -0
  242. package/dist/cjs/validationRules/index.js +9 -0
  243. package/dist/cjs/validationRules/index.js.map +1 -0
  244. package/dist/esm/ApolloServer.d.ts +126 -0
  245. package/dist/esm/ApolloServer.d.ts.map +1 -0
  246. package/dist/esm/ApolloServer.js +683 -0
  247. package/dist/esm/ApolloServer.js.map +1 -0
  248. package/dist/esm/cachePolicy.d.ts +3 -0
  249. package/dist/esm/cachePolicy.d.ts.map +1 -0
  250. package/dist/esm/cachePolicy.js +30 -0
  251. package/dist/esm/cachePolicy.js.map +1 -0
  252. package/dist/esm/determineApolloConfig.d.ts +4 -0
  253. package/dist/esm/determineApolloConfig.d.ts.map +1 -0
  254. package/dist/esm/determineApolloConfig.js +55 -0
  255. package/dist/esm/determineApolloConfig.js.map +1 -0
  256. package/dist/esm/errorNormalize.d.ts +12 -0
  257. package/dist/esm/errorNormalize.d.ts.map +1 -0
  258. package/dist/esm/errorNormalize.js +66 -0
  259. package/dist/esm/errorNormalize.js.map +1 -0
  260. package/dist/esm/errors/index.d.ts +16 -0
  261. package/dist/esm/errors/index.d.ts.map +1 -0
  262. package/dist/esm/errors/index.js +24 -0
  263. package/dist/esm/errors/index.js.map +1 -0
  264. package/dist/esm/externalTypes/constructor.d.ts +78 -0
  265. package/dist/esm/externalTypes/constructor.d.ts.map +1 -0
  266. package/dist/esm/externalTypes/constructor.js +2 -0
  267. package/dist/esm/externalTypes/constructor.js.map +1 -0
  268. package/dist/esm/externalTypes/context.d.ts +4 -0
  269. package/dist/esm/externalTypes/context.d.ts.map +1 -0
  270. package/dist/esm/externalTypes/context.js +2 -0
  271. package/dist/esm/externalTypes/context.js.map +1 -0
  272. package/dist/esm/externalTypes/graphql.d.ts +41 -0
  273. package/dist/esm/externalTypes/graphql.d.ts.map +1 -0
  274. package/dist/esm/externalTypes/graphql.js +2 -0
  275. package/dist/esm/externalTypes/graphql.js.map +1 -0
  276. package/dist/esm/externalTypes/http.d.ts +22 -0
  277. package/dist/esm/externalTypes/http.d.ts.map +1 -0
  278. package/dist/esm/externalTypes/http.js +2 -0
  279. package/dist/esm/externalTypes/http.js.map +1 -0
  280. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts +28 -0
  281. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts.map +1 -0
  282. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.js +2 -0
  283. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.js.map +1 -0
  284. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts +43 -0
  285. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts.map +1 -0
  286. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.js +2 -0
  287. package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.js.map +1 -0
  288. package/dist/esm/externalTypes/index.d.ts +9 -0
  289. package/dist/esm/externalTypes/index.d.ts.map +1 -0
  290. package/dist/esm/externalTypes/index.js +2 -0
  291. package/dist/esm/externalTypes/index.js.map +1 -0
  292. package/dist/esm/externalTypes/plugins.d.ts +75 -0
  293. package/dist/esm/externalTypes/plugins.d.ts.map +1 -0
  294. package/dist/esm/externalTypes/plugins.js +2 -0
  295. package/dist/esm/externalTypes/plugins.js.map +1 -0
  296. package/dist/esm/externalTypes/requestPipeline.d.ts +50 -0
  297. package/dist/esm/externalTypes/requestPipeline.d.ts.map +1 -0
  298. package/dist/esm/externalTypes/requestPipeline.js +2 -0
  299. package/dist/esm/externalTypes/requestPipeline.js.map +1 -0
  300. package/dist/esm/generated/packageVersion.d.ts +2 -0
  301. package/dist/esm/generated/packageVersion.d.ts.map +1 -0
  302. package/dist/esm/generated/packageVersion.js +2 -0
  303. package/dist/esm/generated/packageVersion.js.map +1 -0
  304. package/dist/esm/httpBatching.d.ts +4 -0
  305. package/dist/esm/httpBatching.d.ts.map +1 -0
  306. package/dist/esm/httpBatching.js +55 -0
  307. package/dist/esm/httpBatching.js.map +1 -0
  308. package/dist/esm/incrementalDeliveryPolyfill.d.ts +82 -0
  309. package/dist/esm/incrementalDeliveryPolyfill.d.ts.map +1 -0
  310. package/dist/esm/incrementalDeliveryPolyfill.js +38 -0
  311. package/dist/esm/incrementalDeliveryPolyfill.js.map +1 -0
  312. package/dist/esm/index.d.ts +4 -0
  313. package/dist/esm/index.d.ts.map +1 -0
  314. package/dist/esm/index.js +4 -0
  315. package/dist/esm/index.js.map +1 -0
  316. package/dist/esm/internalErrorClasses.d.ts +28 -0
  317. package/dist/esm/internalErrorClasses.d.ts.map +1 -0
  318. package/dist/esm/internalErrorClasses.js +81 -0
  319. package/dist/esm/internalErrorClasses.js.map +1 -0
  320. package/dist/esm/internalPlugin.d.ts +9 -0
  321. package/dist/esm/internalPlugin.d.ts.map +1 -0
  322. package/dist/esm/internalPlugin.js +7 -0
  323. package/dist/esm/internalPlugin.js.map +1 -0
  324. package/dist/esm/package.json +1 -0
  325. package/dist/esm/plugin/cacheControl/index.d.ts +9 -0
  326. package/dist/esm/plugin/cacheControl/index.d.ts.map +1 -0
  327. package/dist/esm/plugin/cacheControl/index.js +220 -0
  328. package/dist/esm/plugin/cacheControl/index.js.map +1 -0
  329. package/dist/esm/plugin/disableSuggestions/index.d.ts +3 -0
  330. package/dist/esm/plugin/disableSuggestions/index.d.ts.map +1 -0
  331. package/dist/esm/plugin/disableSuggestions/index.js +19 -0
  332. package/dist/esm/plugin/disableSuggestions/index.js.map +1 -0
  333. package/dist/esm/plugin/disabled/index.d.ts +7 -0
  334. package/dist/esm/plugin/disabled/index.d.ts.map +1 -0
  335. package/dist/esm/plugin/disabled/index.js +23 -0
  336. package/dist/esm/plugin/disabled/index.js.map +1 -0
  337. package/dist/esm/plugin/drainHttpServer/index.d.ts +8 -0
  338. package/dist/esm/plugin/drainHttpServer/index.d.ts.map +1 -0
  339. package/dist/esm/plugin/drainHttpServer/index.js +16 -0
  340. package/dist/esm/plugin/drainHttpServer/index.js.map +1 -0
  341. package/dist/esm/plugin/drainHttpServer/stoppable.d.ts +10 -0
  342. package/dist/esm/plugin/drainHttpServer/stoppable.d.ts.map +1 -0
  343. package/dist/esm/plugin/drainHttpServer/stoppable.js +47 -0
  344. package/dist/esm/plugin/drainHttpServer/stoppable.js.map +1 -0
  345. package/dist/esm/plugin/inlineTrace/index.d.ts +8 -0
  346. package/dist/esm/plugin/inlineTrace/index.d.ts.map +1 -0
  347. package/dist/esm/plugin/inlineTrace/index.js +67 -0
  348. package/dist/esm/plugin/inlineTrace/index.js.map +1 -0
  349. package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.d.ts +4 -0
  350. package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.d.ts.map +1 -0
  351. package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.js +138 -0
  352. package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.js.map +1 -0
  353. package/dist/esm/plugin/landingPage/default/index.d.ts +9 -0
  354. package/dist/esm/plugin/landingPage/default/index.d.ts.map +1 -0
  355. package/dist/esm/plugin/landingPage/default/index.js +141 -0
  356. package/dist/esm/plugin/landingPage/default/index.js.map +1 -0
  357. package/dist/esm/plugin/landingPage/default/types.d.ts +56 -0
  358. package/dist/esm/plugin/landingPage/default/types.d.ts.map +1 -0
  359. package/dist/esm/plugin/landingPage/default/types.js +2 -0
  360. package/dist/esm/plugin/landingPage/default/types.js.map +1 -0
  361. package/dist/esm/plugin/schemaIsSubgraph.d.ts +3 -0
  362. package/dist/esm/plugin/schemaIsSubgraph.d.ts.map +1 -0
  363. package/dist/esm/plugin/schemaIsSubgraph.js +20 -0
  364. package/dist/esm/plugin/schemaIsSubgraph.js.map +1 -0
  365. package/dist/esm/plugin/schemaReporting/index.d.ts +10 -0
  366. package/dist/esm/plugin/schemaReporting/index.d.ts.map +1 -0
  367. package/dist/esm/plugin/schemaReporting/index.js +98 -0
  368. package/dist/esm/plugin/schemaReporting/index.js.map +1 -0
  369. package/dist/esm/plugin/schemaReporting/schemaReporter.d.ts +33 -0
  370. package/dist/esm/plugin/schemaReporting/schemaReporter.d.ts.map +1 -0
  371. package/dist/esm/plugin/schemaReporting/schemaReporter.js +143 -0
  372. package/dist/esm/plugin/schemaReporting/schemaReporter.js.map +1 -0
  373. package/dist/esm/plugin/subscriptionCallback/index.d.ts +12 -0
  374. package/dist/esm/plugin/subscriptionCallback/index.d.ts.map +1 -0
  375. package/dist/esm/plugin/subscriptionCallback/index.js +428 -0
  376. package/dist/esm/plugin/subscriptionCallback/index.js.map +1 -0
  377. package/dist/esm/plugin/traceTreeBuilder.d.ts +25 -0
  378. package/dist/esm/plugin/traceTreeBuilder.d.ts.map +1 -0
  379. package/dist/esm/plugin/traceTreeBuilder.js +196 -0
  380. package/dist/esm/plugin/traceTreeBuilder.js.map +1 -0
  381. package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts +3 -0
  382. package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts.map +1 -0
  383. package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.js +41 -0
  384. package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.js.map +1 -0
  385. package/dist/esm/plugin/usageReporting/durationHistogram.d.ts +16 -0
  386. package/dist/esm/plugin/usageReporting/durationHistogram.d.ts.map +1 -0
  387. package/dist/esm/plugin/usageReporting/durationHistogram.js +64 -0
  388. package/dist/esm/plugin/usageReporting/durationHistogram.js.map +1 -0
  389. package/dist/esm/plugin/usageReporting/index.d.ts +3 -0
  390. package/dist/esm/plugin/usageReporting/index.d.ts.map +1 -0
  391. package/dist/esm/plugin/usageReporting/index.js +2 -0
  392. package/dist/esm/plugin/usageReporting/index.js.map +1 -0
  393. package/dist/esm/plugin/usageReporting/iterateOverTrace.d.ts +7 -0
  394. package/dist/esm/plugin/usageReporting/iterateOverTrace.d.ts.map +1 -0
  395. package/dist/esm/plugin/usageReporting/iterateOverTrace.js +78 -0
  396. package/dist/esm/plugin/usageReporting/iterateOverTrace.js.map +1 -0
  397. package/dist/esm/plugin/usageReporting/operationDerivedDataCache.d.ts +12 -0
  398. package/dist/esm/plugin/usageReporting/operationDerivedDataCache.d.ts.map +1 -0
  399. package/dist/esm/plugin/usageReporting/operationDerivedDataCache.js +29 -0
  400. package/dist/esm/plugin/usageReporting/operationDerivedDataCache.js.map +1 -0
  401. package/dist/esm/plugin/usageReporting/options.d.ts +60 -0
  402. package/dist/esm/plugin/usageReporting/options.d.ts.map +1 -0
  403. package/dist/esm/plugin/usageReporting/options.js +2 -0
  404. package/dist/esm/plugin/usageReporting/options.js.map +1 -0
  405. package/dist/esm/plugin/usageReporting/plugin.d.ts +7 -0
  406. package/dist/esm/plugin/usageReporting/plugin.d.ts.map +1 -0
  407. package/dist/esm/plugin/usageReporting/plugin.js +487 -0
  408. package/dist/esm/plugin/usageReporting/plugin.js.map +1 -0
  409. package/dist/esm/plugin/usageReporting/stats.d.ts +96 -0
  410. package/dist/esm/plugin/usageReporting/stats.d.ts.map +1 -0
  411. package/dist/esm/plugin/usageReporting/stats.js +283 -0
  412. package/dist/esm/plugin/usageReporting/stats.js.map +1 -0
  413. package/dist/esm/plugin/usageReporting/traceDetails.d.ts +4 -0
  414. package/dist/esm/plugin/usageReporting/traceDetails.d.ts.map +1 -0
  415. package/dist/esm/plugin/usageReporting/traceDetails.js +60 -0
  416. package/dist/esm/plugin/usageReporting/traceDetails.js.map +1 -0
  417. package/dist/esm/preventCsrf.d.ts +4 -0
  418. package/dist/esm/preventCsrf.d.ts.map +1 -0
  419. package/dist/esm/preventCsrf.js +34 -0
  420. package/dist/esm/preventCsrf.js.map +1 -0
  421. package/dist/esm/requestPipeline.d.ts +9 -0
  422. package/dist/esm/requestPipeline.d.ts.map +1 -0
  423. package/dist/esm/requestPipeline.js +364 -0
  424. package/dist/esm/requestPipeline.js.map +1 -0
  425. package/dist/esm/runHttpQuery.d.ts +15 -0
  426. package/dist/esm/runHttpQuery.d.ts.map +1 -0
  427. package/dist/esm/runHttpQuery.js +221 -0
  428. package/dist/esm/runHttpQuery.js.map +1 -0
  429. package/dist/esm/standalone/index.d.ts +25 -0
  430. package/dist/esm/standalone/index.d.ts.map +1 -0
  431. package/dist/esm/standalone/index.js +91 -0
  432. package/dist/esm/standalone/index.js.map +1 -0
  433. package/dist/esm/utils/HeaderMap.d.ts +8 -0
  434. package/dist/esm/utils/HeaderMap.d.ts.map +1 -0
  435. package/dist/esm/utils/HeaderMap.js +16 -0
  436. package/dist/esm/utils/HeaderMap.js.map +1 -0
  437. package/dist/esm/utils/UnreachableCaseError.d.ts +4 -0
  438. package/dist/esm/utils/UnreachableCaseError.d.ts.map +1 -0
  439. package/dist/esm/utils/UnreachableCaseError.js +6 -0
  440. package/dist/esm/utils/UnreachableCaseError.js.map +1 -0
  441. package/dist/esm/utils/computeCoreSchemaHash.d.ts +2 -0
  442. package/dist/esm/utils/computeCoreSchemaHash.d.ts.map +1 -0
  443. package/dist/esm/utils/computeCoreSchemaHash.js +5 -0
  444. package/dist/esm/utils/computeCoreSchemaHash.js.map +1 -0
  445. package/dist/esm/utils/invokeHooks.d.ts +7 -0
  446. package/dist/esm/utils/invokeHooks.d.ts.map +1 -0
  447. package/dist/esm/utils/invokeHooks.js +31 -0
  448. package/dist/esm/utils/invokeHooks.js.map +1 -0
  449. package/dist/esm/utils/isDefined.d.ts +2 -0
  450. package/dist/esm/utils/isDefined.d.ts.map +1 -0
  451. package/dist/esm/utils/isDefined.js +4 -0
  452. package/dist/esm/utils/isDefined.js.map +1 -0
  453. package/dist/esm/utils/makeGatewayGraphQLRequestContext.d.ts +5 -0
  454. package/dist/esm/utils/makeGatewayGraphQLRequestContext.d.ts.map +1 -0
  455. package/dist/esm/utils/makeGatewayGraphQLRequestContext.js +93 -0
  456. package/dist/esm/utils/makeGatewayGraphQLRequestContext.js.map +1 -0
  457. package/dist/esm/utils/resolvable.d.ts +7 -0
  458. package/dist/esm/utils/resolvable.d.ts.map +1 -0
  459. package/dist/esm/utils/resolvable.js +12 -0
  460. package/dist/esm/utils/resolvable.js.map +1 -0
  461. package/dist/esm/utils/schemaInstrumentation.d.ts +16 -0
  462. package/dist/esm/utils/schemaInstrumentation.d.ts.map +1 -0
  463. package/dist/esm/utils/schemaInstrumentation.js +69 -0
  464. package/dist/esm/utils/schemaInstrumentation.js.map +1 -0
  465. package/dist/esm/utils/schemaManager.d.ts +31 -0
  466. package/dist/esm/utils/schemaManager.d.ts.map +1 -0
  467. package/dist/esm/utils/schemaManager.js +99 -0
  468. package/dist/esm/utils/schemaManager.js.map +1 -0
  469. package/dist/esm/utils/urlForHttpServer.d.ts +3 -0
  470. package/dist/esm/utils/urlForHttpServer.d.ts.map +1 -0
  471. package/dist/esm/utils/urlForHttpServer.js +12 -0
  472. package/dist/esm/utils/urlForHttpServer.js.map +1 -0
  473. package/dist/esm/validationRules/NoIntrospection.d.ts +3 -0
  474. package/dist/esm/validationRules/NoIntrospection.d.ts.map +1 -0
  475. package/dist/esm/validationRules/NoIntrospection.js +15 -0
  476. package/dist/esm/validationRules/NoIntrospection.js.map +1 -0
  477. package/dist/esm/validationRules/RecursiveSelectionsLimit.d.ts +4 -0
  478. package/dist/esm/validationRules/RecursiveSelectionsLimit.d.ts.map +1 -0
  479. package/dist/esm/validationRules/RecursiveSelectionsLimit.js +146 -0
  480. package/dist/esm/validationRules/RecursiveSelectionsLimit.js.map +1 -0
  481. package/dist/esm/validationRules/index.d.ts +3 -0
  482. package/dist/esm/validationRules/index.d.ts.map +1 -0
  483. package/dist/esm/validationRules/index.js +3 -0
  484. package/dist/esm/validationRules/index.js.map +1 -0
  485. package/errors/package.json +8 -0
  486. package/package.json +208 -0
  487. package/plugin/cacheControl/package.json +8 -0
  488. package/plugin/disableSuggestions/package.json +8 -0
  489. package/plugin/disabled/package.json +8 -0
  490. package/plugin/drainHttpServer/package.json +8 -0
  491. package/plugin/inlineTrace/package.json +8 -0
  492. package/plugin/landingPage/default/package.json +8 -0
  493. package/plugin/schemaReporting/package.json +8 -0
  494. package/plugin/subscriptionCallback/package.json +8 -0
  495. package/plugin/usageReporting/package.json +8 -0
  496. package/src/ApolloServer.ts +1456 -0
  497. package/src/cachePolicy.ts +33 -0
  498. package/src/determineApolloConfig.ts +95 -0
  499. package/src/errorNormalize.ts +114 -0
  500. package/src/errors/index.ts +33 -0
  501. package/src/externalTypes/constructor.ts +174 -0
  502. package/src/externalTypes/context.ts +18 -0
  503. package/src/externalTypes/graphql.ts +81 -0
  504. package/src/externalTypes/http.ts +44 -0
  505. package/src/externalTypes/incrementalDeliveryPolyfillAlpha2.ts +63 -0
  506. package/src/externalTypes/incrementalDeliveryPolyfillAlpha9.ts +82 -0
  507. package/src/externalTypes/index.ts +73 -0
  508. package/src/externalTypes/plugins.ts +222 -0
  509. package/src/externalTypes/requestPipeline.ts +123 -0
  510. package/src/generated/packageVersion.ts +1 -0
  511. package/src/httpBatching.ts +105 -0
  512. package/src/incrementalDeliveryPolyfill.ts +253 -0
  513. package/src/index.ts +4 -0
  514. package/src/internalErrorClasses.ts +123 -0
  515. package/src/internalPlugin.ts +42 -0
  516. package/src/plugin/cacheControl/index.ts +453 -0
  517. package/src/plugin/disableSuggestions/index.ts +23 -0
  518. package/src/plugin/disabled/index.ts +41 -0
  519. package/src/plugin/drainHttpServer/index.ts +42 -0
  520. package/src/plugin/drainHttpServer/stoppable.ts +109 -0
  521. package/src/plugin/inlineTrace/index.ts +156 -0
  522. package/src/plugin/landingPage/default/getEmbeddedHTML.ts +204 -0
  523. package/src/plugin/landingPage/default/index.ts +219 -0
  524. package/src/plugin/landingPage/default/types.ts +198 -0
  525. package/src/plugin/schemaIsSubgraph.ts +41 -0
  526. package/src/plugin/schemaReporting/generated/operations.d.ts +18359 -0
  527. package/src/plugin/schemaReporting/index.ts +198 -0
  528. package/src/plugin/schemaReporting/schemaReporter.ts +207 -0
  529. package/src/plugin/subscriptionCallback/index.ts +724 -0
  530. package/src/plugin/traceTreeBuilder.ts +356 -0
  531. package/src/plugin/usageReporting/defaultSendOperationsAsTrace.ts +74 -0
  532. package/src/plugin/usageReporting/durationHistogram.ts +87 -0
  533. package/src/plugin/usageReporting/index.ts +9 -0
  534. package/src/plugin/usageReporting/iterateOverTrace.ts +140 -0
  535. package/src/plugin/usageReporting/operationDerivedDataCache.ts +61 -0
  536. package/src/plugin/usageReporting/options.ts +414 -0
  537. package/src/plugin/usageReporting/plugin.ts +871 -0
  538. package/src/plugin/usageReporting/stats.ts +492 -0
  539. package/src/plugin/usageReporting/traceDetails.ts +96 -0
  540. package/src/preventCsrf.ts +99 -0
  541. package/src/requestPipeline.ts +821 -0
  542. package/src/runHttpQuery.ts +408 -0
  543. package/src/standalone/index.ts +155 -0
  544. package/src/utils/HeaderMap.ts +22 -0
  545. package/src/utils/UnreachableCaseError.ts +10 -0
  546. package/src/utils/computeCoreSchemaHash.ts +9 -0
  547. package/src/utils/invokeHooks.ts +53 -0
  548. package/src/utils/isDefined.ts +3 -0
  549. package/src/utils/makeGatewayGraphQLRequestContext.ts +197 -0
  550. package/src/utils/resolvable.ts +30 -0
  551. package/src/utils/schemaInstrumentation.ts +132 -0
  552. package/src/utils/schemaManager.ts +212 -0
  553. package/src/utils/urlForHttpServer.ts +21 -0
  554. package/src/validationRules/NoIntrospection.ts +27 -0
  555. package/src/validationRules/RecursiveSelectionsLimit.ts +198 -0
  556. package/src/validationRules/index.ts +5 -0
  557. package/standalone/package.json +8 -0
@@ -0,0 +1,1456 @@
1
+ import type { GatewayExecutor } from '@apollo/server-gateway-interface';
2
+ import { isNodeLike } from '@apollo/utils.isnodelike';
3
+ import {
4
+ InMemoryLRUCache,
5
+ PrefixingKeyValueCache,
6
+ type KeyValueCache,
7
+ } from '@apollo/utils.keyvaluecache';
8
+ import type { Logger } from '@apollo/utils.logger';
9
+ import type { WithRequired } from '@apollo/utils.withrequired';
10
+ import { makeExecutableSchema } from '@graphql-tools/schema';
11
+ import resolvable, { type Resolvable } from './utils/resolvable.js';
12
+ import {
13
+ GraphQLError,
14
+ assertValidSchema,
15
+ print,
16
+ printSchema,
17
+ type validate,
18
+ type DocumentNode,
19
+ type ExecutionArgs,
20
+ type FormattedExecutionResult,
21
+ type GraphQLFieldResolver,
22
+ type GraphQLFormattedError,
23
+ type GraphQLSchema,
24
+ type ParseOptions,
25
+ type TypedQueryDocumentNode,
26
+ type ValidationRule,
27
+ } from 'graphql';
28
+ import loglevel from 'loglevel';
29
+ import Negotiator from 'negotiator';
30
+ import { newCachePolicy } from './cachePolicy.js';
31
+ import { determineApolloConfig } from './determineApolloConfig.js';
32
+ import {
33
+ ensureError,
34
+ ensureGraphQLError,
35
+ normalizeAndFormatErrors,
36
+ } from './errorNormalize.js';
37
+ import { ApolloServerErrorCode } from './errors/index.js';
38
+ import type { ApolloServerOptionsWithStaticSchema } from './externalTypes/constructor.js';
39
+ import type {
40
+ ExecuteOperationOptions,
41
+ LegacyExperimentalExecuteIncrementally,
42
+ VariableValues,
43
+ } from './externalTypes/graphql.js';
44
+ import type {
45
+ ApolloConfig,
46
+ ApolloServerOptions,
47
+ ApolloServerPlugin,
48
+ BaseContext,
49
+ ContextThunk,
50
+ DocumentStore,
51
+ GraphQLRequest,
52
+ GraphQLRequestContext,
53
+ GraphQLResponse,
54
+ GraphQLServerContext,
55
+ GraphQLServerListener,
56
+ HTTPGraphQLHead,
57
+ HTTPGraphQLRequest,
58
+ HTTPGraphQLResponse,
59
+ LandingPage,
60
+ PersistedQueryOptions,
61
+ } from './externalTypes/index.js';
62
+ import { runPotentiallyBatchedHttpQuery } from './httpBatching.js';
63
+ import type {
64
+ GraphQLExperimentalIncrementalExecutionResultsAlpha2,
65
+ GraphQLExperimentalIncrementalExecutionResultsAlpha9,
66
+ } from './incrementalDeliveryPolyfill.js';
67
+ import { pluginIsInternal, type InternalPluginId } from './internalPlugin.js';
68
+ import {
69
+ preventCsrf,
70
+ recommendedCsrfPreventionRequestHeaders,
71
+ } from './preventCsrf.js';
72
+ import { APQ_CACHE_PREFIX, processGraphQLRequest } from './requestPipeline.js';
73
+ import { newHTTPGraphQLHead, prettyJSONStringify } from './runHttpQuery.js';
74
+ import { HeaderMap } from './utils/HeaderMap.js';
75
+ import { UnreachableCaseError } from './utils/UnreachableCaseError.js';
76
+ import { computeCoreSchemaHash } from './utils/computeCoreSchemaHash.js';
77
+ import { isDefined } from './utils/isDefined.js';
78
+ import { SchemaManager } from './utils/schemaManager.js';
79
+ import {
80
+ NoIntrospection,
81
+ createMaxRecursiveSelectionsRule,
82
+ DEFAULT_MAX_RECURSIVE_SELECTIONS,
83
+ } from './validationRules/index.js';
84
+
85
+ export type SchemaDerivedData = {
86
+ schema: GraphQLSchema;
87
+ // A store that, when enabled (default), will store the parsed and validated
88
+ // versions of operations in-memory, allowing subsequent parses/validates
89
+ // on the same operation to be executed immediately.
90
+ documentStore: DocumentStore | null;
91
+ // Prefix for keys in the DocumentStore if a custom one is provided (to
92
+ // separate the cache for different schema versions). This is vital to
93
+ // security so we do it explicitly so that
94
+ // PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation
95
+ // doesn't affect it.
96
+ documentStoreKeyPrefix: string;
97
+ };
98
+
99
+ type RunningServerState = {
100
+ schemaManager: SchemaManager;
101
+ landingPage: LandingPage | null;
102
+ };
103
+
104
+ type ServerState =
105
+ | {
106
+ phase: 'initialized';
107
+ schemaManager: SchemaManager;
108
+ }
109
+ | {
110
+ phase: 'starting';
111
+ barrier: Resolvable<void>;
112
+ schemaManager: SchemaManager;
113
+ // This is set to true if you called
114
+ // startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests
115
+ // instead of start. The main purpose is that assertStarted allows you to
116
+ // still be in the starting phase if this is set. (This is the serverless
117
+ // use case.)
118
+ startedInBackground: boolean;
119
+ }
120
+ | {
121
+ phase: 'failed to start';
122
+ error: Error;
123
+ }
124
+ | ({
125
+ phase: 'started';
126
+ drainServers: (() => Promise<void>) | null;
127
+ toDispose: (() => Promise<void>)[];
128
+ toDisposeLast: (() => Promise<void>)[];
129
+ } & RunningServerState)
130
+ | ({
131
+ phase: 'draining';
132
+ barrier: Resolvable<void>;
133
+ } & RunningServerState)
134
+ | {
135
+ phase: 'stopping';
136
+ barrier: Resolvable<void>;
137
+ }
138
+ | {
139
+ phase: 'stopped';
140
+ stopError: Error | null;
141
+ };
142
+
143
+ export type ValidationOptions = NonNullable<Parameters<typeof validate>[3]>;
144
+
145
+ export interface ApolloServerInternals<TContext extends BaseContext> {
146
+ state: ServerState;
147
+ gatewayExecutor: GatewayExecutor | null;
148
+ dangerouslyDisableValidation?: boolean;
149
+ formatError?: (
150
+ formattedError: GraphQLFormattedError,
151
+ error: unknown,
152
+ ) => GraphQLFormattedError;
153
+ includeStacktraceInErrorResponses: boolean;
154
+ persistedQueries?: WithRequired<PersistedQueryOptions, 'cache'>;
155
+ nodeEnv: string;
156
+ allowBatchedHttpRequests: boolean;
157
+ apolloConfig: ApolloConfig;
158
+ plugins: ApolloServerPlugin<TContext>[];
159
+ parseOptions: ParseOptions;
160
+ validationOptions: ValidationOptions;
161
+ executionOptions?: ExecutionArgs['options'];
162
+ // `undefined` means we figure out what to do during _start (because
163
+ // the default depends on whether or not we used the background version
164
+ // of start).
165
+ stopOnTerminationSignals: boolean | undefined;
166
+ csrfPreventionRequestHeaders: string[] | null;
167
+
168
+ rootValue?: ((parsedQuery: DocumentNode) => unknown) | unknown;
169
+ validationRules: Array<ValidationRule>;
170
+ laterValidationRules?: Array<ValidationRule>;
171
+ hideSchemaDetailsFromClientErrors: boolean;
172
+ fieldResolver?: GraphQLFieldResolver<any, TContext>;
173
+ // TODO(AS6): remove this option.
174
+ status400ForVariableCoercionErrors?: boolean;
175
+ __testing_incrementalExecutionResults?:
176
+ | GraphQLExperimentalIncrementalExecutionResultsAlpha2
177
+ | GraphQLExperimentalIncrementalExecutionResultsAlpha9;
178
+ stringifyResult: (
179
+ value: FormattedExecutionResult,
180
+ ) => string | Promise<string>;
181
+ legacyExperimentalExecuteIncrementally?: LegacyExperimentalExecuteIncrementally;
182
+ }
183
+
184
+ function defaultLogger(): Logger {
185
+ const loglevelLogger = loglevel.getLogger('apollo-server');
186
+ loglevelLogger.setLevel(loglevel.levels.INFO);
187
+ return loglevelLogger;
188
+ }
189
+
190
+ // We really want to prevent this from being legal:
191
+ //
192
+ // const s: ApolloServer<{}> =
193
+ // new ApolloServer<{importantContextField: boolean}>({ ... });
194
+ // s.executeOperation({query}, {contextValue: {}});
195
+ //
196
+ // ie, if you declare an ApolloServer whose context values must be of a certain
197
+ // type, you can't assign it to a variable whose context values are less
198
+ // constrained and then pass in a context value missing important fields.
199
+ //
200
+ // We also want this to be illegal:
201
+ //
202
+ // const sBase = new ApolloServer<{}>({ ... });
203
+ // const s: ApolloServer<{importantContextField: boolean}> = sBase;
204
+ // s.addPlugin({async requestDidStart({contextValue: {importantContextField}}) { ... }})
205
+ // sBase.executeOperation({query}, {contextValue: {}});
206
+ //
207
+ // so you shouldn't be able to assign an ApolloServer to a variable whose
208
+ // context values are more constrained, either. So we want to declare that
209
+ // ApolloServer is *invariant* in TContext, which we do with `in out` (a
210
+ // TypeScript 4.7 feature).
211
+ export class ApolloServer<in out TContext extends BaseContext = BaseContext> {
212
+ private internals: ApolloServerInternals<TContext>;
213
+
214
+ public readonly cache: KeyValueCache<string>;
215
+ public readonly logger: Logger;
216
+
217
+ constructor(config: ApolloServerOptions<TContext>) {
218
+ const nodeEnv = config.nodeEnv ?? process.env.NODE_ENV ?? '';
219
+
220
+ this.logger = config.logger ?? defaultLogger();
221
+
222
+ const apolloConfig = determineApolloConfig(config.apollo, this.logger);
223
+
224
+ const isDev = nodeEnv !== 'production';
225
+
226
+ if (
227
+ config.cache &&
228
+ config.cache !== 'bounded' &&
229
+ PrefixingKeyValueCache.prefixesAreUnnecessaryForIsolation(config.cache)
230
+ ) {
231
+ throw new Error(
232
+ 'You cannot pass a cache returned from ' +
233
+ '`PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation`' +
234
+ 'to `new ApolloServer({ cache })`, because Apollo Server may use it for ' +
235
+ 'multiple features whose cache keys must be distinct from each other.',
236
+ );
237
+ }
238
+
239
+ const state: ServerState = config.gateway
240
+ ? // ApolloServer has been initialized but we have not yet tried to load the
241
+ // schema from the gateway. That will wait until `start()` or
242
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests()`
243
+ // is called. (These may be called by other helpers; for example,
244
+ // `standaloneServer` calls `start` for you inside its `listen` method,
245
+ // and a serverless framework integration would call
246
+ // startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests
247
+ // for you.)
248
+ {
249
+ phase: 'initialized',
250
+ schemaManager: new SchemaManager({
251
+ gateway: config.gateway,
252
+ apolloConfig,
253
+ schemaDerivedDataProvider: (schema) =>
254
+ ApolloServer.generateSchemaDerivedData(
255
+ schema,
256
+ config.documentStore,
257
+ ),
258
+ logger: this.logger,
259
+ }),
260
+ }
261
+ : // We construct the schema synchronously so that we can fail fast if the
262
+ // schema can't be constructed. (This used to be more important because we
263
+ // used to have a 'schema' field that was publicly accessible immediately
264
+ // after construction, though that field never actually worked with
265
+ // gateways.)
266
+ {
267
+ phase: 'initialized',
268
+ schemaManager: new SchemaManager({
269
+ apiSchema: ApolloServer.constructSchema(config),
270
+ schemaDerivedDataProvider: (schema) =>
271
+ ApolloServer.generateSchemaDerivedData(
272
+ schema,
273
+ config.documentStore,
274
+ ),
275
+ logger: this.logger,
276
+ }),
277
+ };
278
+
279
+ const introspectionEnabled = config.introspection ?? isDev;
280
+ const hideSchemaDetailsFromClientErrors =
281
+ config.hideSchemaDetailsFromClientErrors ?? false;
282
+
283
+ // We continue to allow 'bounded' for backwards-compatibility with the AS3.9
284
+ // API.
285
+ this.cache =
286
+ config.cache === undefined || config.cache === 'bounded'
287
+ ? new InMemoryLRUCache()
288
+ : config.cache;
289
+
290
+ // Check whether the recursive selections limit has been enabled (off by
291
+ // default), or whether a custom limit has been specified.
292
+ const maxRecursiveSelectionsRule =
293
+ config.maxRecursiveSelections === true
294
+ ? [createMaxRecursiveSelectionsRule(DEFAULT_MAX_RECURSIVE_SELECTIONS)]
295
+ : typeof config.maxRecursiveSelections === 'number'
296
+ ? [createMaxRecursiveSelectionsRule(config.maxRecursiveSelections)]
297
+ : [];
298
+
299
+ // If the recursive selections rule has been enabled, then run configured
300
+ // validations in a later validate() pass.
301
+ const validationRules = [
302
+ ...(introspectionEnabled ? [] : [NoIntrospection]),
303
+ ...maxRecursiveSelectionsRule,
304
+ ];
305
+ let laterValidationRules;
306
+ if (maxRecursiveSelectionsRule.length > 0) {
307
+ laterValidationRules = config.validationRules;
308
+ } else {
309
+ validationRules.push(...(config.validationRules ?? []));
310
+ }
311
+
312
+ // Note that we avoid calling methods on `this` before `this.internals` is assigned
313
+ // (thus a bunch of things being static methods above).
314
+ this.internals = {
315
+ formatError: config.formatError,
316
+ rootValue: config.rootValue,
317
+ validationRules,
318
+ laterValidationRules,
319
+ hideSchemaDetailsFromClientErrors,
320
+ dangerouslyDisableValidation:
321
+ config.dangerouslyDisableValidation ?? false,
322
+ validationOptions: config.validationOptions ?? {},
323
+ fieldResolver: config.fieldResolver,
324
+ includeStacktraceInErrorResponses:
325
+ config.includeStacktraceInErrorResponses ??
326
+ (nodeEnv !== 'production' && nodeEnv !== 'test'),
327
+ persistedQueries:
328
+ config.persistedQueries === false
329
+ ? undefined
330
+ : {
331
+ ...config.persistedQueries,
332
+ cache: new PrefixingKeyValueCache(
333
+ config.persistedQueries?.cache ?? this.cache,
334
+ APQ_CACHE_PREFIX,
335
+ ),
336
+ },
337
+ nodeEnv,
338
+ allowBatchedHttpRequests: config.allowBatchedHttpRequests ?? false,
339
+ apolloConfig,
340
+ // Note that more plugins can be added before `start()` with `addPlugin()`
341
+ // (eg, plugins that want to take this ApolloServer as an argument), and
342
+ // `start()` will call `addDefaultPlugins` to add default plugins.
343
+ plugins: config.plugins ?? [],
344
+ parseOptions: config.parseOptions ?? {},
345
+ executionOptions: config.executionOptions ?? {},
346
+ state,
347
+ stopOnTerminationSignals: config.stopOnTerminationSignals,
348
+
349
+ gatewayExecutor: null, // set by _start
350
+
351
+ csrfPreventionRequestHeaders:
352
+ config.csrfPrevention === true || config.csrfPrevention === undefined
353
+ ? recommendedCsrfPreventionRequestHeaders
354
+ : config.csrfPrevention === false
355
+ ? null
356
+ : (config.csrfPrevention.requestHeaders ??
357
+ recommendedCsrfPreventionRequestHeaders),
358
+ status400ForVariableCoercionErrors:
359
+ config.status400ForVariableCoercionErrors ?? true,
360
+ __testing_incrementalExecutionResults:
361
+ config.__testing_incrementalExecutionResults,
362
+ stringifyResult: config.stringifyResult ?? prettyJSONStringify,
363
+ legacyExperimentalExecuteIncrementally:
364
+ config.legacyExperimentalExecuteIncrementally,
365
+ };
366
+
367
+ this.warnAgainstDeprecatedConfigOptions(config);
368
+ }
369
+
370
+ private warnAgainstDeprecatedConfigOptions(
371
+ config: ApolloServerOptions<TContext>,
372
+ ) {
373
+ // TODO(AS6): this option goes away altogether. We should either update or remove this warning.
374
+ if ('status400ForVariableCoercionErrors' in config) {
375
+ if (config.status400ForVariableCoercionErrors === true) {
376
+ this.logger.warn(
377
+ 'The `status400ForVariableCoercionErrors: true` configuration option is now the default behavior and has no effect in Apollo Server v5. You can safely remove this option from your configuration.',
378
+ );
379
+ } else {
380
+ this.logger.warn(
381
+ 'The `status400ForVariableCoercionErrors: false` configuration option is deprecated and will be removed in Apollo Server v6. Apollo recommends removing any dependency on this behavior.',
382
+ );
383
+ }
384
+ }
385
+ }
386
+
387
+ // Awaiting a call to `start` ensures that a schema has been loaded and that
388
+ // all plugin `serverWillStart` hooks have been called. If either of these
389
+ // processes throw, `start` will (async) throw as well.
390
+ //
391
+ // If you're using `standaloneServer`, you don't need to call `start` yourself
392
+ // (in fact, it will throw if you do so); its `listen` method takes care of
393
+ // that for you.
394
+ //
395
+ // If instead you're using an integration package for a non-serverless
396
+ // framework (like Express), you must await a call to `start` immediately
397
+ // after creating your `ApolloServer`, before attaching it to your web
398
+ // framework and starting to accept requests. `start` should only be called
399
+ // once; if it throws and you'd like to retry, just create another
400
+ // `ApolloServer`. (Calling `start` was optional in Apollo Server 2, but in
401
+ // Apollo Server 3+ the functions like `expressMiddleware` use `assertStarted`
402
+ // to throw if `start` hasn't successfully completed.)
403
+ //
404
+ // Serverless integrations like Lambda do not support calling `start()`,
405
+ // because their lifecycle doesn't allow you to wait before assigning a
406
+ // handler or allowing the handler to be called. So they call
407
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests()`
408
+ // instead, and don't really differentiate between startup failures and
409
+ // request failures. This is hopefully appropriate for a "serverless"
410
+ // framework. Serverless startup failures result in returning a redacted error
411
+ // to the end user and logging the more detailed error.
412
+ public async start(): Promise<void> {
413
+ return await this._start(false);
414
+ }
415
+
416
+ public startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests(): void {
417
+ this._start(true).catch((e) => this.logStartupError(e));
418
+ }
419
+
420
+ private async _start(startedInBackground: boolean): Promise<void> {
421
+ if (this.internals.state.phase !== 'initialized') {
422
+ // If we wanted we could make this error detectable and change
423
+ // `standaloneServer` to change the message to say not to call start() at
424
+ // all.
425
+ throw new Error(
426
+ `You should only call 'start()' or ` +
427
+ `'startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests()' ` +
428
+ `once on your ApolloServer.`,
429
+ );
430
+ }
431
+ const schemaManager = this.internals.state.schemaManager;
432
+ const barrier = resolvable();
433
+ this.internals.state = {
434
+ phase: 'starting',
435
+ barrier,
436
+ schemaManager,
437
+ startedInBackground,
438
+ };
439
+ try {
440
+ // Now that you can't call addPlugin any more, add default plugins like
441
+ // usage reporting if they're not already added.
442
+ await this.addDefaultPlugins();
443
+
444
+ const toDispose: (() => Promise<void>)[] = [];
445
+ const executor = await schemaManager.start();
446
+ if (executor) {
447
+ this.internals.gatewayExecutor = executor;
448
+ }
449
+ toDispose.push(async () => {
450
+ await schemaManager.stop();
451
+ });
452
+
453
+ const schemaDerivedData = schemaManager.getSchemaDerivedData();
454
+ const service: GraphQLServerContext = {
455
+ logger: this.logger,
456
+ cache: this.cache,
457
+ schema: schemaDerivedData.schema,
458
+ apollo: this.internals.apolloConfig,
459
+ startedInBackground,
460
+ };
461
+
462
+ const taggedServerListeners = (
463
+ await Promise.all(
464
+ this.internals.plugins.map(async (plugin) => ({
465
+ serverListener:
466
+ plugin.serverWillStart && (await plugin.serverWillStart(service)),
467
+ installedImplicitly:
468
+ isImplicitlyInstallablePlugin(plugin) &&
469
+ plugin.__internal_installed_implicitly__,
470
+ })),
471
+ )
472
+ ).filter(
473
+ (
474
+ maybeTaggedServerListener,
475
+ ): maybeTaggedServerListener is {
476
+ serverListener: GraphQLServerListener;
477
+ installedImplicitly: boolean;
478
+ } => typeof maybeTaggedServerListener.serverListener === 'object',
479
+ );
480
+
481
+ taggedServerListeners.forEach(
482
+ ({ serverListener: { schemaDidLoadOrUpdate } }) => {
483
+ if (schemaDidLoadOrUpdate) {
484
+ schemaManager.onSchemaLoadOrUpdate(schemaDidLoadOrUpdate);
485
+ }
486
+ },
487
+ );
488
+
489
+ const serverWillStops = taggedServerListeners
490
+ .map((l) => l.serverListener.serverWillStop)
491
+ .filter(isDefined);
492
+ if (serverWillStops.length) {
493
+ toDispose.push(async () => {
494
+ await Promise.all(
495
+ serverWillStops.map((serverWillStop) => serverWillStop()),
496
+ );
497
+ });
498
+ }
499
+
500
+ const drainServerCallbacks = taggedServerListeners
501
+ .map((l) => l.serverListener.drainServer)
502
+ .filter(isDefined);
503
+ const drainServers = drainServerCallbacks.length
504
+ ? async () => {
505
+ await Promise.all(
506
+ drainServerCallbacks.map((drainServer) => drainServer()),
507
+ );
508
+ }
509
+ : null;
510
+
511
+ // Find the renderLandingPage callback, if one is provided. If the user
512
+ // installed ApolloServerPluginLandingPageDisabled then there may be none
513
+ // found. On the other hand, if the user installed a landingPage plugin,
514
+ // then both the implicit installation of
515
+ // ApolloServerPluginLandingPage*Default and the other plugin will be
516
+ // found; we skip the implicit plugin.
517
+ let taggedServerListenersWithRenderLandingPage =
518
+ taggedServerListeners.filter((l) => l.serverListener.renderLandingPage);
519
+ if (taggedServerListenersWithRenderLandingPage.length > 1) {
520
+ taggedServerListenersWithRenderLandingPage =
521
+ taggedServerListenersWithRenderLandingPage.filter(
522
+ (l) => !l.installedImplicitly,
523
+ );
524
+ }
525
+ let landingPage: LandingPage | null = null;
526
+ if (taggedServerListenersWithRenderLandingPage.length > 1) {
527
+ throw Error('Only one plugin can implement renderLandingPage.');
528
+ } else if (taggedServerListenersWithRenderLandingPage.length) {
529
+ landingPage =
530
+ await taggedServerListenersWithRenderLandingPage[0].serverListener
531
+ .renderLandingPage!();
532
+ }
533
+
534
+ const toDisposeLast = this.maybeRegisterTerminationSignalHandlers(
535
+ ['SIGINT', 'SIGTERM'],
536
+ startedInBackground,
537
+ );
538
+
539
+ this.internals.state = {
540
+ phase: 'started',
541
+ schemaManager,
542
+ drainServers,
543
+ landingPage,
544
+ toDispose,
545
+ toDisposeLast,
546
+ };
547
+ } catch (maybeError: unknown) {
548
+ const error = ensureError(maybeError);
549
+
550
+ try {
551
+ await Promise.all(
552
+ this.internals.plugins.map(async (plugin) =>
553
+ plugin.startupDidFail?.({ error }),
554
+ ),
555
+ );
556
+ } catch (pluginError) {
557
+ this.logger.error(`startupDidFail hook threw: ${pluginError}`);
558
+ }
559
+
560
+ this.internals.state = {
561
+ phase: 'failed to start',
562
+ error,
563
+ };
564
+ throw error;
565
+ } finally {
566
+ barrier.resolve();
567
+ }
568
+ }
569
+
570
+ private maybeRegisterTerminationSignalHandlers(
571
+ signals: NodeJS.Signals[],
572
+ startedInBackground: boolean,
573
+ ): (() => Promise<void>)[] {
574
+ const toDisposeLast: (() => Promise<void>)[] = [];
575
+
576
+ // We handle signals if it was explicitly requested
577
+ // (stopOnTerminationSignals === true), or if we're in Node, not in a test,
578
+ // not in a serverless framework (which we guess based on whether they
579
+ // called
580
+ // startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests),
581
+ // and it wasn't explicitly turned off. (We only actually register the
582
+ // signal handlers once we've successfully started up, because there's
583
+ // nothing to stop otherwise.)
584
+ if (
585
+ this.internals.stopOnTerminationSignals === false ||
586
+ (this.internals.stopOnTerminationSignals === undefined &&
587
+ !(
588
+ isNodeLike &&
589
+ this.internals.nodeEnv !== 'test' &&
590
+ !startedInBackground
591
+ ))
592
+ ) {
593
+ return toDisposeLast;
594
+ }
595
+
596
+ let receivedSignal = false;
597
+ const signalHandler: NodeJS.SignalsListener = async (signal) => {
598
+ if (receivedSignal) {
599
+ // If we receive another SIGINT or SIGTERM while we're waiting
600
+ // for the server to stop, just ignore it.
601
+ return;
602
+ }
603
+ receivedSignal = true;
604
+ try {
605
+ await this.stop();
606
+ } catch (e) {
607
+ this.logger.error(`stop() threw during ${signal} shutdown`);
608
+ this.logger.error(e);
609
+ // Can't rely on the signal handlers being removed.
610
+ process.exit(1);
611
+ }
612
+ // Note: this.stop will call the toDisposeLast handlers below, so at
613
+ // this point this handler will have been removed and we can re-kill
614
+ // ourself to die with the appropriate signal exit status. this.stop
615
+ // takes care to call toDisposeLast last, so the signal handler isn't
616
+ // removed until after the rest of shutdown happens.
617
+ process.kill(process.pid, signal);
618
+ };
619
+
620
+ signals.forEach((signal) => {
621
+ process.on(signal, signalHandler);
622
+ toDisposeLast.push(async () => {
623
+ process.removeListener(signal, signalHandler);
624
+ });
625
+ });
626
+ return toDisposeLast;
627
+ }
628
+
629
+ // This method is called at the beginning of each GraphQL request by
630
+ // `executeHTTPGraphQLRequest` and `executeOperation`. Most of its logic is
631
+ // only helpful if you started the server in the background (ie, for
632
+ // serverless frameworks): unless you're in a serverless framework, you should
633
+ // have called `await server.start()` before the server got to the point of
634
+ // running GraphQL requests (`assertStarted` calls in the framework
635
+ // integrations verify that) and so the only cases for non-serverless
636
+ // frameworks that this should hit are 'started', 'stopping', and 'stopped'.
637
+ // But if you started the server in the background (with
638
+ // startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests), this
639
+ // lets the server wait until fully started before serving operations.
640
+ private async _ensureStarted(): Promise<RunningServerState> {
641
+ while (true) {
642
+ switch (this.internals.state.phase) {
643
+ case 'initialized':
644
+ // This error probably won't happen: serverless framework integrations
645
+ // should call
646
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests`
647
+ // for you, and other frameworks call `assertStarted` before setting
648
+ // things up enough to make calling this function possible.
649
+ throw new Error(
650
+ 'You need to call `server.start()` before using your Apollo Server.',
651
+ );
652
+ case 'starting':
653
+ await this.internals.state.barrier;
654
+ // continue the while loop
655
+ break;
656
+ case 'failed to start':
657
+ // First we log the error that prevented startup (which means it will
658
+ // get logged once for every GraphQL operation).
659
+ this.logStartupError(this.internals.state.error);
660
+ // Now make the operation itself fail.
661
+ // We intentionally do not re-throw actual startup error as it may contain
662
+ // implementation details and this error will propagate to the client.
663
+ throw new Error(
664
+ 'This data graph is missing a valid configuration. More details may be available in the server logs.',
665
+ );
666
+ case 'started':
667
+ case 'draining': // We continue to run operations while draining.
668
+ return this.internals.state;
669
+ case 'stopping':
670
+ case 'stopped':
671
+ this.logger.warn(
672
+ 'A GraphQL operation was received during server shutdown. The ' +
673
+ 'operation will fail. Consider draining the HTTP server on shutdown; ' +
674
+ 'see https://go.apollo.dev/s/drain for details.',
675
+ );
676
+ throw new Error(
677
+ `Cannot execute GraphQL operations ${
678
+ this.internals.state.phase === 'stopping'
679
+ ? 'while the server is stopping'
680
+ : 'after the server has stopped'
681
+ }.'`,
682
+ );
683
+ default:
684
+ throw new UnreachableCaseError(this.internals.state);
685
+ }
686
+ }
687
+ }
688
+
689
+ // Framework integrations should call this to ensure that you've properly
690
+ // started your server before you get anywhere close to actually listening for
691
+ // incoming requests.
692
+ //
693
+ // There's a special case that if you called
694
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests` and
695
+ // it hasn't finished starting up yet, this works too. This is intended for
696
+ // cases like a serverless integration (say, Google Cloud Functions) that
697
+ // calls
698
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests` for
699
+ // you and then immediately sets up an integration based on another middleware
700
+ // like `expressMiddleware` which calls this function. We'd like this to be
701
+ // OK, but we still want normal Express users to start their ApolloServer
702
+ // before setting up their HTTP server unless they know what they are doing
703
+ // well enough to call the function with the long name themselves.
704
+ public assertStarted(expressionForError: string) {
705
+ if (
706
+ this.internals.state.phase !== 'started' &&
707
+ this.internals.state.phase !== 'draining' &&
708
+ !(
709
+ this.internals.state.phase === 'starting' &&
710
+ this.internals.state.startedInBackground
711
+ )
712
+ ) {
713
+ throw new Error(
714
+ 'You must `await server.start()` before calling `' +
715
+ expressionForError +
716
+ '`',
717
+ );
718
+ }
719
+ }
720
+
721
+ // Given an error that occurred during Apollo Server startup, log it with a
722
+ // helpful message. This should happen when you call
723
+ // `startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests` (ie,
724
+ // in serverless frameworks); with other frameworks, you must `await
725
+ // server.start()` which will throw the startup error directly instead of
726
+ // logging. This gets called both immediately when the startup error happens,
727
+ // and on all subsequent requests.
728
+ private logStartupError(err: Error) {
729
+ this.logger.error(
730
+ 'An error occurred during Apollo Server startup. All GraphQL requests ' +
731
+ 'will now fail. The startup error was: ' +
732
+ (err?.message || err),
733
+ );
734
+ }
735
+
736
+ private static constructSchema<TContext extends BaseContext>(
737
+ config: ApolloServerOptionsWithStaticSchema<TContext>,
738
+ ): GraphQLSchema {
739
+ if (config.schema) {
740
+ return config.schema;
741
+ }
742
+
743
+ const { typeDefs, resolvers } = config;
744
+ const augmentedTypeDefs = Array.isArray(typeDefs) ? typeDefs : [typeDefs];
745
+
746
+ // For convenience, we allow you to pass a few options that we pass through
747
+ // to a particular version of `@graphql-tools/schema`'s
748
+ // `makeExecutableSchema`. If you want to use more of this function's
749
+ // features or have more control over the version of the packages used, just
750
+ // call it yourself like `new ApolloServer({schema:
751
+ // makeExecutableSchema(...)})`.
752
+ return makeExecutableSchema({
753
+ typeDefs: augmentedTypeDefs,
754
+ resolvers,
755
+ });
756
+ }
757
+
758
+ private static generateSchemaDerivedData(
759
+ schema: GraphQLSchema,
760
+ // null means don't use a documentStore at all.
761
+ // missing/undefined means use the default (creating a new one each
762
+ // time).
763
+ // defined means wrap this one in a random prefix for each new schema.
764
+ providedDocumentStore: DocumentStore | null | undefined,
765
+ ): SchemaDerivedData {
766
+ // Instead of waiting for the first operation execution against the schema
767
+ // to find out if it's a valid schema or not, check right now. In the
768
+ // non-gateway case, if this throws then the `new ApolloServer` call will
769
+ // throw. In the gateway case if this throws then it will log a message and
770
+ // just not update the schema (although oddly the message will claim that
771
+ // the schema is updating).
772
+ assertValidSchema(schema);
773
+
774
+ return {
775
+ schema,
776
+ // The DocumentStore is schema-derived because we put documents in it
777
+ // after checking that they pass GraphQL validation against the schema and
778
+ // use this to skip validation as well as parsing. So we can't reuse the
779
+ // same DocumentStore for different schemas because that might make us
780
+ // treat invalid operations as valid. If we're using the default
781
+ // DocumentStore, then we just create it from scratch each time we get a
782
+ // new schema. If we're using a user-provided DocumentStore, then we use
783
+ // the schema hash as a prefix.
784
+ documentStore:
785
+ providedDocumentStore === undefined
786
+ ? new InMemoryLRUCache<DocumentNode>()
787
+ : providedDocumentStore,
788
+ documentStoreKeyPrefix: providedDocumentStore
789
+ ? `${computeCoreSchemaHash(printSchema(schema))}:`
790
+ : '',
791
+ };
792
+ }
793
+
794
+ public async stop() {
795
+ switch (this.internals.state.phase) {
796
+ case 'initialized':
797
+ case 'starting':
798
+ case 'failed to start':
799
+ throw Error(
800
+ 'apolloServer.stop() should only be called after `await apolloServer.start()` has succeeded',
801
+ );
802
+
803
+ // Calling stop more than once should have the same result as the first time.
804
+ case 'stopped':
805
+ if (this.internals.state.stopError) {
806
+ throw this.internals.state.stopError;
807
+ }
808
+ return;
809
+
810
+ // Two parallel calls to stop; just wait for the other one to finish and
811
+ // do whatever it did.
812
+ case 'stopping':
813
+ case 'draining': {
814
+ await this.internals.state.barrier;
815
+ // The cast here is because TS doesn't understand that this.state can
816
+ // change during the await
817
+ // (https://github.com/microsoft/TypeScript/issues/9998).
818
+ const state = this.internals.state as ServerState;
819
+ if (state.phase !== 'stopped') {
820
+ throw Error(`Surprising post-stopping state ${state.phase}`);
821
+ }
822
+ if (state.stopError) {
823
+ throw state.stopError;
824
+ }
825
+ return;
826
+ }
827
+
828
+ case 'started':
829
+ // This is handled by the rest of the function.
830
+ break;
831
+
832
+ default:
833
+ throw new UnreachableCaseError(this.internals.state);
834
+ }
835
+
836
+ const barrier = resolvable();
837
+
838
+ const {
839
+ schemaManager,
840
+ drainServers,
841
+ landingPage,
842
+ toDispose,
843
+ toDisposeLast,
844
+ } = this.internals.state;
845
+
846
+ // Commit to stopping and start draining servers.
847
+ this.internals.state = {
848
+ phase: 'draining',
849
+ barrier,
850
+ schemaManager,
851
+ landingPage,
852
+ };
853
+
854
+ try {
855
+ await drainServers?.();
856
+
857
+ // Servers are drained. Prevent further operations from starting and call
858
+ // stop handlers.
859
+ this.internals.state = { phase: 'stopping', barrier };
860
+
861
+ // We run shutdown handlers in two phases because we don't want to turn
862
+ // off our signal listeners (ie, allow signals to kill the process) until
863
+ // we've done the important parts of shutdown like running serverWillStop
864
+ // handlers. (We can make this more generic later if it's helpful.)
865
+ await Promise.all([...toDispose].map((dispose) => dispose()));
866
+ await Promise.all([...toDisposeLast].map((dispose) => dispose()));
867
+ } catch (stopError) {
868
+ this.internals.state = {
869
+ phase: 'stopped',
870
+ stopError: stopError as Error,
871
+ };
872
+ barrier.resolve();
873
+ throw stopError;
874
+ }
875
+ this.internals.state = { phase: 'stopped', stopError: null };
876
+ }
877
+
878
+ private async addDefaultPlugins() {
879
+ const {
880
+ plugins,
881
+ apolloConfig,
882
+ nodeEnv,
883
+ hideSchemaDetailsFromClientErrors,
884
+ } = this.internals;
885
+ const isDev = nodeEnv !== 'production';
886
+
887
+ const alreadyHavePluginWithInternalId = (id: InternalPluginId) =>
888
+ plugins.some(
889
+ (p) => pluginIsInternal(p) && p.__internal_plugin_id__ === id,
890
+ );
891
+
892
+ // Make sure we're not trying to explicitly enable and disable the same
893
+ // feature. (Be careful: we are not trying to stop people from installing
894
+ // the same plugin twice if they have a use case for it, like two usage
895
+ // reporting plugins for different variants.)
896
+ //
897
+ // Note that this check doesn't work for the landing page plugin, because
898
+ // users can write their own landing page plugins and we don't know if a
899
+ // given plugin is a landing page plugin until the server has started.
900
+ const pluginsByInternalID = new Map<
901
+ InternalPluginId,
902
+ { sawDisabled: boolean; sawNonDisabled: boolean }
903
+ >();
904
+ for (const p of plugins) {
905
+ if (pluginIsInternal(p)) {
906
+ const id = p.__internal_plugin_id__;
907
+ if (!pluginsByInternalID.has(id)) {
908
+ pluginsByInternalID.set(id, {
909
+ sawDisabled: false,
910
+ sawNonDisabled: false,
911
+ });
912
+ }
913
+ const seen = pluginsByInternalID.get(id)!;
914
+ if (p.__is_disabled_plugin__) {
915
+ seen.sawDisabled = true;
916
+ } else {
917
+ seen.sawNonDisabled = true;
918
+ }
919
+
920
+ if (seen.sawDisabled && seen.sawNonDisabled) {
921
+ throw new Error(
922
+ `You have tried to install both ApolloServerPlugin${id} and ` +
923
+ `ApolloServerPlugin${id}Disabled in your server. Please choose ` +
924
+ `whether or not you want to disable the feature and install the ` +
925
+ `appropriate plugin for your use case.`,
926
+ );
927
+ }
928
+ }
929
+ }
930
+
931
+ // Special case: cache control is on unless you explicitly disable it.
932
+ {
933
+ if (!alreadyHavePluginWithInternalId('CacheControl')) {
934
+ const { ApolloServerPluginCacheControl } = await import(
935
+ './plugin/cacheControl/index.js'
936
+ );
937
+ plugins.push(ApolloServerPluginCacheControl());
938
+ }
939
+ }
940
+
941
+ // Special case: usage reporting is on by default (and first!) if you
942
+ // configure an API key.
943
+ {
944
+ const alreadyHavePlugin =
945
+ alreadyHavePluginWithInternalId('UsageReporting');
946
+ if (!alreadyHavePlugin && apolloConfig.key) {
947
+ if (apolloConfig.graphRef) {
948
+ // Keep this plugin first so it wraps everything. (Unfortunately despite
949
+ // the fact that the person who wrote this line also was the original
950
+ // author of the comment above in #1105, they don't quite understand why this was important.)
951
+ const { ApolloServerPluginUsageReporting } = await import(
952
+ './plugin/usageReporting/index.js'
953
+ );
954
+ plugins.unshift(
955
+ ApolloServerPluginUsageReporting({
956
+ __onlyIfSchemaIsNotSubgraph: true,
957
+ }),
958
+ );
959
+ } else {
960
+ this.logger.warn(
961
+ 'You have specified an Apollo key but have not specified a graph ref; usage ' +
962
+ 'reporting is disabled. To enable usage reporting, set the `APOLLO_GRAPH_REF` ' +
963
+ 'environment variable to `your-graph-id@your-graph-variant`. To disable this ' +
964
+ 'warning, install `ApolloServerPluginUsageReportingDisabled`.',
965
+ );
966
+ }
967
+ }
968
+ }
969
+
970
+ // Special case: schema reporting can be turned on via environment variable.
971
+ {
972
+ const alreadyHavePlugin =
973
+ alreadyHavePluginWithInternalId('SchemaReporting');
974
+ const enabledViaEnvVar = process.env.APOLLO_SCHEMA_REPORTING === 'true';
975
+ if (!alreadyHavePlugin && enabledViaEnvVar) {
976
+ if (apolloConfig.key) {
977
+ const { ApolloServerPluginSchemaReporting } = await import(
978
+ './plugin/schemaReporting/index.js'
979
+ );
980
+ plugins.push(ApolloServerPluginSchemaReporting());
981
+ } else {
982
+ throw new Error(
983
+ "You've enabled schema reporting by setting the APOLLO_SCHEMA_REPORTING " +
984
+ 'environment variable to true, but you also need to provide your ' +
985
+ 'Apollo API key, via the APOLLO_KEY environment ' +
986
+ 'variable or via `new ApolloServer({apollo: {key})',
987
+ );
988
+ }
989
+ }
990
+ }
991
+
992
+ // Special case: inline tracing is on by default for federated schemas.
993
+ {
994
+ const alreadyHavePlugin = alreadyHavePluginWithInternalId('InlineTrace');
995
+ if (!alreadyHavePlugin) {
996
+ // If we haven't explicitly disabled inline tracing via
997
+ // ApolloServerPluginInlineTraceDisabled or explicitly installed our own
998
+ // ApolloServerPluginInlineTrace, we set up inline tracing in "only if
999
+ // federated" mode. (This is slightly different than the
1000
+ // pre-ApolloServerPluginInlineTrace where we would also avoid doing
1001
+ // this if an API key was configured and log a warning.)
1002
+ const { ApolloServerPluginInlineTrace } = await import(
1003
+ './plugin/inlineTrace/index.js'
1004
+ );
1005
+ plugins.push(
1006
+ ApolloServerPluginInlineTrace({ __onlyIfSchemaIsSubgraph: true }),
1007
+ );
1008
+ }
1009
+ }
1010
+
1011
+ // Special case: If we're not in production, show our default landing page.
1012
+ //
1013
+ // This works a bit differently from the other implicitly installed plugins,
1014
+ // which rely entirely on the __internal_plugin_id__ to decide whether the
1015
+ // plugin takes effect. That's because we want third-party plugins to be
1016
+ // able to provide a landing page that overrides the default landing page,
1017
+ // without them having to know about __internal_plugin_id__. So unless we
1018
+ // actively disable the default landing page with
1019
+ // ApolloServerPluginLandingPageDisabled, we install the default landing
1020
+ // page, but with a special flag that _start() uses to ignore it if some
1021
+ // other plugin defines a renderLandingPage callback. (We can't just look
1022
+ // now to see if the plugin defines renderLandingPage because we haven't run
1023
+ // serverWillStart yet.)
1024
+ const alreadyHavePlugin = alreadyHavePluginWithInternalId(
1025
+ 'LandingPageDisabled',
1026
+ );
1027
+ if (!alreadyHavePlugin) {
1028
+ const {
1029
+ ApolloServerPluginLandingPageLocalDefault,
1030
+ ApolloServerPluginLandingPageProductionDefault,
1031
+ } = await import('./plugin/landingPage/default/index.js');
1032
+ const plugin: ApolloServerPlugin<TContext> = isDev
1033
+ ? ApolloServerPluginLandingPageLocalDefault()
1034
+ : ApolloServerPluginLandingPageProductionDefault();
1035
+ if (!isImplicitlyInstallablePlugin(plugin)) {
1036
+ throw Error(
1037
+ 'default landing page plugin should be implicitly installable?',
1038
+ );
1039
+ }
1040
+ plugin.__internal_installed_implicitly__ = true;
1041
+ plugins.push(plugin);
1042
+ }
1043
+
1044
+ {
1045
+ const alreadyHavePlugin =
1046
+ alreadyHavePluginWithInternalId('DisableSuggestions');
1047
+ if (hideSchemaDetailsFromClientErrors && !alreadyHavePlugin) {
1048
+ const { ApolloServerPluginDisableSuggestions } = await import(
1049
+ './plugin/disableSuggestions/index.js'
1050
+ );
1051
+ plugins.push(ApolloServerPluginDisableSuggestions());
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+ public addPlugin(plugin: ApolloServerPlugin<TContext>) {
1057
+ if (this.internals.state.phase !== 'initialized') {
1058
+ throw new Error("Can't add plugins after the server has started");
1059
+ }
1060
+ this.internals.plugins.push(plugin);
1061
+ }
1062
+
1063
+ public async executeHTTPGraphQLRequest({
1064
+ httpGraphQLRequest,
1065
+ context,
1066
+ }: {
1067
+ httpGraphQLRequest: HTTPGraphQLRequest;
1068
+ context: ContextThunk<TContext>;
1069
+ }): Promise<HTTPGraphQLResponse> {
1070
+ try {
1071
+ let runningServerState;
1072
+ try {
1073
+ runningServerState = await this._ensureStarted();
1074
+ } catch (error: unknown) {
1075
+ // This is typically either the masked error from when background startup
1076
+ // failed, or related to invoking this function before startup or
1077
+ // during/after shutdown (due to lack of draining).
1078
+ return await this.errorResponse(error, httpGraphQLRequest);
1079
+ }
1080
+
1081
+ if (
1082
+ runningServerState.landingPage &&
1083
+ this.prefersHTML(httpGraphQLRequest)
1084
+ ) {
1085
+ let renderedHtml;
1086
+ if (typeof runningServerState.landingPage.html === 'string') {
1087
+ renderedHtml = runningServerState.landingPage.html;
1088
+ } else {
1089
+ try {
1090
+ renderedHtml = await runningServerState.landingPage.html();
1091
+ } catch (maybeError: unknown) {
1092
+ const error = ensureError(maybeError);
1093
+ this.logger.error(`Landing page \`html\` function threw: ${error}`);
1094
+ return await this.errorResponse(error, httpGraphQLRequest);
1095
+ }
1096
+ }
1097
+
1098
+ return {
1099
+ headers: new HeaderMap([['content-type', 'text/html']]),
1100
+ body: {
1101
+ kind: 'complete',
1102
+ string: renderedHtml,
1103
+ },
1104
+ };
1105
+ }
1106
+
1107
+ // If enabled, check to ensure that this request was preflighted before doing
1108
+ // anything real (such as running the context function).
1109
+ if (this.internals.csrfPreventionRequestHeaders) {
1110
+ preventCsrf(
1111
+ httpGraphQLRequest.headers,
1112
+ this.internals.csrfPreventionRequestHeaders,
1113
+ );
1114
+ }
1115
+
1116
+ let contextValue: TContext;
1117
+ try {
1118
+ contextValue = await context();
1119
+ } catch (maybeError: unknown) {
1120
+ const error = ensureError(maybeError);
1121
+ try {
1122
+ await Promise.all(
1123
+ this.internals.plugins.map(async (plugin) =>
1124
+ plugin.contextCreationDidFail?.({
1125
+ error,
1126
+ }),
1127
+ ),
1128
+ );
1129
+ } catch (pluginError) {
1130
+ this.logger.error(
1131
+ `contextCreationDidFail hook threw: ${pluginError}`,
1132
+ );
1133
+ }
1134
+
1135
+ // If some random function threw, add a helpful prefix when converting
1136
+ // to GraphQLError. If it was already a GraphQLError, trust that the
1137
+ // message was chosen thoughtfully and leave off the prefix.
1138
+ return await this.errorResponse(
1139
+ ensureGraphQLError(error, 'Context creation failed: '),
1140
+ httpGraphQLRequest,
1141
+ );
1142
+ }
1143
+
1144
+ return await runPotentiallyBatchedHttpQuery(
1145
+ this,
1146
+ httpGraphQLRequest,
1147
+ contextValue,
1148
+ runningServerState.schemaManager.getSchemaDerivedData(),
1149
+ this.internals,
1150
+ );
1151
+ } catch (maybeError_: unknown) {
1152
+ const maybeError = maybeError_; // fixes inference because catch vars are not const
1153
+ if (
1154
+ maybeError instanceof GraphQLError &&
1155
+ maybeError.extensions.code === ApolloServerErrorCode.BAD_REQUEST
1156
+ ) {
1157
+ try {
1158
+ await Promise.all(
1159
+ this.internals.plugins.map(async (plugin) =>
1160
+ plugin.invalidRequestWasReceived?.({ error: maybeError }),
1161
+ ),
1162
+ );
1163
+ } catch (pluginError) {
1164
+ this.logger.error(
1165
+ `invalidRequestWasReceived hook threw: ${pluginError}`,
1166
+ );
1167
+ }
1168
+ }
1169
+ return await this.errorResponse(maybeError, httpGraphQLRequest);
1170
+ }
1171
+ }
1172
+
1173
+ private async errorResponse(
1174
+ error: unknown,
1175
+ requestHead: HTTPGraphQLHead,
1176
+ ): Promise<HTTPGraphQLResponse> {
1177
+ const { formattedErrors, httpFromErrors } = normalizeAndFormatErrors(
1178
+ [error],
1179
+ {
1180
+ includeStacktraceInErrorResponses:
1181
+ this.internals.includeStacktraceInErrorResponses,
1182
+ formatError: this.internals.formatError,
1183
+ },
1184
+ );
1185
+
1186
+ return {
1187
+ status: httpFromErrors.status ?? 500,
1188
+ headers: new HeaderMap([
1189
+ ...httpFromErrors.headers,
1190
+ [
1191
+ 'content-type',
1192
+ // Note that we may change the default to
1193
+ // 'application/graphql-response+json' by 2025 as encouraged by the
1194
+ // graphql-over-http spec. It's maybe a bit bad for us to provide
1195
+ // an application/json response if they send `accept: foo/bar`,
1196
+ // but we're already providing some sort of bad request error, and
1197
+ // it's probably more useful for them to fix the other error before
1198
+ // they deal with the `accept` header.
1199
+ chooseContentTypeForSingleResultResponse(requestHead) ??
1200
+ MEDIA_TYPES.APPLICATION_JSON,
1201
+ ],
1202
+ ]),
1203
+ body: {
1204
+ kind: 'complete',
1205
+ string: await this.internals.stringifyResult({
1206
+ errors: formattedErrors,
1207
+ }),
1208
+ },
1209
+ };
1210
+ }
1211
+
1212
+ private prefersHTML(request: HTTPGraphQLRequest): boolean {
1213
+ const acceptHeader = request.headers.get('accept');
1214
+ return (
1215
+ request.method === 'GET' &&
1216
+ !!acceptHeader &&
1217
+ new Negotiator({
1218
+ headers: { accept: acceptHeader },
1219
+ }).mediaType([
1220
+ // We need it to actively prefer text/html over less browser-y types;
1221
+ // eg, `accept: */*' should still go for JSON. Negotiator does tiebreak
1222
+ // by the order in the list we provide, so we put text/html last.
1223
+ MEDIA_TYPES.APPLICATION_JSON,
1224
+ MEDIA_TYPES.APPLICATION_GRAPHQL_RESPONSE_JSON,
1225
+ MEDIA_TYPES.MULTIPART_MIXED_EXPERIMENTAL_ALPHA_2,
1226
+ MEDIA_TYPES.MULTIPART_MIXED_EXPERIMENTAL_ALPHA_9,
1227
+ MEDIA_TYPES.MULTIPART_MIXED_NO_DEFER_SPEC,
1228
+ MEDIA_TYPES.TEXT_HTML,
1229
+ ]) === MEDIA_TYPES.TEXT_HTML
1230
+ );
1231
+ }
1232
+
1233
+ /**
1234
+ * This method is primarily meant for testing: it allows you to execute a
1235
+ * GraphQL operation via the request pipeline without going through the HTTP
1236
+ * layer. Note that this means that any handling you do in your server at the
1237
+ * HTTP level will not affect this call!
1238
+ *
1239
+ * For convenience, you can provide `request.query` either as a string or a
1240
+ * DocumentNode, in case you choose to use the gql tag in your tests. This is
1241
+ * just a convenience, not an optimization (we convert provided ASTs back into
1242
+ * string).
1243
+ *
1244
+ * The second object is an optional options object which includes the optional
1245
+ * `contextValue` object available in resolvers.
1246
+ *
1247
+ * You may specify the TData and TVariables generic types when calling this
1248
+ * method; Apollo Server does not validate that the returned data actually
1249
+ * matches the structure of TData. (Typically these types are created by a
1250
+ * code generation tool.) Note that this does not enforce that `variables` is
1251
+ * provided at all, just that it has the right type if provided.
1252
+ */
1253
+ public async executeOperation<
1254
+ TData = Record<string, unknown>,
1255
+ TVariables extends VariableValues = VariableValues,
1256
+ >(
1257
+ this: ApolloServer<BaseContext>,
1258
+ request: Omit<GraphQLRequest<TVariables>, 'query'> & {
1259
+ query?: string | DocumentNode | TypedQueryDocumentNode<TData, TVariables>;
1260
+ },
1261
+ ): Promise<GraphQLResponse<TData>>;
1262
+ public async executeOperation<
1263
+ TData = Record<string, unknown>,
1264
+ TVariables extends VariableValues = VariableValues,
1265
+ >(
1266
+ request: Omit<GraphQLRequest<TVariables>, 'query'> & {
1267
+ query?: string | DocumentNode | TypedQueryDocumentNode<TData, TVariables>;
1268
+ },
1269
+ options?: ExecuteOperationOptions<TContext>,
1270
+ ): Promise<GraphQLResponse<TData>>;
1271
+
1272
+ async executeOperation<
1273
+ TData = Record<string, unknown>,
1274
+ TVariables extends VariableValues = VariableValues,
1275
+ >(
1276
+ request: Omit<GraphQLRequest<TVariables>, 'query'> & {
1277
+ // We should consider supporting TypedDocumentNode from
1278
+ // `@graphql-typed-document-node/core` as well, as it is more popular than
1279
+ // the newer built-in type.
1280
+ query?: string | DocumentNode | TypedQueryDocumentNode<TData, TVariables>;
1281
+ },
1282
+ options: ExecuteOperationOptions<TContext> = {},
1283
+ ): Promise<GraphQLResponse<TData>> {
1284
+ // Since this function is mostly for testing, you don't need to explicitly
1285
+ // start your server before calling it. (That also means you can use it with
1286
+ // `apollo-server` which doesn't support `start()`.)
1287
+ if (this.internals.state.phase === 'initialized') {
1288
+ await this.start();
1289
+ }
1290
+
1291
+ const schemaDerivedData = (
1292
+ await this._ensureStarted()
1293
+ ).schemaManager.getSchemaDerivedData();
1294
+
1295
+ // For convenience, this function lets you pass either a string or an AST,
1296
+ // but we normalize to string.
1297
+ const graphQLRequest: GraphQLRequest = {
1298
+ ...request,
1299
+ query:
1300
+ request.query && typeof request.query !== 'string'
1301
+ ? print(request.query)
1302
+ : request.query,
1303
+ };
1304
+
1305
+ const response: GraphQLResponse = await internalExecuteOperation(
1306
+ {
1307
+ server: this,
1308
+ graphQLRequest,
1309
+ internals: this.internals,
1310
+ schemaDerivedData,
1311
+ sharedResponseHTTPGraphQLHead: null,
1312
+ },
1313
+ options,
1314
+ );
1315
+
1316
+ // It's your job to set an appropriate TData (perhaps using codegen); we
1317
+ // don't validate it.
1318
+ return response as GraphQLResponse<TData>;
1319
+ }
1320
+ }
1321
+
1322
+ // Shared code between runHttpQuery (ie executeHTTPGraphQLRequest) and
1323
+ // executeOperation to set up a request context and invoke the request pipeline.
1324
+ export async function internalExecuteOperation<TContext extends BaseContext>(
1325
+ {
1326
+ server,
1327
+ graphQLRequest,
1328
+ internals,
1329
+ schemaDerivedData,
1330
+ sharedResponseHTTPGraphQLHead,
1331
+ }: {
1332
+ server: ApolloServer<TContext>;
1333
+ graphQLRequest: GraphQLRequest;
1334
+ internals: ApolloServerInternals<TContext>;
1335
+ schemaDerivedData: SchemaDerivedData;
1336
+ sharedResponseHTTPGraphQLHead: HTTPGraphQLHead | null;
1337
+ },
1338
+ options: ExecuteOperationOptions<TContext>,
1339
+ ): Promise<GraphQLResponse> {
1340
+ const requestContext: GraphQLRequestContext<TContext> = {
1341
+ logger: server.logger,
1342
+ cache: server.cache,
1343
+ schema: schemaDerivedData.schema,
1344
+ request: graphQLRequest,
1345
+ response: {
1346
+ http: sharedResponseHTTPGraphQLHead ?? newHTTPGraphQLHead(),
1347
+ },
1348
+ // We clone the context because there are some assumptions that every operation
1349
+ // execution has a brand new context object; specifically, in order to implement
1350
+ // willResolveField we put a Symbol on the context that is specific to a particular
1351
+ // request pipeline execution. We could avoid this if we had a better way of
1352
+ // instrumenting execution.
1353
+ //
1354
+ // We don't want to do a deep clone here, because one of the main advantages of
1355
+ // using batched HTTP requests is to share context across operations for a
1356
+ // single request.
1357
+ //
1358
+ // The typecast here is safe, because the only way `contextValue` can be
1359
+ // null-ish is if we used the `contextValue?: BaseContext` override, in
1360
+ // which case TContext is BaseContext and {} is ok. (This does depend on
1361
+ // the fact we've hackily forced the class to be contravariant in
1362
+ // TContext.)
1363
+ contextValue: cloneObject(options?.contextValue ?? ({} as TContext)),
1364
+ metrics: {},
1365
+ overallCachePolicy: newCachePolicy(),
1366
+ requestIsBatched: sharedResponseHTTPGraphQLHead !== null,
1367
+ };
1368
+
1369
+ try {
1370
+ return await processGraphQLRequest(
1371
+ schemaDerivedData,
1372
+ server,
1373
+ internals,
1374
+ requestContext,
1375
+ );
1376
+ } catch (maybeError: unknown) {
1377
+ // processGraphQLRequest throwing usually means that either there's a bug in
1378
+ // Apollo Server or some plugin hook threw unexpectedly.
1379
+ const error = ensureError(maybeError);
1380
+ // If *these* hooks throw then we'll still get a 500 but won't mask its
1381
+ // error.
1382
+ await Promise.all(
1383
+ internals.plugins.map(async (plugin) =>
1384
+ plugin.unexpectedErrorProcessingRequest?.({
1385
+ requestContext,
1386
+ error,
1387
+ }),
1388
+ ),
1389
+ );
1390
+ // Mask unexpected error externally.
1391
+ server.logger.error(`Unexpected error processing request: ${error}`);
1392
+ throw new Error('Internal server error');
1393
+ }
1394
+ }
1395
+
1396
+ // Unlike InternalPlugins (where we can decide whether to install the default
1397
+ // plugin based on looking at which plugins are installed),
1398
+ // ImplicitlyInstallablePlugins (ie the default landing page plugin) can't
1399
+ // determine if they're needed until later in startup. Specifically, we can't
1400
+ // know if we've defined our own landing page until after serverWillStart
1401
+ // plugins have run.
1402
+ export type ImplicitlyInstallablePlugin<TContext extends BaseContext> =
1403
+ ApolloServerPlugin<TContext> & {
1404
+ __internal_installed_implicitly__: boolean;
1405
+ };
1406
+
1407
+ export function isImplicitlyInstallablePlugin<TContext extends BaseContext>(
1408
+ p: ApolloServerPlugin<TContext>,
1409
+ ): p is ImplicitlyInstallablePlugin<TContext> {
1410
+ return '__internal_installed_implicitly__' in p;
1411
+ }
1412
+
1413
+ export const MEDIA_TYPES = {
1414
+ APPLICATION_JSON: 'application/json; charset=utf-8',
1415
+ APPLICATION_JSON_GRAPHQL_CALLBACK:
1416
+ 'application/json; callbackSpec=1.0; charset=utf-8',
1417
+ APPLICATION_GRAPHQL_RESPONSE_JSON:
1418
+ 'application/graphql-response+json; charset=utf-8',
1419
+ // We do *not* currently support this content-type; we will once incremental
1420
+ // delivery is part of the official GraphQL spec.
1421
+ MULTIPART_MIXED_NO_DEFER_SPEC: 'multipart/mixed',
1422
+ MULTIPART_MIXED_EXPERIMENTAL_ALPHA_2: 'multipart/mixed; deferSpec=20220824',
1423
+ // This references the spec stored at
1424
+ // https://specs.apollo.dev/incremental/v0.2/
1425
+ MULTIPART_MIXED_EXPERIMENTAL_ALPHA_9: 'multipart/mixed; incrementalSpec=v0.2',
1426
+ TEXT_HTML: 'text/html',
1427
+ };
1428
+
1429
+ export function chooseContentTypeForSingleResultResponse(
1430
+ head: HTTPGraphQLHead,
1431
+ ): string | null {
1432
+ const acceptHeader = head.headers.get('accept');
1433
+ if (!acceptHeader) {
1434
+ // Note that we may change the default to
1435
+ // 'application/graphql-response+json' by 2025 as encouraged by the
1436
+ // graphql-over-http spec.
1437
+ return MEDIA_TYPES.APPLICATION_JSON;
1438
+ } else {
1439
+ const preferred = new Negotiator({
1440
+ headers: { accept: head.headers.get('accept') },
1441
+ }).mediaType([
1442
+ MEDIA_TYPES.APPLICATION_JSON,
1443
+ MEDIA_TYPES.APPLICATION_GRAPHQL_RESPONSE_JSON,
1444
+ MEDIA_TYPES.APPLICATION_JSON_GRAPHQL_CALLBACK,
1445
+ ]);
1446
+ if (preferred) {
1447
+ return preferred;
1448
+ } else {
1449
+ return null;
1450
+ }
1451
+ }
1452
+ }
1453
+
1454
+ function cloneObject<T extends Object>(object: T): T {
1455
+ return Object.assign(Object.create(Object.getPrototypeOf(object)), object);
1456
+ }