@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.
- package/README.md +40 -0
- package/changes.json +46 -0
- package/dist/cjs/ApolloServer.d.ts +126 -0
- package/dist/cjs/ApolloServer.d.ts.map +1 -0
- package/dist/cjs/ApolloServer.js +726 -0
- package/dist/cjs/ApolloServer.js.map +1 -0
- package/dist/cjs/cachePolicy.d.ts +3 -0
- package/dist/cjs/cachePolicy.d.ts.map +1 -0
- package/dist/cjs/cachePolicy.js +33 -0
- package/dist/cjs/cachePolicy.js.map +1 -0
- package/dist/cjs/determineApolloConfig.d.ts +4 -0
- package/dist/cjs/determineApolloConfig.d.ts.map +1 -0
- package/dist/cjs/determineApolloConfig.js +58 -0
- package/dist/cjs/determineApolloConfig.js.map +1 -0
- package/dist/cjs/errorNormalize.d.ts +12 -0
- package/dist/cjs/errorNormalize.d.ts.map +1 -0
- package/dist/cjs/errorNormalize.js +71 -0
- package/dist/cjs/errorNormalize.js.map +1 -0
- package/dist/cjs/errors/index.d.ts +16 -0
- package/dist/cjs/errors/index.d.ts.map +1 -0
- package/dist/cjs/errors/index.js +28 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/externalTypes/constructor.d.ts +78 -0
- package/dist/cjs/externalTypes/constructor.d.ts.map +1 -0
- package/dist/cjs/externalTypes/constructor.js +3 -0
- package/dist/cjs/externalTypes/constructor.js.map +1 -0
- package/dist/cjs/externalTypes/context.d.ts +4 -0
- package/dist/cjs/externalTypes/context.d.ts.map +1 -0
- package/dist/cjs/externalTypes/context.js +3 -0
- package/dist/cjs/externalTypes/context.js.map +1 -0
- package/dist/cjs/externalTypes/graphql.d.ts +41 -0
- package/dist/cjs/externalTypes/graphql.d.ts.map +1 -0
- package/dist/cjs/externalTypes/graphql.js +3 -0
- package/dist/cjs/externalTypes/graphql.js.map +1 -0
- package/dist/cjs/externalTypes/http.d.ts +22 -0
- package/dist/cjs/externalTypes/http.d.ts.map +1 -0
- package/dist/cjs/externalTypes/http.js +3 -0
- package/dist/cjs/externalTypes/http.js.map +1 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts +28 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts.map +1 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.js +3 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha2.js.map +1 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts +43 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts.map +1 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.js +3 -0
- package/dist/cjs/externalTypes/incrementalDeliveryPolyfillAlpha9.js.map +1 -0
- package/dist/cjs/externalTypes/index.d.ts +9 -0
- package/dist/cjs/externalTypes/index.d.ts.map +1 -0
- package/dist/cjs/externalTypes/index.js +3 -0
- package/dist/cjs/externalTypes/index.js.map +1 -0
- package/dist/cjs/externalTypes/plugins.d.ts +75 -0
- package/dist/cjs/externalTypes/plugins.d.ts.map +1 -0
- package/dist/cjs/externalTypes/plugins.js +3 -0
- package/dist/cjs/externalTypes/plugins.js.map +1 -0
- package/dist/cjs/externalTypes/requestPipeline.d.ts +50 -0
- package/dist/cjs/externalTypes/requestPipeline.d.ts.map +1 -0
- package/dist/cjs/externalTypes/requestPipeline.js +3 -0
- package/dist/cjs/externalTypes/requestPipeline.js.map +1 -0
- package/dist/cjs/generated/packageVersion.d.ts +2 -0
- package/dist/cjs/generated/packageVersion.d.ts.map +1 -0
- package/dist/cjs/generated/packageVersion.js +5 -0
- package/dist/cjs/generated/packageVersion.js.map +1 -0
- package/dist/cjs/httpBatching.d.ts +4 -0
- package/dist/cjs/httpBatching.d.ts.map +1 -0
- package/dist/cjs/httpBatching.js +58 -0
- package/dist/cjs/httpBatching.js.map +1 -0
- package/dist/cjs/incrementalDeliveryPolyfill.d.ts +82 -0
- package/dist/cjs/incrementalDeliveryPolyfill.d.ts.map +1 -0
- package/dist/cjs/incrementalDeliveryPolyfill.js +74 -0
- package/dist/cjs/incrementalDeliveryPolyfill.js.map +1 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +23 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/internalErrorClasses.d.ts +28 -0
- package/dist/cjs/internalErrorClasses.d.ts.map +1 -0
- package/dist/cjs/internalErrorClasses.js +91 -0
- package/dist/cjs/internalErrorClasses.js.map +1 -0
- package/dist/cjs/internalPlugin.d.ts +9 -0
- package/dist/cjs/internalPlugin.d.ts.map +1 -0
- package/dist/cjs/internalPlugin.js +11 -0
- package/dist/cjs/internalPlugin.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/plugin/cacheControl/index.d.ts +9 -0
- package/dist/cjs/plugin/cacheControl/index.d.ts.map +1 -0
- package/dist/cjs/plugin/cacheControl/index.js +223 -0
- package/dist/cjs/plugin/cacheControl/index.js.map +1 -0
- package/dist/cjs/plugin/disableSuggestions/index.d.ts +3 -0
- package/dist/cjs/plugin/disableSuggestions/index.d.ts.map +1 -0
- package/dist/cjs/plugin/disableSuggestions/index.js +22 -0
- package/dist/cjs/plugin/disableSuggestions/index.js.map +1 -0
- package/dist/cjs/plugin/disabled/index.d.ts +7 -0
- package/dist/cjs/plugin/disabled/index.d.ts.map +1 -0
- package/dist/cjs/plugin/disabled/index.js +30 -0
- package/dist/cjs/plugin/disabled/index.js.map +1 -0
- package/dist/cjs/plugin/drainHttpServer/index.d.ts +8 -0
- package/dist/cjs/plugin/drainHttpServer/index.d.ts.map +1 -0
- package/dist/cjs/plugin/drainHttpServer/index.js +19 -0
- package/dist/cjs/plugin/drainHttpServer/index.js.map +1 -0
- package/dist/cjs/plugin/drainHttpServer/stoppable.d.ts +10 -0
- package/dist/cjs/plugin/drainHttpServer/stoppable.d.ts.map +1 -0
- package/dist/cjs/plugin/drainHttpServer/stoppable.js +54 -0
- package/dist/cjs/plugin/drainHttpServer/stoppable.js.map +1 -0
- package/dist/cjs/plugin/inlineTrace/index.d.ts +8 -0
- package/dist/cjs/plugin/inlineTrace/index.d.ts.map +1 -0
- package/dist/cjs/plugin/inlineTrace/index.js +70 -0
- package/dist/cjs/plugin/inlineTrace/index.js.map +1 -0
- package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.d.ts +4 -0
- package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.d.ts.map +1 -0
- package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.js +143 -0
- package/dist/cjs/plugin/landingPage/default/getEmbeddedHTML.js.map +1 -0
- package/dist/cjs/plugin/landingPage/default/index.d.ts +9 -0
- package/dist/cjs/plugin/landingPage/default/index.d.ts.map +1 -0
- package/dist/cjs/plugin/landingPage/default/index.js +146 -0
- package/dist/cjs/plugin/landingPage/default/index.js.map +1 -0
- package/dist/cjs/plugin/landingPage/default/types.d.ts +56 -0
- package/dist/cjs/plugin/landingPage/default/types.d.ts.map +1 -0
- package/dist/cjs/plugin/landingPage/default/types.js +3 -0
- package/dist/cjs/plugin/landingPage/default/types.js.map +1 -0
- package/dist/cjs/plugin/schemaIsSubgraph.d.ts +3 -0
- package/dist/cjs/plugin/schemaIsSubgraph.d.ts.map +1 -0
- package/dist/cjs/plugin/schemaIsSubgraph.js +23 -0
- package/dist/cjs/plugin/schemaIsSubgraph.js.map +1 -0
- package/dist/cjs/plugin/schemaReporting/index.d.ts +10 -0
- package/dist/cjs/plugin/schemaReporting/index.d.ts.map +1 -0
- package/dist/cjs/plugin/schemaReporting/index.js +104 -0
- package/dist/cjs/plugin/schemaReporting/index.js.map +1 -0
- package/dist/cjs/plugin/schemaReporting/schemaReporter.d.ts +33 -0
- package/dist/cjs/plugin/schemaReporting/schemaReporter.d.ts.map +1 -0
- package/dist/cjs/plugin/schemaReporting/schemaReporter.js +147 -0
- package/dist/cjs/plugin/schemaReporting/schemaReporter.js.map +1 -0
- package/dist/cjs/plugin/subscriptionCallback/index.d.ts +12 -0
- package/dist/cjs/plugin/subscriptionCallback/index.d.ts.map +1 -0
- package/dist/cjs/plugin/subscriptionCallback/index.js +434 -0
- package/dist/cjs/plugin/subscriptionCallback/index.js.map +1 -0
- package/dist/cjs/plugin/traceTreeBuilder.d.ts +25 -0
- package/dist/cjs/plugin/traceTreeBuilder.d.ts.map +1 -0
- package/dist/cjs/plugin/traceTreeBuilder.js +201 -0
- package/dist/cjs/plugin/traceTreeBuilder.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts +3 -0
- package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.js +44 -0
- package/dist/cjs/plugin/usageReporting/defaultSendOperationsAsTrace.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/durationHistogram.d.ts +16 -0
- package/dist/cjs/plugin/usageReporting/durationHistogram.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/durationHistogram.js +68 -0
- package/dist/cjs/plugin/usageReporting/durationHistogram.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/index.d.ts +3 -0
- package/dist/cjs/plugin/usageReporting/index.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/index.js +6 -0
- package/dist/cjs/plugin/usageReporting/index.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/iterateOverTrace.d.ts +7 -0
- package/dist/cjs/plugin/usageReporting/iterateOverTrace.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/iterateOverTrace.js +81 -0
- package/dist/cjs/plugin/usageReporting/iterateOverTrace.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.d.ts +12 -0
- package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.js +33 -0
- package/dist/cjs/plugin/usageReporting/operationDerivedDataCache.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/options.d.ts +60 -0
- package/dist/cjs/plugin/usageReporting/options.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/options.js +3 -0
- package/dist/cjs/plugin/usageReporting/options.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/plugin.d.ts +7 -0
- package/dist/cjs/plugin/usageReporting/plugin.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/plugin.js +494 -0
- package/dist/cjs/plugin/usageReporting/plugin.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/stats.d.ts +96 -0
- package/dist/cjs/plugin/usageReporting/stats.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/stats.js +289 -0
- package/dist/cjs/plugin/usageReporting/stats.js.map +1 -0
- package/dist/cjs/plugin/usageReporting/traceDetails.d.ts +4 -0
- package/dist/cjs/plugin/usageReporting/traceDetails.d.ts.map +1 -0
- package/dist/cjs/plugin/usageReporting/traceDetails.js +63 -0
- package/dist/cjs/plugin/usageReporting/traceDetails.js.map +1 -0
- package/dist/cjs/preventCsrf.d.ts +4 -0
- package/dist/cjs/preventCsrf.d.ts.map +1 -0
- package/dist/cjs/preventCsrf.js +41 -0
- package/dist/cjs/preventCsrf.js.map +1 -0
- package/dist/cjs/requestPipeline.d.ts +9 -0
- package/dist/cjs/requestPipeline.d.ts.map +1 -0
- package/dist/cjs/requestPipeline.js +371 -0
- package/dist/cjs/requestPipeline.js.map +1 -0
- package/dist/cjs/runHttpQuery.d.ts +15 -0
- package/dist/cjs/runHttpQuery.d.ts.map +1 -0
- package/dist/cjs/runHttpQuery.js +230 -0
- package/dist/cjs/runHttpQuery.js.map +1 -0
- package/dist/cjs/standalone/index.d.ts +25 -0
- package/dist/cjs/standalone/index.d.ts.map +1 -0
- package/dist/cjs/standalone/index.js +97 -0
- package/dist/cjs/standalone/index.js.map +1 -0
- package/dist/cjs/utils/HeaderMap.d.ts +8 -0
- package/dist/cjs/utils/HeaderMap.d.ts.map +1 -0
- package/dist/cjs/utils/HeaderMap.js +20 -0
- package/dist/cjs/utils/HeaderMap.js.map +1 -0
- package/dist/cjs/utils/UnreachableCaseError.d.ts +4 -0
- package/dist/cjs/utils/UnreachableCaseError.d.ts.map +1 -0
- package/dist/cjs/utils/UnreachableCaseError.js +10 -0
- package/dist/cjs/utils/UnreachableCaseError.js.map +1 -0
- package/dist/cjs/utils/computeCoreSchemaHash.d.ts +2 -0
- package/dist/cjs/utils/computeCoreSchemaHash.d.ts.map +1 -0
- package/dist/cjs/utils/computeCoreSchemaHash.js +8 -0
- package/dist/cjs/utils/computeCoreSchemaHash.js.map +1 -0
- package/dist/cjs/utils/invokeHooks.d.ts +7 -0
- package/dist/cjs/utils/invokeHooks.d.ts.map +1 -0
- package/dist/cjs/utils/invokeHooks.js +36 -0
- package/dist/cjs/utils/invokeHooks.js.map +1 -0
- package/dist/cjs/utils/isDefined.d.ts +2 -0
- package/dist/cjs/utils/isDefined.d.ts.map +1 -0
- package/dist/cjs/utils/isDefined.js +7 -0
- package/dist/cjs/utils/isDefined.js.map +1 -0
- package/dist/cjs/utils/makeGatewayGraphQLRequestContext.d.ts +5 -0
- package/dist/cjs/utils/makeGatewayGraphQLRequestContext.d.ts.map +1 -0
- package/dist/cjs/utils/makeGatewayGraphQLRequestContext.js +96 -0
- package/dist/cjs/utils/makeGatewayGraphQLRequestContext.js.map +1 -0
- package/dist/cjs/utils/resolvable.d.ts +7 -0
- package/dist/cjs/utils/resolvable.d.ts.map +1 -0
- package/dist/cjs/utils/resolvable.js +14 -0
- package/dist/cjs/utils/resolvable.js.map +1 -0
- package/dist/cjs/utils/schemaInstrumentation.d.ts +16 -0
- package/dist/cjs/utils/schemaInstrumentation.d.ts.map +1 -0
- package/dist/cjs/utils/schemaInstrumentation.js +75 -0
- package/dist/cjs/utils/schemaInstrumentation.js.map +1 -0
- package/dist/cjs/utils/schemaManager.d.ts +31 -0
- package/dist/cjs/utils/schemaManager.d.ts.map +1 -0
- package/dist/cjs/utils/schemaManager.js +103 -0
- package/dist/cjs/utils/schemaManager.js.map +1 -0
- package/dist/cjs/utils/urlForHttpServer.d.ts +3 -0
- package/dist/cjs/utils/urlForHttpServer.d.ts.map +1 -0
- package/dist/cjs/utils/urlForHttpServer.js +15 -0
- package/dist/cjs/utils/urlForHttpServer.js.map +1 -0
- package/dist/cjs/validationRules/NoIntrospection.d.ts +3 -0
- package/dist/cjs/validationRules/NoIntrospection.d.ts.map +1 -0
- package/dist/cjs/validationRules/NoIntrospection.js +19 -0
- package/dist/cjs/validationRules/NoIntrospection.js.map +1 -0
- package/dist/cjs/validationRules/RecursiveSelectionsLimit.d.ts +4 -0
- package/dist/cjs/validationRules/RecursiveSelectionsLimit.d.ts.map +1 -0
- package/dist/cjs/validationRules/RecursiveSelectionsLimit.js +150 -0
- package/dist/cjs/validationRules/RecursiveSelectionsLimit.js.map +1 -0
- package/dist/cjs/validationRules/index.d.ts +3 -0
- package/dist/cjs/validationRules/index.d.ts.map +1 -0
- package/dist/cjs/validationRules/index.js +9 -0
- package/dist/cjs/validationRules/index.js.map +1 -0
- package/dist/esm/ApolloServer.d.ts +126 -0
- package/dist/esm/ApolloServer.d.ts.map +1 -0
- package/dist/esm/ApolloServer.js +683 -0
- package/dist/esm/ApolloServer.js.map +1 -0
- package/dist/esm/cachePolicy.d.ts +3 -0
- package/dist/esm/cachePolicy.d.ts.map +1 -0
- package/dist/esm/cachePolicy.js +30 -0
- package/dist/esm/cachePolicy.js.map +1 -0
- package/dist/esm/determineApolloConfig.d.ts +4 -0
- package/dist/esm/determineApolloConfig.d.ts.map +1 -0
- package/dist/esm/determineApolloConfig.js +55 -0
- package/dist/esm/determineApolloConfig.js.map +1 -0
- package/dist/esm/errorNormalize.d.ts +12 -0
- package/dist/esm/errorNormalize.d.ts.map +1 -0
- package/dist/esm/errorNormalize.js +66 -0
- package/dist/esm/errorNormalize.js.map +1 -0
- package/dist/esm/errors/index.d.ts +16 -0
- package/dist/esm/errors/index.d.ts.map +1 -0
- package/dist/esm/errors/index.js +24 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/externalTypes/constructor.d.ts +78 -0
- package/dist/esm/externalTypes/constructor.d.ts.map +1 -0
- package/dist/esm/externalTypes/constructor.js +2 -0
- package/dist/esm/externalTypes/constructor.js.map +1 -0
- package/dist/esm/externalTypes/context.d.ts +4 -0
- package/dist/esm/externalTypes/context.d.ts.map +1 -0
- package/dist/esm/externalTypes/context.js +2 -0
- package/dist/esm/externalTypes/context.js.map +1 -0
- package/dist/esm/externalTypes/graphql.d.ts +41 -0
- package/dist/esm/externalTypes/graphql.d.ts.map +1 -0
- package/dist/esm/externalTypes/graphql.js +2 -0
- package/dist/esm/externalTypes/graphql.js.map +1 -0
- package/dist/esm/externalTypes/http.d.ts +22 -0
- package/dist/esm/externalTypes/http.d.ts.map +1 -0
- package/dist/esm/externalTypes/http.js +2 -0
- package/dist/esm/externalTypes/http.js.map +1 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts +28 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.d.ts.map +1 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.js +2 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha2.js.map +1 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts +43 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.d.ts.map +1 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.js +2 -0
- package/dist/esm/externalTypes/incrementalDeliveryPolyfillAlpha9.js.map +1 -0
- package/dist/esm/externalTypes/index.d.ts +9 -0
- package/dist/esm/externalTypes/index.d.ts.map +1 -0
- package/dist/esm/externalTypes/index.js +2 -0
- package/dist/esm/externalTypes/index.js.map +1 -0
- package/dist/esm/externalTypes/plugins.d.ts +75 -0
- package/dist/esm/externalTypes/plugins.d.ts.map +1 -0
- package/dist/esm/externalTypes/plugins.js +2 -0
- package/dist/esm/externalTypes/plugins.js.map +1 -0
- package/dist/esm/externalTypes/requestPipeline.d.ts +50 -0
- package/dist/esm/externalTypes/requestPipeline.d.ts.map +1 -0
- package/dist/esm/externalTypes/requestPipeline.js +2 -0
- package/dist/esm/externalTypes/requestPipeline.js.map +1 -0
- package/dist/esm/generated/packageVersion.d.ts +2 -0
- package/dist/esm/generated/packageVersion.d.ts.map +1 -0
- package/dist/esm/generated/packageVersion.js +2 -0
- package/dist/esm/generated/packageVersion.js.map +1 -0
- package/dist/esm/httpBatching.d.ts +4 -0
- package/dist/esm/httpBatching.d.ts.map +1 -0
- package/dist/esm/httpBatching.js +55 -0
- package/dist/esm/httpBatching.js.map +1 -0
- package/dist/esm/incrementalDeliveryPolyfill.d.ts +82 -0
- package/dist/esm/incrementalDeliveryPolyfill.d.ts.map +1 -0
- package/dist/esm/incrementalDeliveryPolyfill.js +38 -0
- package/dist/esm/incrementalDeliveryPolyfill.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internalErrorClasses.d.ts +28 -0
- package/dist/esm/internalErrorClasses.d.ts.map +1 -0
- package/dist/esm/internalErrorClasses.js +81 -0
- package/dist/esm/internalErrorClasses.js.map +1 -0
- package/dist/esm/internalPlugin.d.ts +9 -0
- package/dist/esm/internalPlugin.d.ts.map +1 -0
- package/dist/esm/internalPlugin.js +7 -0
- package/dist/esm/internalPlugin.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/plugin/cacheControl/index.d.ts +9 -0
- package/dist/esm/plugin/cacheControl/index.d.ts.map +1 -0
- package/dist/esm/plugin/cacheControl/index.js +220 -0
- package/dist/esm/plugin/cacheControl/index.js.map +1 -0
- package/dist/esm/plugin/disableSuggestions/index.d.ts +3 -0
- package/dist/esm/plugin/disableSuggestions/index.d.ts.map +1 -0
- package/dist/esm/plugin/disableSuggestions/index.js +19 -0
- package/dist/esm/plugin/disableSuggestions/index.js.map +1 -0
- package/dist/esm/plugin/disabled/index.d.ts +7 -0
- package/dist/esm/plugin/disabled/index.d.ts.map +1 -0
- package/dist/esm/plugin/disabled/index.js +23 -0
- package/dist/esm/plugin/disabled/index.js.map +1 -0
- package/dist/esm/plugin/drainHttpServer/index.d.ts +8 -0
- package/dist/esm/plugin/drainHttpServer/index.d.ts.map +1 -0
- package/dist/esm/plugin/drainHttpServer/index.js +16 -0
- package/dist/esm/plugin/drainHttpServer/index.js.map +1 -0
- package/dist/esm/plugin/drainHttpServer/stoppable.d.ts +10 -0
- package/dist/esm/plugin/drainHttpServer/stoppable.d.ts.map +1 -0
- package/dist/esm/plugin/drainHttpServer/stoppable.js +47 -0
- package/dist/esm/plugin/drainHttpServer/stoppable.js.map +1 -0
- package/dist/esm/plugin/inlineTrace/index.d.ts +8 -0
- package/dist/esm/plugin/inlineTrace/index.d.ts.map +1 -0
- package/dist/esm/plugin/inlineTrace/index.js +67 -0
- package/dist/esm/plugin/inlineTrace/index.js.map +1 -0
- package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.d.ts +4 -0
- package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.d.ts.map +1 -0
- package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.js +138 -0
- package/dist/esm/plugin/landingPage/default/getEmbeddedHTML.js.map +1 -0
- package/dist/esm/plugin/landingPage/default/index.d.ts +9 -0
- package/dist/esm/plugin/landingPage/default/index.d.ts.map +1 -0
- package/dist/esm/plugin/landingPage/default/index.js +141 -0
- package/dist/esm/plugin/landingPage/default/index.js.map +1 -0
- package/dist/esm/plugin/landingPage/default/types.d.ts +56 -0
- package/dist/esm/plugin/landingPage/default/types.d.ts.map +1 -0
- package/dist/esm/plugin/landingPage/default/types.js +2 -0
- package/dist/esm/plugin/landingPage/default/types.js.map +1 -0
- package/dist/esm/plugin/schemaIsSubgraph.d.ts +3 -0
- package/dist/esm/plugin/schemaIsSubgraph.d.ts.map +1 -0
- package/dist/esm/plugin/schemaIsSubgraph.js +20 -0
- package/dist/esm/plugin/schemaIsSubgraph.js.map +1 -0
- package/dist/esm/plugin/schemaReporting/index.d.ts +10 -0
- package/dist/esm/plugin/schemaReporting/index.d.ts.map +1 -0
- package/dist/esm/plugin/schemaReporting/index.js +98 -0
- package/dist/esm/plugin/schemaReporting/index.js.map +1 -0
- package/dist/esm/plugin/schemaReporting/schemaReporter.d.ts +33 -0
- package/dist/esm/plugin/schemaReporting/schemaReporter.d.ts.map +1 -0
- package/dist/esm/plugin/schemaReporting/schemaReporter.js +143 -0
- package/dist/esm/plugin/schemaReporting/schemaReporter.js.map +1 -0
- package/dist/esm/plugin/subscriptionCallback/index.d.ts +12 -0
- package/dist/esm/plugin/subscriptionCallback/index.d.ts.map +1 -0
- package/dist/esm/plugin/subscriptionCallback/index.js +428 -0
- package/dist/esm/plugin/subscriptionCallback/index.js.map +1 -0
- package/dist/esm/plugin/traceTreeBuilder.d.ts +25 -0
- package/dist/esm/plugin/traceTreeBuilder.d.ts.map +1 -0
- package/dist/esm/plugin/traceTreeBuilder.js +196 -0
- package/dist/esm/plugin/traceTreeBuilder.js.map +1 -0
- package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts +3 -0
- package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.js +41 -0
- package/dist/esm/plugin/usageReporting/defaultSendOperationsAsTrace.js.map +1 -0
- package/dist/esm/plugin/usageReporting/durationHistogram.d.ts +16 -0
- package/dist/esm/plugin/usageReporting/durationHistogram.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/durationHistogram.js +64 -0
- package/dist/esm/plugin/usageReporting/durationHistogram.js.map +1 -0
- package/dist/esm/plugin/usageReporting/index.d.ts +3 -0
- package/dist/esm/plugin/usageReporting/index.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/index.js +2 -0
- package/dist/esm/plugin/usageReporting/index.js.map +1 -0
- package/dist/esm/plugin/usageReporting/iterateOverTrace.d.ts +7 -0
- package/dist/esm/plugin/usageReporting/iterateOverTrace.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/iterateOverTrace.js +78 -0
- package/dist/esm/plugin/usageReporting/iterateOverTrace.js.map +1 -0
- package/dist/esm/plugin/usageReporting/operationDerivedDataCache.d.ts +12 -0
- package/dist/esm/plugin/usageReporting/operationDerivedDataCache.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/operationDerivedDataCache.js +29 -0
- package/dist/esm/plugin/usageReporting/operationDerivedDataCache.js.map +1 -0
- package/dist/esm/plugin/usageReporting/options.d.ts +60 -0
- package/dist/esm/plugin/usageReporting/options.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/options.js +2 -0
- package/dist/esm/plugin/usageReporting/options.js.map +1 -0
- package/dist/esm/plugin/usageReporting/plugin.d.ts +7 -0
- package/dist/esm/plugin/usageReporting/plugin.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/plugin.js +487 -0
- package/dist/esm/plugin/usageReporting/plugin.js.map +1 -0
- package/dist/esm/plugin/usageReporting/stats.d.ts +96 -0
- package/dist/esm/plugin/usageReporting/stats.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/stats.js +283 -0
- package/dist/esm/plugin/usageReporting/stats.js.map +1 -0
- package/dist/esm/plugin/usageReporting/traceDetails.d.ts +4 -0
- package/dist/esm/plugin/usageReporting/traceDetails.d.ts.map +1 -0
- package/dist/esm/plugin/usageReporting/traceDetails.js +60 -0
- package/dist/esm/plugin/usageReporting/traceDetails.js.map +1 -0
- package/dist/esm/preventCsrf.d.ts +4 -0
- package/dist/esm/preventCsrf.d.ts.map +1 -0
- package/dist/esm/preventCsrf.js +34 -0
- package/dist/esm/preventCsrf.js.map +1 -0
- package/dist/esm/requestPipeline.d.ts +9 -0
- package/dist/esm/requestPipeline.d.ts.map +1 -0
- package/dist/esm/requestPipeline.js +364 -0
- package/dist/esm/requestPipeline.js.map +1 -0
- package/dist/esm/runHttpQuery.d.ts +15 -0
- package/dist/esm/runHttpQuery.d.ts.map +1 -0
- package/dist/esm/runHttpQuery.js +221 -0
- package/dist/esm/runHttpQuery.js.map +1 -0
- package/dist/esm/standalone/index.d.ts +25 -0
- package/dist/esm/standalone/index.d.ts.map +1 -0
- package/dist/esm/standalone/index.js +91 -0
- package/dist/esm/standalone/index.js.map +1 -0
- package/dist/esm/utils/HeaderMap.d.ts +8 -0
- package/dist/esm/utils/HeaderMap.d.ts.map +1 -0
- package/dist/esm/utils/HeaderMap.js +16 -0
- package/dist/esm/utils/HeaderMap.js.map +1 -0
- package/dist/esm/utils/UnreachableCaseError.d.ts +4 -0
- package/dist/esm/utils/UnreachableCaseError.d.ts.map +1 -0
- package/dist/esm/utils/UnreachableCaseError.js +6 -0
- package/dist/esm/utils/UnreachableCaseError.js.map +1 -0
- package/dist/esm/utils/computeCoreSchemaHash.d.ts +2 -0
- package/dist/esm/utils/computeCoreSchemaHash.d.ts.map +1 -0
- package/dist/esm/utils/computeCoreSchemaHash.js +5 -0
- package/dist/esm/utils/computeCoreSchemaHash.js.map +1 -0
- package/dist/esm/utils/invokeHooks.d.ts +7 -0
- package/dist/esm/utils/invokeHooks.d.ts.map +1 -0
- package/dist/esm/utils/invokeHooks.js +31 -0
- package/dist/esm/utils/invokeHooks.js.map +1 -0
- package/dist/esm/utils/isDefined.d.ts +2 -0
- package/dist/esm/utils/isDefined.d.ts.map +1 -0
- package/dist/esm/utils/isDefined.js +4 -0
- package/dist/esm/utils/isDefined.js.map +1 -0
- package/dist/esm/utils/makeGatewayGraphQLRequestContext.d.ts +5 -0
- package/dist/esm/utils/makeGatewayGraphQLRequestContext.d.ts.map +1 -0
- package/dist/esm/utils/makeGatewayGraphQLRequestContext.js +93 -0
- package/dist/esm/utils/makeGatewayGraphQLRequestContext.js.map +1 -0
- package/dist/esm/utils/resolvable.d.ts +7 -0
- package/dist/esm/utils/resolvable.d.ts.map +1 -0
- package/dist/esm/utils/resolvable.js +12 -0
- package/dist/esm/utils/resolvable.js.map +1 -0
- package/dist/esm/utils/schemaInstrumentation.d.ts +16 -0
- package/dist/esm/utils/schemaInstrumentation.d.ts.map +1 -0
- package/dist/esm/utils/schemaInstrumentation.js +69 -0
- package/dist/esm/utils/schemaInstrumentation.js.map +1 -0
- package/dist/esm/utils/schemaManager.d.ts +31 -0
- package/dist/esm/utils/schemaManager.d.ts.map +1 -0
- package/dist/esm/utils/schemaManager.js +99 -0
- package/dist/esm/utils/schemaManager.js.map +1 -0
- package/dist/esm/utils/urlForHttpServer.d.ts +3 -0
- package/dist/esm/utils/urlForHttpServer.d.ts.map +1 -0
- package/dist/esm/utils/urlForHttpServer.js +12 -0
- package/dist/esm/utils/urlForHttpServer.js.map +1 -0
- package/dist/esm/validationRules/NoIntrospection.d.ts +3 -0
- package/dist/esm/validationRules/NoIntrospection.d.ts.map +1 -0
- package/dist/esm/validationRules/NoIntrospection.js +15 -0
- package/dist/esm/validationRules/NoIntrospection.js.map +1 -0
- package/dist/esm/validationRules/RecursiveSelectionsLimit.d.ts +4 -0
- package/dist/esm/validationRules/RecursiveSelectionsLimit.d.ts.map +1 -0
- package/dist/esm/validationRules/RecursiveSelectionsLimit.js +146 -0
- package/dist/esm/validationRules/RecursiveSelectionsLimit.js.map +1 -0
- package/dist/esm/validationRules/index.d.ts +3 -0
- package/dist/esm/validationRules/index.d.ts.map +1 -0
- package/dist/esm/validationRules/index.js +3 -0
- package/dist/esm/validationRules/index.js.map +1 -0
- package/errors/package.json +8 -0
- package/package.json +208 -0
- package/plugin/cacheControl/package.json +8 -0
- package/plugin/disableSuggestions/package.json +8 -0
- package/plugin/disabled/package.json +8 -0
- package/plugin/drainHttpServer/package.json +8 -0
- package/plugin/inlineTrace/package.json +8 -0
- package/plugin/landingPage/default/package.json +8 -0
- package/plugin/schemaReporting/package.json +8 -0
- package/plugin/subscriptionCallback/package.json +8 -0
- package/plugin/usageReporting/package.json +8 -0
- package/src/ApolloServer.ts +1456 -0
- package/src/cachePolicy.ts +33 -0
- package/src/determineApolloConfig.ts +95 -0
- package/src/errorNormalize.ts +114 -0
- package/src/errors/index.ts +33 -0
- package/src/externalTypes/constructor.ts +174 -0
- package/src/externalTypes/context.ts +18 -0
- package/src/externalTypes/graphql.ts +81 -0
- package/src/externalTypes/http.ts +44 -0
- package/src/externalTypes/incrementalDeliveryPolyfillAlpha2.ts +63 -0
- package/src/externalTypes/incrementalDeliveryPolyfillAlpha9.ts +82 -0
- package/src/externalTypes/index.ts +73 -0
- package/src/externalTypes/plugins.ts +222 -0
- package/src/externalTypes/requestPipeline.ts +123 -0
- package/src/generated/packageVersion.ts +1 -0
- package/src/httpBatching.ts +105 -0
- package/src/incrementalDeliveryPolyfill.ts +253 -0
- package/src/index.ts +4 -0
- package/src/internalErrorClasses.ts +123 -0
- package/src/internalPlugin.ts +42 -0
- package/src/plugin/cacheControl/index.ts +453 -0
- package/src/plugin/disableSuggestions/index.ts +23 -0
- package/src/plugin/disabled/index.ts +41 -0
- package/src/plugin/drainHttpServer/index.ts +42 -0
- package/src/plugin/drainHttpServer/stoppable.ts +109 -0
- package/src/plugin/inlineTrace/index.ts +156 -0
- package/src/plugin/landingPage/default/getEmbeddedHTML.ts +204 -0
- package/src/plugin/landingPage/default/index.ts +219 -0
- package/src/plugin/landingPage/default/types.ts +198 -0
- package/src/plugin/schemaIsSubgraph.ts +41 -0
- package/src/plugin/schemaReporting/generated/operations.d.ts +18359 -0
- package/src/plugin/schemaReporting/index.ts +198 -0
- package/src/plugin/schemaReporting/schemaReporter.ts +207 -0
- package/src/plugin/subscriptionCallback/index.ts +724 -0
- package/src/plugin/traceTreeBuilder.ts +356 -0
- package/src/plugin/usageReporting/defaultSendOperationsAsTrace.ts +74 -0
- package/src/plugin/usageReporting/durationHistogram.ts +87 -0
- package/src/plugin/usageReporting/index.ts +9 -0
- package/src/plugin/usageReporting/iterateOverTrace.ts +140 -0
- package/src/plugin/usageReporting/operationDerivedDataCache.ts +61 -0
- package/src/plugin/usageReporting/options.ts +414 -0
- package/src/plugin/usageReporting/plugin.ts +871 -0
- package/src/plugin/usageReporting/stats.ts +492 -0
- package/src/plugin/usageReporting/traceDetails.ts +96 -0
- package/src/preventCsrf.ts +99 -0
- package/src/requestPipeline.ts +821 -0
- package/src/runHttpQuery.ts +408 -0
- package/src/standalone/index.ts +155 -0
- package/src/utils/HeaderMap.ts +22 -0
- package/src/utils/UnreachableCaseError.ts +10 -0
- package/src/utils/computeCoreSchemaHash.ts +9 -0
- package/src/utils/invokeHooks.ts +53 -0
- package/src/utils/isDefined.ts +3 -0
- package/src/utils/makeGatewayGraphQLRequestContext.ts +197 -0
- package/src/utils/resolvable.ts +30 -0
- package/src/utils/schemaInstrumentation.ts +132 -0
- package/src/utils/schemaManager.ts +212 -0
- package/src/utils/urlForHttpServer.ts +21 -0
- package/src/validationRules/NoIntrospection.ts +27 -0
- package/src/validationRules/RecursiveSelectionsLimit.ts +198 -0
- package/src/validationRules/index.ts +5 -0
- package/standalone/package.json +8 -0
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
import { type FetcherResponse, type Fetcher } from '@apollo/utils.fetcher';
|
|
2
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
3
|
+
import retry from 'async-retry';
|
|
4
|
+
import { subscribe, type ExecutionResult, type GraphQLError } from 'graphql';
|
|
5
|
+
import { setImmediate } from 'node:timers/promises';
|
|
6
|
+
import { ensureError, ensureGraphQLError } from '../../errorNormalize.js';
|
|
7
|
+
import type { ApolloServerPlugin } from '../../externalTypes/index.js';
|
|
8
|
+
import { HeaderMap } from '../../utils/HeaderMap.js';
|
|
9
|
+
|
|
10
|
+
export interface ApolloServerPluginSubscriptionCallbackOptions {
|
|
11
|
+
maxConsecutiveHeartbeatFailures?: number;
|
|
12
|
+
logger?: Logger;
|
|
13
|
+
retry?: retry.Options;
|
|
14
|
+
/**
|
|
15
|
+
* Specifies which Fetch API implementation to use for the callback URL.
|
|
16
|
+
*/
|
|
17
|
+
fetcher?: Fetcher;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ApolloServerPluginSubscriptionCallback(
|
|
21
|
+
options: ApolloServerPluginSubscriptionCallbackOptions = Object.create(null),
|
|
22
|
+
): ApolloServerPlugin {
|
|
23
|
+
const subscriptionManager = new SubscriptionManager(options);
|
|
24
|
+
const logger = options.logger
|
|
25
|
+
? prefixedLogger(options.logger, 'SubscriptionCallback')
|
|
26
|
+
: undefined;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
async requestDidStart({ request }) {
|
|
30
|
+
const subscriptionExtension = request?.extensions?.subscription;
|
|
31
|
+
// If it's not a callback subscription, ignore the request.
|
|
32
|
+
if (!subscriptionExtension) return;
|
|
33
|
+
let {
|
|
34
|
+
callbackUrl,
|
|
35
|
+
subscriptionId: id,
|
|
36
|
+
verifier,
|
|
37
|
+
heartbeatIntervalMs,
|
|
38
|
+
} = subscriptionExtension;
|
|
39
|
+
// The GA version of callback protocol use camelCase, this is to keep backward compatibility
|
|
40
|
+
callbackUrl = callbackUrl || subscriptionExtension.callback_url;
|
|
41
|
+
id = id || subscriptionExtension.subscription_id;
|
|
42
|
+
heartbeatIntervalMs =
|
|
43
|
+
heartbeatIntervalMs ??
|
|
44
|
+
subscriptionExtension.heartbeat_interval_ms ??
|
|
45
|
+
5000;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
// Implementing `responseForOperation` is the only hook that allows us
|
|
49
|
+
// to bypass normal execution by returning our own response. We don't
|
|
50
|
+
// want Apollo Server to actually handle this subscription request, we
|
|
51
|
+
// want to handle everything ourselves. The actual subscription handling
|
|
52
|
+
// will be done in `willSendResponse`.
|
|
53
|
+
async responseForOperation() {
|
|
54
|
+
logger?.debug('Received new subscription request', id);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
http: {
|
|
58
|
+
status: 200,
|
|
59
|
+
headers: new HeaderMap([['content-type', 'application/json']]),
|
|
60
|
+
},
|
|
61
|
+
body: {
|
|
62
|
+
kind: 'single',
|
|
63
|
+
singleResult: {
|
|
64
|
+
data: null,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
// The majority of the subscription work is implemented in this hook.
|
|
70
|
+
// This can _almost_ all be implemented in `responseForOperation`,
|
|
71
|
+
// however in the case of GraphQL validation errors,
|
|
72
|
+
// `responseForOperation` won't actually be called, but
|
|
73
|
+
// `willSendResponse` will.
|
|
74
|
+
async willSendResponse({
|
|
75
|
+
request,
|
|
76
|
+
schema,
|
|
77
|
+
document,
|
|
78
|
+
contextValue,
|
|
79
|
+
operationName,
|
|
80
|
+
response,
|
|
81
|
+
}) {
|
|
82
|
+
try {
|
|
83
|
+
// Before responding to the original request, we need to complete a
|
|
84
|
+
// roundtrip `check` request to the router, so we `await` this
|
|
85
|
+
// request.
|
|
86
|
+
await subscriptionManager.checkRequest({
|
|
87
|
+
callbackUrl,
|
|
88
|
+
id,
|
|
89
|
+
verifier,
|
|
90
|
+
});
|
|
91
|
+
} catch (e) {
|
|
92
|
+
const graphqlError = ensureGraphQLError(e);
|
|
93
|
+
logger?.error(
|
|
94
|
+
`\`check\` request failed: ${graphqlError.message}`,
|
|
95
|
+
id,
|
|
96
|
+
);
|
|
97
|
+
// In the event of a check failure, we respond to the original
|
|
98
|
+
// request with a >=400 status code.
|
|
99
|
+
if (response.body.kind === 'single') {
|
|
100
|
+
response.body.singleResult.errors = [graphqlError];
|
|
101
|
+
response.http.status = 500;
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// We're about to `await` the subscription, which could have some
|
|
107
|
+
// nontrivial asynchronous work to do before returning the generator.
|
|
108
|
+
// We set up the heartbeat first so the router knows we're alive
|
|
109
|
+
// during that wait period.
|
|
110
|
+
subscriptionManager.initHeartbeat({
|
|
111
|
+
callbackUrl,
|
|
112
|
+
id,
|
|
113
|
+
verifier,
|
|
114
|
+
heartbeatIntervalMs,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// The `check` request was successful, so we can initialize the actual
|
|
118
|
+
// `graphql-js` subscription. We don't expect `subscribe` to throw,
|
|
119
|
+
// but rather return an object with `errors` on it (if there are any).
|
|
120
|
+
logger?.debug(`Starting graphql-js subscription`, id);
|
|
121
|
+
let subscription: Awaited<ReturnType<typeof subscribe>>;
|
|
122
|
+
try {
|
|
123
|
+
subscription = await subscribe({
|
|
124
|
+
schema,
|
|
125
|
+
document: document!,
|
|
126
|
+
variableValues: request.variables,
|
|
127
|
+
contextValue: contextValue,
|
|
128
|
+
operationName: operationName,
|
|
129
|
+
});
|
|
130
|
+
} catch (e) {
|
|
131
|
+
// While we don't expect this scenario, we should still handle it
|
|
132
|
+
// gracefully (in the same way that we do below, when the
|
|
133
|
+
// subscription object has `errors` on it).
|
|
134
|
+
const graphqlError = ensureGraphQLError(e);
|
|
135
|
+
logger?.error(
|
|
136
|
+
`Programming error: graphql-js subscribe() threw unexpectedly! Please report this bug to Apollo. The error was: ${e}`,
|
|
137
|
+
id,
|
|
138
|
+
);
|
|
139
|
+
subscriptionManager.completeRequest({
|
|
140
|
+
errors: [graphqlError],
|
|
141
|
+
callbackUrl,
|
|
142
|
+
id,
|
|
143
|
+
verifier,
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// In the case of errors, send a `complete` request to the router with
|
|
149
|
+
// the errors.
|
|
150
|
+
if ('errors' in subscription) {
|
|
151
|
+
logger?.error(
|
|
152
|
+
`graphql-js subscription unsuccessful: [\n\t${subscription.errors
|
|
153
|
+
?.map((e) => e.message)
|
|
154
|
+
.join(',\n\t')}\n]`,
|
|
155
|
+
id,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
subscriptionManager.completeRequest({
|
|
160
|
+
errors: subscription.errors,
|
|
161
|
+
callbackUrl,
|
|
162
|
+
id,
|
|
163
|
+
verifier,
|
|
164
|
+
});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
// TODO: not sure how to best handle a failed "completion with
|
|
167
|
+
// errors" request outside of retrying.
|
|
168
|
+
logger?.error(`\`complete\` request failed: ${e}`, id);
|
|
169
|
+
}
|
|
170
|
+
} else if (isAsyncIterable(subscription)) {
|
|
171
|
+
// We have a real subscription - now we can consume the
|
|
172
|
+
// AsyncIterable on the `subscription` object.
|
|
173
|
+
logger?.debug('graphql-js subscription successful', id);
|
|
174
|
+
|
|
175
|
+
subscriptionManager.startConsumingSubscription({
|
|
176
|
+
subscription,
|
|
177
|
+
callbackUrl,
|
|
178
|
+
id,
|
|
179
|
+
verifier,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
logger?.debug(`Responding to original subscription request`, id);
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
async serverWillStart() {
|
|
188
|
+
return {
|
|
189
|
+
async drainServer() {
|
|
190
|
+
logger?.debug(
|
|
191
|
+
'Server is shutting down. Cleaning up outstanding subscriptions and heartbeat intervals',
|
|
192
|
+
);
|
|
193
|
+
await subscriptionManager.cleanup();
|
|
194
|
+
// This setImmediate makes the precise timing of the log line below
|
|
195
|
+
// consistent between when we run our test suite with GraphQL.js v16
|
|
196
|
+
// and v17.0.0-alpha.9.
|
|
197
|
+
await setImmediate();
|
|
198
|
+
logger?.debug(
|
|
199
|
+
'Successfully cleaned up outstanding subscriptions and heartbeat intervals.',
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function isAsyncIterable<T>(value: any): value is AsyncIterable<T> {
|
|
208
|
+
return value && typeof value[Symbol.asyncIterator] === 'function';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface SubscriptionObject {
|
|
212
|
+
cancelled: boolean;
|
|
213
|
+
asyncIter: AsyncGenerator<ExecutionResult, void, void>;
|
|
214
|
+
startConsumingSubscription: () => Promise<void>;
|
|
215
|
+
completeSubscription: () => Promise<void>;
|
|
216
|
+
}
|
|
217
|
+
// This class manages the state of subscriptions, heartbeat intervals, and
|
|
218
|
+
// router requests. It keeps track of in flight requests so we can await them
|
|
219
|
+
// during server cleanup.
|
|
220
|
+
class SubscriptionManager {
|
|
221
|
+
private maxConsecutiveHeartbeatFailures: number;
|
|
222
|
+
private logger?: ReturnType<typeof prefixedLogger>;
|
|
223
|
+
private retryConfig?: retry.Options;
|
|
224
|
+
private requestsInFlight: Set<Promise<any>> = new Set();
|
|
225
|
+
// A map of information about subscription for a given callback url including the subscription id.
|
|
226
|
+
private subscriptionInfoByCallbackUrl: Map<
|
|
227
|
+
string,
|
|
228
|
+
{
|
|
229
|
+
heartbeat?: {
|
|
230
|
+
id: string;
|
|
231
|
+
verifier: string;
|
|
232
|
+
interval: NodeJS.Timeout;
|
|
233
|
+
queue: Promise<void>[];
|
|
234
|
+
};
|
|
235
|
+
subscription?: SubscriptionObject;
|
|
236
|
+
}
|
|
237
|
+
> = new Map();
|
|
238
|
+
private fetcher: Fetcher;
|
|
239
|
+
|
|
240
|
+
constructor(options: ApolloServerPluginSubscriptionCallbackOptions) {
|
|
241
|
+
this.maxConsecutiveHeartbeatFailures =
|
|
242
|
+
options.maxConsecutiveHeartbeatFailures ?? 5;
|
|
243
|
+
this.retryConfig = {
|
|
244
|
+
retries: 5,
|
|
245
|
+
minTimeout: 100,
|
|
246
|
+
maxTimeout: 1000,
|
|
247
|
+
...options.retry,
|
|
248
|
+
};
|
|
249
|
+
this.logger = options.logger
|
|
250
|
+
? prefixedLogger(options.logger, 'SubscriptionManager')
|
|
251
|
+
: undefined;
|
|
252
|
+
this.fetcher = options.fetcher ?? fetch;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async retryFetch({
|
|
256
|
+
url,
|
|
257
|
+
action,
|
|
258
|
+
id,
|
|
259
|
+
verifier,
|
|
260
|
+
payload,
|
|
261
|
+
errors,
|
|
262
|
+
headers,
|
|
263
|
+
}: {
|
|
264
|
+
url: string;
|
|
265
|
+
action: 'check' | 'next' | 'complete';
|
|
266
|
+
id: string;
|
|
267
|
+
verifier: string;
|
|
268
|
+
payload?: ExecutionResult;
|
|
269
|
+
errors?: readonly GraphQLError[];
|
|
270
|
+
headers?: Record<string, string>;
|
|
271
|
+
}) {
|
|
272
|
+
let response: Promise<FetcherResponse> | undefined;
|
|
273
|
+
try {
|
|
274
|
+
const maybeWithErrors = errors?.length ? ` with errors` : '';
|
|
275
|
+
this.logger?.debug(
|
|
276
|
+
`Sending \`${action}\` request to router` + maybeWithErrors,
|
|
277
|
+
id,
|
|
278
|
+
);
|
|
279
|
+
return retry<FetcherResponse, Error>(
|
|
280
|
+
async (bail) => {
|
|
281
|
+
response = this.fetcher(url, {
|
|
282
|
+
method: 'POST',
|
|
283
|
+
headers: {
|
|
284
|
+
'content-type': 'application/json',
|
|
285
|
+
...headers,
|
|
286
|
+
},
|
|
287
|
+
body: JSON.stringify({
|
|
288
|
+
kind: 'subscription',
|
|
289
|
+
action,
|
|
290
|
+
id,
|
|
291
|
+
verifier,
|
|
292
|
+
...(payload && { payload }),
|
|
293
|
+
...(errors?.length && { errors }),
|
|
294
|
+
}),
|
|
295
|
+
});
|
|
296
|
+
this.requestsInFlight.add(response);
|
|
297
|
+
const result = await response;
|
|
298
|
+
|
|
299
|
+
if (!result.ok) {
|
|
300
|
+
if (result.status >= 500) {
|
|
301
|
+
// Throwing here triggers a retry, which seems reasonable for 5xx
|
|
302
|
+
// (i.e. an internal server error).
|
|
303
|
+
throw new Error(
|
|
304
|
+
`\`${action}\` request failed with unexpected status code: ${result.status}`,
|
|
305
|
+
);
|
|
306
|
+
} else {
|
|
307
|
+
// For 4xx, we don't want to retry. These errors carry a semantic
|
|
308
|
+
// meaning (terminate), so we bail. This will reject the promise and
|
|
309
|
+
// should be handled by the caller. Specifically, 404 from the
|
|
310
|
+
// router means terminate, but the protocol says that in other error
|
|
311
|
+
// cases the subscription should be terminated due to an unexpected
|
|
312
|
+
// error.
|
|
313
|
+
if (result.status === 404) {
|
|
314
|
+
this.logger?.debug(
|
|
315
|
+
`\`${action}\` request received 404, terminating subscription`,
|
|
316
|
+
id,
|
|
317
|
+
);
|
|
318
|
+
} else {
|
|
319
|
+
const errMsg = `\`${action}\` request failed with unexpected status code: ${result.status}, terminating subscription`;
|
|
320
|
+
this.logger?.debug(errMsg, id);
|
|
321
|
+
bail(new Error(errMsg));
|
|
322
|
+
}
|
|
323
|
+
this.terminateSubscription(id, url);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
this.logger?.debug(`\`${action}\` request successful`, id);
|
|
328
|
+
return result;
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
...this.retryConfig,
|
|
332
|
+
onRetry: (e, attempt) => {
|
|
333
|
+
this.requestsInFlight.delete(response!);
|
|
334
|
+
this.logger?.warn(
|
|
335
|
+
`Retrying \`${action}\` request (attempt ${attempt}) due to error: ${e.message}`,
|
|
336
|
+
id,
|
|
337
|
+
);
|
|
338
|
+
this.retryConfig?.onRetry?.(e, attempt);
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
);
|
|
342
|
+
} finally {
|
|
343
|
+
this.requestsInFlight.delete(response!);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Implements sending the `check` request to the router. Fetch errors are
|
|
348
|
+
// thrown and expected to be handled by the caller.
|
|
349
|
+
async checkRequest({
|
|
350
|
+
callbackUrl,
|
|
351
|
+
id,
|
|
352
|
+
verifier,
|
|
353
|
+
}: {
|
|
354
|
+
callbackUrl: string;
|
|
355
|
+
id: string;
|
|
356
|
+
verifier: string;
|
|
357
|
+
}) {
|
|
358
|
+
return this.retryFetch({
|
|
359
|
+
url: callbackUrl,
|
|
360
|
+
action: 'check',
|
|
361
|
+
id,
|
|
362
|
+
verifier,
|
|
363
|
+
headers: { 'subscription-protocol': 'callback/1.0' },
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Kicks off an interval that sends `heartbeat` requests to the router. If an
|
|
368
|
+
// interval already exists for the callback url, we just add the new ID to its
|
|
369
|
+
// list of IDs that it's sending a heartbeat for. This allows us to send one
|
|
370
|
+
// batched heartbeat per interval per callback url.
|
|
371
|
+
initHeartbeat({
|
|
372
|
+
callbackUrl,
|
|
373
|
+
id,
|
|
374
|
+
verifier,
|
|
375
|
+
heartbeatIntervalMs,
|
|
376
|
+
}: {
|
|
377
|
+
callbackUrl: string;
|
|
378
|
+
id: string;
|
|
379
|
+
verifier: string;
|
|
380
|
+
heartbeatIntervalMs: number;
|
|
381
|
+
}) {
|
|
382
|
+
if (!this.subscriptionInfoByCallbackUrl.has(callbackUrl)) {
|
|
383
|
+
this.subscriptionInfoByCallbackUrl.set(callbackUrl, {});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (heartbeatIntervalMs === 0) {
|
|
387
|
+
// Heartbeat has been disabled on the router
|
|
388
|
+
this.logger?.debug(`Heartbeat disabled for ${callbackUrl}`, id);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Kickoff heartbeat interval since there isn't one already
|
|
393
|
+
this.logger?.debug(
|
|
394
|
+
`Starting new heartbeat interval for ${callbackUrl}`,
|
|
395
|
+
id,
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
let consecutiveHeartbeatFailureCount = 0;
|
|
399
|
+
const heartbeatInterval = setInterval(async () => {
|
|
400
|
+
let heartbeatRequest: Promise<FetcherResponse> | undefined;
|
|
401
|
+
|
|
402
|
+
// XXX since we're on an interval, it's possible a heartbeat goes out
|
|
403
|
+
// before the previous heartbeat has finished. It seems reasonable to
|
|
404
|
+
// queue them and await the previous heartbeat if there is one. It might
|
|
405
|
+
// also be reasonable to just bail / skip this heartbeat if there's
|
|
406
|
+
// already one in flight. I'm not sure which is better. This Promise and
|
|
407
|
+
// all of the queue stuff try to address this. Maybe this would be better
|
|
408
|
+
// off chaining timeouts instead of using an interval?
|
|
409
|
+
let resolveHeartbeatPromise: () => void;
|
|
410
|
+
const heartbeatPromise = new Promise<void>((r) => {
|
|
411
|
+
resolveHeartbeatPromise = r;
|
|
412
|
+
});
|
|
413
|
+
const existingSubscriptionInfo =
|
|
414
|
+
this.subscriptionInfoByCallbackUrl.get(callbackUrl);
|
|
415
|
+
|
|
416
|
+
if (!existingSubscriptionInfo?.heartbeat) {
|
|
417
|
+
// This is unexpected - if the interval is still running we should have
|
|
418
|
+
// an entry in the map for it. But if we do end up here, there's no
|
|
419
|
+
// reason to let the interval continue to run.
|
|
420
|
+
clearInterval(heartbeatInterval);
|
|
421
|
+
this.logger?.error(
|
|
422
|
+
`Programming error: Heartbeat interval unexpectedly missing for ${callbackUrl}. This is probably a bug in Apollo Server.`,
|
|
423
|
+
);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const existingHeartbeat = existingSubscriptionInfo.heartbeat;
|
|
427
|
+
const { queue } = existingHeartbeat;
|
|
428
|
+
queue.push(heartbeatPromise);
|
|
429
|
+
if (queue.length > 1) {
|
|
430
|
+
const requestBeforeMe = queue[existingHeartbeat?.queue.length - 2];
|
|
431
|
+
await requestBeforeMe;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Send the heartbeat request
|
|
435
|
+
try {
|
|
436
|
+
this.logger?.debug(
|
|
437
|
+
`Sending \`check\` request to ${callbackUrl} for ID: ${id}`,
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
heartbeatRequest = this.fetcher(callbackUrl, {
|
|
441
|
+
method: 'POST',
|
|
442
|
+
body: JSON.stringify({
|
|
443
|
+
kind: 'subscription',
|
|
444
|
+
action: 'check',
|
|
445
|
+
id,
|
|
446
|
+
verifier,
|
|
447
|
+
}),
|
|
448
|
+
headers: {
|
|
449
|
+
'content-type': 'application/json',
|
|
450
|
+
'subscription-protocol': 'callback/1.0',
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
this.requestsInFlight.add(heartbeatRequest);
|
|
454
|
+
|
|
455
|
+
// heartbeat response might be a 4xx, in which case we'd need to
|
|
456
|
+
// terminate the subscription, so we need to await it
|
|
457
|
+
const result = await heartbeatRequest;
|
|
458
|
+
|
|
459
|
+
this.logger?.debug(`Heartbeat received response for ID: ${id}`);
|
|
460
|
+
if (result.ok) {
|
|
461
|
+
this.logger?.debug(`Heartbeat request successful, ID: ${id}`);
|
|
462
|
+
} else if (result.status === 400) {
|
|
463
|
+
this.logger?.debug(`Heartbeat request received invalid ID: ${id}`);
|
|
464
|
+
|
|
465
|
+
this.terminateSubscription(id, callbackUrl);
|
|
466
|
+
} else if (result.status === 404) {
|
|
467
|
+
// the id we sent is invalid
|
|
468
|
+
this.logger?.debug(`Heartbeat request received invalid ID: ${id}`);
|
|
469
|
+
// This will also handle cleaning up the heartbeat interval
|
|
470
|
+
this.terminateSubscription(id, callbackUrl);
|
|
471
|
+
} else {
|
|
472
|
+
// We'll catch this below and log it with the expectation that we'll
|
|
473
|
+
// retry this request some number of times before giving up
|
|
474
|
+
throw new Error(`Unexpected status code: ${result.status}`);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// If we make it here, there wasn't some transient error with the
|
|
478
|
+
// request and it had an expected status code (2xx, 400, 404).
|
|
479
|
+
consecutiveHeartbeatFailureCount = 0;
|
|
480
|
+
} catch (e) {
|
|
481
|
+
const err = ensureError(e);
|
|
482
|
+
// The heartbeat request failed.
|
|
483
|
+
this.logger?.error(
|
|
484
|
+
`Heartbeat request failed (${++consecutiveHeartbeatFailureCount} consecutive): ${
|
|
485
|
+
err.message
|
|
486
|
+
}`,
|
|
487
|
+
existingHeartbeat.id,
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
if (
|
|
491
|
+
consecutiveHeartbeatFailureCount >=
|
|
492
|
+
this.maxConsecutiveHeartbeatFailures
|
|
493
|
+
) {
|
|
494
|
+
this.logger?.error(
|
|
495
|
+
`Heartbeat request failed ${consecutiveHeartbeatFailureCount} times, terminating subscriptions and heartbeat interval: ${err.message}`,
|
|
496
|
+
existingHeartbeat.id,
|
|
497
|
+
);
|
|
498
|
+
// If we've failed 5 times in a row, we should terminate all
|
|
499
|
+
// subscriptions for this callback url. This will also handle
|
|
500
|
+
// cleaning up the heartbeat interval.
|
|
501
|
+
this.terminateSubscription(id, callbackUrl);
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
} finally {
|
|
505
|
+
if (heartbeatRequest) {
|
|
506
|
+
this.requestsInFlight.delete(heartbeatRequest);
|
|
507
|
+
}
|
|
508
|
+
// remove itself from the queue and resolve the promise
|
|
509
|
+
existingHeartbeat?.queue.shift();
|
|
510
|
+
resolveHeartbeatPromise!();
|
|
511
|
+
}
|
|
512
|
+
}, heartbeatIntervalMs);
|
|
513
|
+
|
|
514
|
+
// Add the heartbeat interval to the map of intervals
|
|
515
|
+
const subscriptionInfo =
|
|
516
|
+
this.subscriptionInfoByCallbackUrl.get(callbackUrl)!;
|
|
517
|
+
subscriptionInfo.heartbeat = {
|
|
518
|
+
interval: heartbeatInterval,
|
|
519
|
+
id,
|
|
520
|
+
verifier,
|
|
521
|
+
queue: [],
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Cancels and cleans up the subscriptions for given IDs and callback url. If
|
|
526
|
+
// there are no active subscriptions after this, we also clean up the
|
|
527
|
+
// heartbeat interval. This does not handle sending the `complete` request to
|
|
528
|
+
// the router.
|
|
529
|
+
private terminateSubscription(id: string, callbackUrl: string) {
|
|
530
|
+
this.logger?.debug(`Terminating subscriptions for ID: ${id}`);
|
|
531
|
+
const subscriptionInfo =
|
|
532
|
+
this.subscriptionInfoByCallbackUrl.get(callbackUrl);
|
|
533
|
+
if (!subscriptionInfo) {
|
|
534
|
+
this.logger?.error(
|
|
535
|
+
`No subscriptions found for ${callbackUrl}, skipping termination`,
|
|
536
|
+
);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const { subscription, heartbeat } = subscriptionInfo;
|
|
540
|
+
if (subscription) {
|
|
541
|
+
subscription.cancelled = true;
|
|
542
|
+
subscription.asyncIter?.return();
|
|
543
|
+
}
|
|
544
|
+
// cleanup heartbeat for subscription
|
|
545
|
+
if (heartbeat) {
|
|
546
|
+
this.logger?.debug(`Terminating heartbeat interval for ${callbackUrl}`);
|
|
547
|
+
clearInterval(heartbeat.interval);
|
|
548
|
+
}
|
|
549
|
+
this.subscriptionInfoByCallbackUrl.delete(callbackUrl);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Consumes the AsyncIterable returned by `graphql-js`'s `subscribe` function.
|
|
553
|
+
// This handles sending the `next` requests to the router as well as the
|
|
554
|
+
// `complete` request when the subscription is finished.
|
|
555
|
+
startConsumingSubscription({
|
|
556
|
+
subscription,
|
|
557
|
+
callbackUrl,
|
|
558
|
+
id,
|
|
559
|
+
verifier,
|
|
560
|
+
}: {
|
|
561
|
+
subscription: AsyncGenerator<ExecutionResult, void, void>;
|
|
562
|
+
callbackUrl: string;
|
|
563
|
+
id: string;
|
|
564
|
+
verifier: string;
|
|
565
|
+
}) {
|
|
566
|
+
// For each subscription we need to manage a bit of state. We need to be
|
|
567
|
+
// able to cancel the subscription externally. Setting `cancelled` to true
|
|
568
|
+
// allows us to break out of the `for await` and ignore future payloads.
|
|
569
|
+
const self = this;
|
|
570
|
+
const subscriptionObject = {
|
|
571
|
+
asyncIter: subscription,
|
|
572
|
+
cancelled: false,
|
|
573
|
+
async startConsumingSubscription() {
|
|
574
|
+
self.logger?.debug(`Listening to graphql-js subscription`, id);
|
|
575
|
+
try {
|
|
576
|
+
for await (const payload of subscription) {
|
|
577
|
+
if (this.cancelled) {
|
|
578
|
+
self.logger?.debug(
|
|
579
|
+
`Subscription already cancelled, ignoring current and future payloads`,
|
|
580
|
+
id,
|
|
581
|
+
);
|
|
582
|
+
// It's already been cancelled - something else has already handled
|
|
583
|
+
// sending the `complete` request so we don't want to `break` here
|
|
584
|
+
// and send it again after the loop.
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
try {
|
|
589
|
+
await self.retryFetch({
|
|
590
|
+
url: callbackUrl,
|
|
591
|
+
action: 'next',
|
|
592
|
+
id,
|
|
593
|
+
verifier,
|
|
594
|
+
payload,
|
|
595
|
+
});
|
|
596
|
+
} catch (e) {
|
|
597
|
+
const originalError = ensureError(e);
|
|
598
|
+
self.logger?.error(
|
|
599
|
+
`\`next\` request failed, terminating subscription: ${originalError.message}`,
|
|
600
|
+
id,
|
|
601
|
+
);
|
|
602
|
+
self.terminateSubscription(id, callbackUrl);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// The subscription ended without errors, send the `complete` request to
|
|
606
|
+
// the router
|
|
607
|
+
self.logger?.debug(`Subscription completed without errors`, id);
|
|
608
|
+
await this.completeSubscription();
|
|
609
|
+
} catch (e) {
|
|
610
|
+
const error = ensureGraphQLError(e);
|
|
611
|
+
self.logger?.error(
|
|
612
|
+
`Generator threw an error, terminating subscription: ${error.message}`,
|
|
613
|
+
id,
|
|
614
|
+
);
|
|
615
|
+
this.completeSubscription([error]);
|
|
616
|
+
}
|
|
617
|
+
},
|
|
618
|
+
async completeSubscription(errors?: readonly GraphQLError[]) {
|
|
619
|
+
if (this.cancelled) return;
|
|
620
|
+
this.cancelled = true;
|
|
621
|
+
|
|
622
|
+
try {
|
|
623
|
+
await self.completeRequest({
|
|
624
|
+
callbackUrl,
|
|
625
|
+
id,
|
|
626
|
+
verifier,
|
|
627
|
+
...(errors && { errors }),
|
|
628
|
+
});
|
|
629
|
+
} catch (e) {
|
|
630
|
+
const error = ensureError(e);
|
|
631
|
+
// This is just the `complete` request. If we fail to get this message
|
|
632
|
+
// to the router, it should just invalidate the subscription after the
|
|
633
|
+
// next heartbeat fails.
|
|
634
|
+
self.logger?.error(
|
|
635
|
+
`\`complete\` request failed: ${error.message}`,
|
|
636
|
+
id,
|
|
637
|
+
);
|
|
638
|
+
} finally {
|
|
639
|
+
self.terminateSubscription(id, callbackUrl);
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
subscriptionObject.startConsumingSubscription();
|
|
645
|
+
const subscriptionInfo =
|
|
646
|
+
this.subscriptionInfoByCallbackUrl.get(callbackUrl);
|
|
647
|
+
if (!subscriptionInfo) {
|
|
648
|
+
this.logger?.error(
|
|
649
|
+
`No existing heartbeat found for ${callbackUrl}, skipping subscription`,
|
|
650
|
+
);
|
|
651
|
+
} else {
|
|
652
|
+
subscriptionInfo.subscription = subscriptionObject;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Sends the `complete` request to the router.
|
|
657
|
+
async completeRequest({
|
|
658
|
+
errors,
|
|
659
|
+
callbackUrl,
|
|
660
|
+
id,
|
|
661
|
+
verifier,
|
|
662
|
+
}: {
|
|
663
|
+
errors?: readonly GraphQLError[];
|
|
664
|
+
callbackUrl: string;
|
|
665
|
+
id: string;
|
|
666
|
+
verifier: string;
|
|
667
|
+
}) {
|
|
668
|
+
return this.retryFetch({
|
|
669
|
+
url: callbackUrl,
|
|
670
|
+
action: 'complete',
|
|
671
|
+
id,
|
|
672
|
+
verifier,
|
|
673
|
+
errors,
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
collectAllSubscriptions() {
|
|
678
|
+
return Array.from(this.subscriptionInfoByCallbackUrl.values()).reduce(
|
|
679
|
+
(subscriptions, { subscription }) => {
|
|
680
|
+
if (subscription) {
|
|
681
|
+
subscriptions.push(subscription);
|
|
682
|
+
}
|
|
683
|
+
return subscriptions;
|
|
684
|
+
},
|
|
685
|
+
[] as SubscriptionObject[],
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
async cleanup() {
|
|
690
|
+
// Wait for our inflight heartbeats to finish - they might handle cancelling
|
|
691
|
+
// some subscriptions
|
|
692
|
+
await Promise.allSettled(
|
|
693
|
+
Array.from(this.subscriptionInfoByCallbackUrl.values()).map(
|
|
694
|
+
async ({ heartbeat }) => {
|
|
695
|
+
clearInterval(heartbeat?.interval);
|
|
696
|
+
await heartbeat?.queue[heartbeat.queue.length - 1];
|
|
697
|
+
},
|
|
698
|
+
),
|
|
699
|
+
);
|
|
700
|
+
// Cancel / complete any still-active subscriptions
|
|
701
|
+
await Promise.allSettled(
|
|
702
|
+
this.collectAllSubscriptions()
|
|
703
|
+
.filter((s) => !s.cancelled)
|
|
704
|
+
.map((s) => s.completeSubscription()),
|
|
705
|
+
);
|
|
706
|
+
// Wait for any remaining requests to finish
|
|
707
|
+
await Promise.allSettled(this.requestsInFlight.values());
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Simple prefixing logger to curry class name and request IDs into log messages
|
|
712
|
+
function prefixedLogger(logger: Logger, prefix: string) {
|
|
713
|
+
function log(level: keyof Logger) {
|
|
714
|
+
return function (message: string, id?: string) {
|
|
715
|
+
logger[level](`${prefix}${id ? `[${id}]` : ''}: ${message}`);
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
debug: log('debug'),
|
|
720
|
+
error: log('error'),
|
|
721
|
+
info: log('info'),
|
|
722
|
+
warn: log('warn'),
|
|
723
|
+
};
|
|
724
|
+
}
|