@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,871 @@
|
|
|
1
|
+
import { Report, ReportHeader, Trace } from '@apollo/usage-reporting-protobuf';
|
|
2
|
+
import type { Fetcher, FetcherResponse } from '@apollo/utils.fetcher';
|
|
3
|
+
import {
|
|
4
|
+
usageReportingSignature,
|
|
5
|
+
calculateReferencedFieldsByType,
|
|
6
|
+
type ReferencedFieldsByType,
|
|
7
|
+
} from '@apollo/utils.usagereporting';
|
|
8
|
+
import retry from 'async-retry';
|
|
9
|
+
import { type GraphQLSchema, printSchema } from 'graphql';
|
|
10
|
+
import { type LRUCache } from 'lru-cache';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import { gzip } from 'zlib';
|
|
13
|
+
import type {
|
|
14
|
+
ApolloServerPlugin,
|
|
15
|
+
BaseContext,
|
|
16
|
+
GraphQLRequestContext,
|
|
17
|
+
GraphQLRequestContextDidResolveOperation,
|
|
18
|
+
GraphQLRequestContextWillSendResponse,
|
|
19
|
+
GraphQLRequestListener,
|
|
20
|
+
GraphQLServerListener,
|
|
21
|
+
} from '../../externalTypes/index.js';
|
|
22
|
+
import { internalPlugin } from '../../internalPlugin.js';
|
|
23
|
+
import { dateToProtoTimestamp, TraceTreeBuilder } from '../traceTreeBuilder.js';
|
|
24
|
+
import { defaultSendOperationsAsTrace } from './defaultSendOperationsAsTrace.js';
|
|
25
|
+
import {
|
|
26
|
+
createOperationDerivedDataCache,
|
|
27
|
+
type OperationDerivedData,
|
|
28
|
+
operationDerivedDataCacheKey,
|
|
29
|
+
} from './operationDerivedDataCache.js';
|
|
30
|
+
import type {
|
|
31
|
+
ApolloServerPluginUsageReportingOptions,
|
|
32
|
+
SendValuesBaseOptions,
|
|
33
|
+
} from './options.js';
|
|
34
|
+
import { OurReport } from './stats.js';
|
|
35
|
+
import { makeTraceDetails } from './traceDetails.js';
|
|
36
|
+
import { packageVersion } from '../../generated/packageVersion.js';
|
|
37
|
+
import { computeCoreSchemaHash } from '../../utils/computeCoreSchemaHash.js';
|
|
38
|
+
import type { HeaderMap } from '../../utils/HeaderMap.js';
|
|
39
|
+
import { schemaIsSubgraph } from '../schemaIsSubgraph.js';
|
|
40
|
+
|
|
41
|
+
const reportHeaderDefaults = {
|
|
42
|
+
hostname: os.hostname(),
|
|
43
|
+
agentVersion: `@apollo/server@${packageVersion}`,
|
|
44
|
+
runtimeVersion: `node ${process.version}`,
|
|
45
|
+
// XXX not actually uname, but what node has easily.
|
|
46
|
+
uname: `${os.platform()}, ${os.type()}, ${os.release()}, ${os.arch()})`,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
|
|
50
|
+
options: ApolloServerPluginUsageReportingOptions<TContext> = Object.create(
|
|
51
|
+
null,
|
|
52
|
+
),
|
|
53
|
+
): ApolloServerPlugin<TContext> {
|
|
54
|
+
const fieldLevelInstrumentationOption = options.fieldLevelInstrumentation;
|
|
55
|
+
const fieldLevelInstrumentation =
|
|
56
|
+
typeof fieldLevelInstrumentationOption === 'number'
|
|
57
|
+
? async () =>
|
|
58
|
+
Math.random() < fieldLevelInstrumentationOption
|
|
59
|
+
? 1 / fieldLevelInstrumentationOption
|
|
60
|
+
: 0
|
|
61
|
+
: fieldLevelInstrumentationOption
|
|
62
|
+
? fieldLevelInstrumentationOption
|
|
63
|
+
: async () => true;
|
|
64
|
+
|
|
65
|
+
let requestDidStartHandler:
|
|
66
|
+
| ((
|
|
67
|
+
requestContext: GraphQLRequestContext<TContext>,
|
|
68
|
+
) => GraphQLRequestListener<TContext>)
|
|
69
|
+
| null = null;
|
|
70
|
+
return internalPlugin({
|
|
71
|
+
__internal_plugin_id__: 'UsageReporting',
|
|
72
|
+
__is_disabled_plugin__: false,
|
|
73
|
+
|
|
74
|
+
// We want to be able to access locals from `serverWillStart` in our `requestDidStart`, thus
|
|
75
|
+
// this little hack. (Perhaps we should also allow GraphQLServerListener to contain
|
|
76
|
+
// a requestDidStart?)
|
|
77
|
+
async requestDidStart(requestContext: GraphQLRequestContext<TContext>) {
|
|
78
|
+
if (requestDidStartHandler) {
|
|
79
|
+
return requestDidStartHandler(requestContext);
|
|
80
|
+
}
|
|
81
|
+
// This happens if usage reporting is disabled (eg because this is a
|
|
82
|
+
// subgraph).
|
|
83
|
+
return {};
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
async serverWillStart({
|
|
87
|
+
logger: serverLogger,
|
|
88
|
+
apollo,
|
|
89
|
+
startedInBackground,
|
|
90
|
+
schema,
|
|
91
|
+
}): Promise<GraphQLServerListener> {
|
|
92
|
+
// Use the plugin-specific logger if one is provided; otherwise the general server one.
|
|
93
|
+
const logger = options.logger ?? serverLogger;
|
|
94
|
+
const { key, graphRef } = apollo;
|
|
95
|
+
if (!(key && graphRef)) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"You've enabled usage reporting via ApolloServerPluginUsageReporting, " +
|
|
98
|
+
'but you also need to provide your Apollo API key and graph ref, via ' +
|
|
99
|
+
'the APOLLO_KEY/APOLLO_GRAPH_REF environment ' +
|
|
100
|
+
'variables or via `new ApolloServer({apollo: {key, graphRef})`.',
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (schemaIsSubgraph(schema)) {
|
|
105
|
+
if (options.__onlyIfSchemaIsNotSubgraph) {
|
|
106
|
+
logger.warn(
|
|
107
|
+
'You have specified an Apollo API key and graph ref but this server appears ' +
|
|
108
|
+
'to be a subgraph. Typically usage reports are sent to Apollo by your Router ' +
|
|
109
|
+
'or Gateway, not directly from your subgraph; usage reporting is disabled. To ' +
|
|
110
|
+
'enable usage reporting anyway, explicitly install `ApolloServerPluginUsageReporting`. ' +
|
|
111
|
+
'To disable this warning, install `ApolloServerPluginUsageReportingDisabled`.',
|
|
112
|
+
);
|
|
113
|
+
// This early return means we don't start background timers, don't
|
|
114
|
+
// register serverDidStart, don't assign requestDidStartHandler, etc.
|
|
115
|
+
return {};
|
|
116
|
+
} else {
|
|
117
|
+
// This is just a warning; usage reporting is still enabled. If it
|
|
118
|
+
// turns out there are lots of people who really need to have this odd
|
|
119
|
+
// setup and they don't like the warning, we can provide a new option
|
|
120
|
+
// to disable the warning (or they can filter in their `logger`).
|
|
121
|
+
logger.warn(
|
|
122
|
+
'You have installed `ApolloServerPluginUsageReporting` but this server appears to ' +
|
|
123
|
+
'be a subgraph. Typically usage reports are sent to Apollo by your Router ' +
|
|
124
|
+
'or Gateway, not directly from your subgraph. If this was unintentional, remove ' +
|
|
125
|
+
"`ApolloServerPluginUsageReporting` from your server's `plugins` array.",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
logger.info(
|
|
131
|
+
'Apollo usage reporting starting! See your graph at ' +
|
|
132
|
+
`https://studio.apollographql.com/graph/${encodeURI(graphRef)}/`,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// If sendReportsImmediately is not specified, we default to true if we're running
|
|
136
|
+
// with the ApolloServer designed for Lambda or similar. That's because these
|
|
137
|
+
// environments aren't designed around letting us run a background task to
|
|
138
|
+
// send reports later or hook into container destruction to flush buffered reports.
|
|
139
|
+
const sendReportsImmediately =
|
|
140
|
+
options.sendReportsImmediately ?? startedInBackground;
|
|
141
|
+
|
|
142
|
+
// Since calculating the signature and referenced fields for usage
|
|
143
|
+
// reporting is potentially an expensive operation, we'll cache the data
|
|
144
|
+
// we generate and re-use them for repeated operations for the same
|
|
145
|
+
// `queryHash`. However, because referenced fields depend on the current
|
|
146
|
+
// schema, we want to throw it out entirely any time the schema changes.
|
|
147
|
+
let operationDerivedDataCache: {
|
|
148
|
+
forSchema: GraphQLSchema;
|
|
149
|
+
cache: LRUCache<string, OperationDerivedData>;
|
|
150
|
+
} | null = null;
|
|
151
|
+
|
|
152
|
+
// This map maps from executable schema ID (schema hash, basically) to the
|
|
153
|
+
// report we'll send about it. That's because when we're using a gateway,
|
|
154
|
+
// the schema can change over time, but each report needs to be about a
|
|
155
|
+
// single schema. We avoid having this function be a memory leak by
|
|
156
|
+
// removing values from it when we're in the process of sending reports.
|
|
157
|
+
// That means we have to be very careful never to pull a Report out of it
|
|
158
|
+
// and hang on to it for a while before writing to it, because the report
|
|
159
|
+
// might have gotten sent and discarded in the meantime. So you should
|
|
160
|
+
// only access the values of this Map via
|
|
161
|
+
// getReportWhichMustBeUsedImmediately and getAndDeleteReport, and never
|
|
162
|
+
// hang on to the value returned by getReportWhichMustBeUsedImmediately.
|
|
163
|
+
const reportByExecutableSchemaId = new Map<string, OurReport>();
|
|
164
|
+
const getReportWhichMustBeUsedImmediately = (
|
|
165
|
+
executableSchemaId: string,
|
|
166
|
+
): OurReport => {
|
|
167
|
+
const existing = reportByExecutableSchemaId.get(executableSchemaId);
|
|
168
|
+
if (existing) {
|
|
169
|
+
return existing;
|
|
170
|
+
}
|
|
171
|
+
const report = new OurReport(
|
|
172
|
+
new ReportHeader({
|
|
173
|
+
...reportHeaderDefaults,
|
|
174
|
+
executableSchemaId,
|
|
175
|
+
graphRef,
|
|
176
|
+
}),
|
|
177
|
+
);
|
|
178
|
+
reportByExecutableSchemaId.set(executableSchemaId, report);
|
|
179
|
+
return report;
|
|
180
|
+
};
|
|
181
|
+
const getAndDeleteReport = (
|
|
182
|
+
executableSchemaId: string,
|
|
183
|
+
): OurReport | null => {
|
|
184
|
+
const report = reportByExecutableSchemaId.get(executableSchemaId);
|
|
185
|
+
if (report) {
|
|
186
|
+
reportByExecutableSchemaId.delete(executableSchemaId);
|
|
187
|
+
return report;
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const overriddenExecutableSchemaId = options.overrideReportedSchema
|
|
193
|
+
? computeCoreSchemaHash(options.overrideReportedSchema)
|
|
194
|
+
: undefined;
|
|
195
|
+
|
|
196
|
+
let lastSeenExecutableSchemaToId:
|
|
197
|
+
| {
|
|
198
|
+
executableSchema: GraphQLSchema;
|
|
199
|
+
executableSchemaId: string;
|
|
200
|
+
}
|
|
201
|
+
| undefined;
|
|
202
|
+
|
|
203
|
+
let reportTimer: NodeJS.Timeout | undefined;
|
|
204
|
+
if (!sendReportsImmediately) {
|
|
205
|
+
reportTimer = setInterval(
|
|
206
|
+
() => sendAllReportsAndReportErrors(),
|
|
207
|
+
options.reportIntervalMs || 10 * 1000,
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// We don't send traces if the user set `sendTraces: false`. We also may
|
|
212
|
+
// set this to false later if the usage-reporting ingress informs us that
|
|
213
|
+
// this graph does not support viewing traces.
|
|
214
|
+
let sendTraces = options.sendTraces ?? true;
|
|
215
|
+
const sendOperationAsTrace =
|
|
216
|
+
options.experimental_sendOperationAsTrace ??
|
|
217
|
+
defaultSendOperationsAsTrace();
|
|
218
|
+
|
|
219
|
+
let stopped = false;
|
|
220
|
+
|
|
221
|
+
function executableSchemaIdForSchema(schema: GraphQLSchema) {
|
|
222
|
+
if (lastSeenExecutableSchemaToId?.executableSchema === schema) {
|
|
223
|
+
return lastSeenExecutableSchemaToId.executableSchemaId;
|
|
224
|
+
}
|
|
225
|
+
const id = computeCoreSchemaHash(printSchema(schema));
|
|
226
|
+
|
|
227
|
+
// We override this variable every time we get a new schema so we cache
|
|
228
|
+
// the last seen value. It is a single-entry cache.
|
|
229
|
+
lastSeenExecutableSchemaToId = {
|
|
230
|
+
executableSchema: schema,
|
|
231
|
+
executableSchemaId: id,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
return id;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function sendAllReportsAndReportErrors(): Promise<void> {
|
|
238
|
+
await Promise.all(
|
|
239
|
+
[...reportByExecutableSchemaId.keys()].map((executableSchemaId) =>
|
|
240
|
+
sendReportAndReportErrors(executableSchemaId),
|
|
241
|
+
),
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function sendReportAndReportErrors(
|
|
246
|
+
executableSchemaId: string,
|
|
247
|
+
): Promise<void> {
|
|
248
|
+
return sendReport(executableSchemaId).catch((err) => {
|
|
249
|
+
// This catch block is primarily intended to catch network errors from
|
|
250
|
+
// the retried request itself, which include network errors and non-2xx
|
|
251
|
+
// HTTP errors.
|
|
252
|
+
if (options.reportErrorFunction) {
|
|
253
|
+
options.reportErrorFunction(err);
|
|
254
|
+
} else {
|
|
255
|
+
logger.error(err.message);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Needs to be an arrow function to be confident that key is defined.
|
|
261
|
+
const sendReport = async (executableSchemaId: string): Promise<void> => {
|
|
262
|
+
let report = getAndDeleteReport(executableSchemaId);
|
|
263
|
+
if (
|
|
264
|
+
!report ||
|
|
265
|
+
(Object.keys(report.tracesPerQuery).length === 0 &&
|
|
266
|
+
report.operationCount === 0)
|
|
267
|
+
) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Set the report's overall end time. This is the timestamp that will be
|
|
272
|
+
// associated with the summarized statistics.
|
|
273
|
+
report.endTime = dateToProtoTimestamp(new Date());
|
|
274
|
+
|
|
275
|
+
report.ensureCountsAreIntegers();
|
|
276
|
+
|
|
277
|
+
const protobufError = Report.verify(report);
|
|
278
|
+
if (protobufError) {
|
|
279
|
+
throw new Error(`Error verifying report: ${protobufError}`);
|
|
280
|
+
}
|
|
281
|
+
let message: Uint8Array | null = Report.encode(report).finish();
|
|
282
|
+
// Let the original protobuf object be garbage collected (helpful if the
|
|
283
|
+
// HTTP request hangs).
|
|
284
|
+
report = null;
|
|
285
|
+
|
|
286
|
+
// Potential follow-up: we can compare message.length to
|
|
287
|
+
// report.sizeEstimator.bytes and use it to "learn" if our estimation is
|
|
288
|
+
// off and adjust it based on what we learn.
|
|
289
|
+
|
|
290
|
+
if (options.debugPrintReports) {
|
|
291
|
+
// We decode the report rather than printing the original `report`
|
|
292
|
+
// so that it includes all of the pre-encoded traces.
|
|
293
|
+
const decodedReport = Report.decode(message);
|
|
294
|
+
logger.info(
|
|
295
|
+
`Apollo usage report: ${JSON.stringify(decodedReport.toJSON())}`,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const compressed = await new Promise<Buffer>((resolve, reject) => {
|
|
300
|
+
gzip(message!, (error, result) => {
|
|
301
|
+
error ? reject(error) : resolve(result);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
// Let the uncompressed message be garbage collected (helpful if the
|
|
305
|
+
// HTTP request is slow).
|
|
306
|
+
message = null;
|
|
307
|
+
|
|
308
|
+
// Wrap fetcher with async-retry for automatic retrying
|
|
309
|
+
const fetcher: Fetcher = options.fetcher ?? fetch;
|
|
310
|
+
const response: FetcherResponse = await retry(
|
|
311
|
+
// Retry on network errors and 5xx HTTP
|
|
312
|
+
// responses.
|
|
313
|
+
async () => {
|
|
314
|
+
const curResponse = await fetcher(
|
|
315
|
+
(options.endpointUrl ||
|
|
316
|
+
'https://usage-reporting.api.apollographql.com') +
|
|
317
|
+
'/api/ingress/traces',
|
|
318
|
+
{
|
|
319
|
+
method: 'POST',
|
|
320
|
+
headers: {
|
|
321
|
+
'user-agent': 'ApolloServerPluginUsageReporting',
|
|
322
|
+
'x-api-key': key,
|
|
323
|
+
'content-encoding': 'gzip',
|
|
324
|
+
accept: 'application/json',
|
|
325
|
+
},
|
|
326
|
+
body: compressed,
|
|
327
|
+
signal: AbortSignal.timeout(options.requestTimeoutMs ?? 30_000),
|
|
328
|
+
},
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
if (curResponse.status >= 500 && curResponse.status < 600) {
|
|
332
|
+
throw new Error(
|
|
333
|
+
`HTTP status ${curResponse.status}, ${
|
|
334
|
+
(await curResponse.text()) || '(no body)'
|
|
335
|
+
}`,
|
|
336
|
+
);
|
|
337
|
+
} else {
|
|
338
|
+
return curResponse;
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
retries: (options.maxAttempts || 5) - 1,
|
|
343
|
+
minTimeout: options.minimumRetryDelayMs || 100,
|
|
344
|
+
factor: 2,
|
|
345
|
+
},
|
|
346
|
+
).catch((err: Error) => {
|
|
347
|
+
throw new Error(
|
|
348
|
+
`Error sending report to Apollo servers: ${err.message}`,
|
|
349
|
+
);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
if (response.status < 200 || response.status >= 300) {
|
|
353
|
+
// Note that we don't expect to see a 3xx here because request follows
|
|
354
|
+
// redirects.
|
|
355
|
+
throw new Error(
|
|
356
|
+
`Error sending report to Apollo servers: HTTP status ${
|
|
357
|
+
response.status
|
|
358
|
+
}, ${(await response.text()) || '(no body)'}`,
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (
|
|
363
|
+
sendTraces &&
|
|
364
|
+
response.status === 200 &&
|
|
365
|
+
response.headers
|
|
366
|
+
.get('content-type')
|
|
367
|
+
?.match(/^\s*application\/json\s*(?:;|$)/i)
|
|
368
|
+
) {
|
|
369
|
+
const body = await response.text();
|
|
370
|
+
let parsedBody;
|
|
371
|
+
try {
|
|
372
|
+
parsedBody = JSON.parse(body);
|
|
373
|
+
} catch (e) {
|
|
374
|
+
throw new Error(`Error parsing response from Apollo servers: ${e}`);
|
|
375
|
+
}
|
|
376
|
+
if (parsedBody.tracesIgnored === true) {
|
|
377
|
+
logger.debug(
|
|
378
|
+
"This graph's organization does not have access to traces; sending all " +
|
|
379
|
+
'subsequent operations as stats.',
|
|
380
|
+
);
|
|
381
|
+
sendTraces = false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (options.debugPrintReports) {
|
|
385
|
+
logger.info(`Apollo usage report: status ${response.status}`);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
requestDidStartHandler = ({
|
|
390
|
+
metrics,
|
|
391
|
+
schema,
|
|
392
|
+
request: { http, variables },
|
|
393
|
+
}): GraphQLRequestListener<TContext> => {
|
|
394
|
+
const treeBuilder: TraceTreeBuilder = new TraceTreeBuilder({
|
|
395
|
+
maskedBy: 'ApolloServerPluginUsageReporting',
|
|
396
|
+
sendErrors: options.sendErrors,
|
|
397
|
+
});
|
|
398
|
+
treeBuilder.startTiming();
|
|
399
|
+
metrics.startHrTime = treeBuilder.startHrTime;
|
|
400
|
+
let graphqlValidationFailure = false;
|
|
401
|
+
let graphqlUnknownOperationName = false;
|
|
402
|
+
let includeOperationInUsageReporting: boolean | null = null;
|
|
403
|
+
|
|
404
|
+
if (http) {
|
|
405
|
+
treeBuilder.trace.http = new Trace.HTTP({
|
|
406
|
+
method:
|
|
407
|
+
Trace.HTTP.Method[
|
|
408
|
+
http.method as keyof typeof Trace.HTTP.Method
|
|
409
|
+
] || Trace.HTTP.Method.UNKNOWN,
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
if (options.sendHeaders) {
|
|
413
|
+
makeHTTPRequestHeaders(
|
|
414
|
+
treeBuilder.trace.http,
|
|
415
|
+
http.headers,
|
|
416
|
+
options.sendHeaders,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// After this function completes, includeOperationInUsageReporting is
|
|
422
|
+
// defined.
|
|
423
|
+
async function maybeCallIncludeRequestHook(
|
|
424
|
+
requestContext:
|
|
425
|
+
| GraphQLRequestContextDidResolveOperation<TContext>
|
|
426
|
+
| GraphQLRequestContextWillSendResponse<TContext>,
|
|
427
|
+
): Promise<void> {
|
|
428
|
+
// If this is the second call in `willSendResponse` after
|
|
429
|
+
// `didResolveOperation`, we're done.
|
|
430
|
+
if (includeOperationInUsageReporting !== null) return;
|
|
431
|
+
|
|
432
|
+
if (typeof options.includeRequest !== 'function') {
|
|
433
|
+
// Default case we always report
|
|
434
|
+
includeOperationInUsageReporting = true;
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
includeOperationInUsageReporting =
|
|
438
|
+
await options.includeRequest(requestContext);
|
|
439
|
+
|
|
440
|
+
// Help the user understand they've returned an unexpected value,
|
|
441
|
+
// which might be a subtle mistake.
|
|
442
|
+
if (typeof includeOperationInUsageReporting !== 'boolean') {
|
|
443
|
+
logger.warn(
|
|
444
|
+
"The 'includeRequest' async predicate function must return a boolean value.",
|
|
445
|
+
);
|
|
446
|
+
includeOperationInUsageReporting = true;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Our usage reporting groups everything by operation, so we don't
|
|
451
|
+
// actually report about any issues that prevent us from getting an
|
|
452
|
+
// operation string (eg, a missing operation, or APQ problems).
|
|
453
|
+
// This is effectively bypassing the reporting of:
|
|
454
|
+
// - PersistedQueryNotFoundError
|
|
455
|
+
// - PersistedQueryNotSupportedError
|
|
456
|
+
// - Missing `query` error
|
|
457
|
+
// We may want to report them some other way later!
|
|
458
|
+
let didResolveSource = false;
|
|
459
|
+
|
|
460
|
+
return {
|
|
461
|
+
async didResolveSource(requestContext) {
|
|
462
|
+
didResolveSource = true;
|
|
463
|
+
|
|
464
|
+
if (metrics.persistedQueryHit) {
|
|
465
|
+
treeBuilder.trace.persistedQueryHit = true;
|
|
466
|
+
}
|
|
467
|
+
if (metrics.persistedQueryRegister) {
|
|
468
|
+
treeBuilder.trace.persistedQueryRegister = true;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (variables) {
|
|
472
|
+
treeBuilder.trace.details = makeTraceDetails(
|
|
473
|
+
variables,
|
|
474
|
+
options.sendVariableValues,
|
|
475
|
+
requestContext.source,
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const clientInfo = (
|
|
480
|
+
options.generateClientInfo || defaultGenerateClientInfo
|
|
481
|
+
)(requestContext);
|
|
482
|
+
if (clientInfo) {
|
|
483
|
+
// While there is a clientAddress protobuf field, the backend
|
|
484
|
+
// doesn't pay attention to it yet, so we'll ignore it for now.
|
|
485
|
+
const { clientName, clientVersion } = clientInfo;
|
|
486
|
+
treeBuilder.trace.clientVersion = clientVersion || '';
|
|
487
|
+
treeBuilder.trace.clientName = clientName || '';
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
async validationDidStart() {
|
|
491
|
+
return async (validationErrors?: ReadonlyArray<Error>) => {
|
|
492
|
+
graphqlValidationFailure = validationErrors
|
|
493
|
+
? validationErrors.length !== 0
|
|
494
|
+
: false;
|
|
495
|
+
};
|
|
496
|
+
},
|
|
497
|
+
async didResolveOperation(requestContext) {
|
|
498
|
+
// If operation is undefined then `getOperationAST` returned null
|
|
499
|
+
// and an unknown operation was specified.
|
|
500
|
+
graphqlUnknownOperationName =
|
|
501
|
+
requestContext.operation === undefined;
|
|
502
|
+
await maybeCallIncludeRequestHook(requestContext);
|
|
503
|
+
|
|
504
|
+
if (
|
|
505
|
+
includeOperationInUsageReporting &&
|
|
506
|
+
// No need to capture traces if the operation is going to
|
|
507
|
+
// immediately fail due to unknown operation name.
|
|
508
|
+
!graphqlUnknownOperationName
|
|
509
|
+
) {
|
|
510
|
+
if (metrics.captureTraces === undefined) {
|
|
511
|
+
// We're not completely ignoring the operation. But should we
|
|
512
|
+
// calculate a detailed trace of every field while we do so (either
|
|
513
|
+
// directly in this plugin, or in a subgraph by sending the
|
|
514
|
+
// apollo-federation-include-trace header)? That will allow this
|
|
515
|
+
// operation to contribute to the "field executions" column in the
|
|
516
|
+
// Studio Fields page, to the timing hints in Explorer and
|
|
517
|
+
// vscode-graphql, and to the traces visible under Operations. (Note
|
|
518
|
+
// that `true` here does not imply that this operation will
|
|
519
|
+
// necessarily be *sent* to the usage-reporting endpoint in the form
|
|
520
|
+
// of a trace --- it still might be aggregated into stats first. But
|
|
521
|
+
// capturing a trace will mean we can understand exactly what fields
|
|
522
|
+
// were executed and what their performance was, at the tradeoff of
|
|
523
|
+
// some overhead for tracking the trace (and transmitting it between
|
|
524
|
+
// subgraph and gateway).
|
|
525
|
+
const rawWeight =
|
|
526
|
+
await fieldLevelInstrumentation(requestContext);
|
|
527
|
+
treeBuilder.trace.fieldExecutionWeight =
|
|
528
|
+
typeof rawWeight === 'number' ? rawWeight : rawWeight ? 1 : 0;
|
|
529
|
+
|
|
530
|
+
metrics.captureTraces =
|
|
531
|
+
!!treeBuilder.trace.fieldExecutionWeight;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
async executionDidStart() {
|
|
536
|
+
// If we're not capturing traces, don't return a willResolveField so
|
|
537
|
+
// that we don't build up a detailed trace inside treeBuilder. (We still
|
|
538
|
+
// will use treeBuilder as a convenient place to put top-level facts
|
|
539
|
+
// about the operation which can end up aggregated as stats, and we do
|
|
540
|
+
// eventually put *errors* onto the trace tree.)
|
|
541
|
+
if (!metrics.captureTraces) return;
|
|
542
|
+
|
|
543
|
+
return {
|
|
544
|
+
willResolveField({ info }) {
|
|
545
|
+
return treeBuilder.willResolveField(info);
|
|
546
|
+
// We could save the error into the trace during the end handler, but
|
|
547
|
+
// it won't have all the information that graphql-js adds to it later,
|
|
548
|
+
// like 'locations'.
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
},
|
|
552
|
+
|
|
553
|
+
async didEncounterSubsequentErrors(_requestContext, errors) {
|
|
554
|
+
treeBuilder.didEncounterErrors(errors);
|
|
555
|
+
},
|
|
556
|
+
|
|
557
|
+
async willSendSubsequentPayload(requestContext, payload) {
|
|
558
|
+
if (!payload.hasNext) {
|
|
559
|
+
await operationFinished(requestContext);
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
|
|
563
|
+
async willSendResponse(requestContext) {
|
|
564
|
+
// Search above for a comment about "didResolveSource" to see which
|
|
565
|
+
// of the pre-source-resolution errors we are intentionally avoiding.
|
|
566
|
+
if (!didResolveSource) return;
|
|
567
|
+
if (requestContext.errors) {
|
|
568
|
+
treeBuilder.didEncounterErrors(requestContext.errors);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// If there isn't any defer/stream coming later, we're done.
|
|
572
|
+
// Otherwise willSendSubsequentPayload will trigger
|
|
573
|
+
// operationFinished.
|
|
574
|
+
if (requestContext.response.body.kind === 'single') {
|
|
575
|
+
await operationFinished(requestContext);
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
async function operationFinished(
|
|
581
|
+
requestContext: GraphQLRequestContextWillSendResponse<TContext>,
|
|
582
|
+
) {
|
|
583
|
+
const resolvedOperation = !!requestContext.operation;
|
|
584
|
+
|
|
585
|
+
// If we got an error before we called didResolveOperation (eg parse or
|
|
586
|
+
// validation error), check to see if we should include the request.
|
|
587
|
+
await maybeCallIncludeRequestHook(requestContext);
|
|
588
|
+
|
|
589
|
+
treeBuilder.stopTiming();
|
|
590
|
+
const executableSchemaId =
|
|
591
|
+
overriddenExecutableSchemaId ?? executableSchemaIdForSchema(schema);
|
|
592
|
+
|
|
593
|
+
if (includeOperationInUsageReporting === false) {
|
|
594
|
+
if (resolvedOperation) {
|
|
595
|
+
getReportWhichMustBeUsedImmediately(executableSchemaId)
|
|
596
|
+
.operationCount++;
|
|
597
|
+
}
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
treeBuilder.trace.fullQueryCacheHit = !!metrics.responseCacheHit;
|
|
602
|
+
treeBuilder.trace.forbiddenOperation = !!metrics.forbiddenOperation;
|
|
603
|
+
treeBuilder.trace.registeredOperation = !!metrics.registeredOperation;
|
|
604
|
+
|
|
605
|
+
const policyIfCacheable =
|
|
606
|
+
requestContext.overallCachePolicy.policyIfCacheable();
|
|
607
|
+
if (policyIfCacheable) {
|
|
608
|
+
treeBuilder.trace.cachePolicy = new Trace.CachePolicy({
|
|
609
|
+
scope:
|
|
610
|
+
policyIfCacheable.scope === 'PRIVATE'
|
|
611
|
+
? Trace.CachePolicy.Scope.PRIVATE
|
|
612
|
+
: policyIfCacheable.scope === 'PUBLIC'
|
|
613
|
+
? Trace.CachePolicy.Scope.PUBLIC
|
|
614
|
+
: Trace.CachePolicy.Scope.UNKNOWN,
|
|
615
|
+
// Convert from seconds to ns.
|
|
616
|
+
maxAgeNs: policyIfCacheable.maxAge * 1e9,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// If this was a federated operation and we're the gateway, add the query plan
|
|
621
|
+
// to the trace.
|
|
622
|
+
if (metrics.queryPlanTrace) {
|
|
623
|
+
treeBuilder.trace.queryPlan = metrics.queryPlanTrace;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Intentionally un-awaited so as not to block the response. Any
|
|
627
|
+
// errors will be logged, but will not manifest a user-facing error.
|
|
628
|
+
// The logger in this case is a request specific logger OR the logger
|
|
629
|
+
// defined by the plugin if that's unavailable. The request-specific
|
|
630
|
+
// logger is preferred since this is very much coupled directly to a
|
|
631
|
+
// client-triggered action which might be more granularly tagged by
|
|
632
|
+
// logging implementations.
|
|
633
|
+
addTrace().catch(logger.error.bind(logger));
|
|
634
|
+
|
|
635
|
+
async function addTrace(): Promise<void> {
|
|
636
|
+
// Ignore traces that come in after stop().
|
|
637
|
+
if (stopped) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Ensure that the caller of addTrace (which does not await it) is
|
|
642
|
+
// not blocked. We use setImmediate rather than process.nextTick or
|
|
643
|
+
// just relying on the Promise microtask queue because setImmediate
|
|
644
|
+
// comes after IO, which is what we want.
|
|
645
|
+
await new Promise((res) => setImmediate(res));
|
|
646
|
+
|
|
647
|
+
const executableSchemaId =
|
|
648
|
+
overriddenExecutableSchemaId ??
|
|
649
|
+
executableSchemaIdForSchema(schema);
|
|
650
|
+
|
|
651
|
+
const { trace } = treeBuilder;
|
|
652
|
+
|
|
653
|
+
let statsReportKey: string | undefined = undefined;
|
|
654
|
+
let referencedFieldsByType: ReferencedFieldsByType;
|
|
655
|
+
if (!requestContext.document) {
|
|
656
|
+
statsReportKey = `## GraphQLParseFailure\n`;
|
|
657
|
+
} else if (graphqlValidationFailure) {
|
|
658
|
+
statsReportKey = `## GraphQLValidationFailure\n`;
|
|
659
|
+
} else if (graphqlUnknownOperationName) {
|
|
660
|
+
statsReportKey = `## GraphQLUnknownOperationName\n`;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const isExecutable = statsReportKey === undefined;
|
|
664
|
+
|
|
665
|
+
if (statsReportKey) {
|
|
666
|
+
if (options.sendUnexecutableOperationDocuments) {
|
|
667
|
+
trace.unexecutedOperationBody = requestContext.source;
|
|
668
|
+
// Get the operation name from the request (which might not
|
|
669
|
+
// correspond to an actual operation).
|
|
670
|
+
trace.unexecutedOperationName =
|
|
671
|
+
requestContext.request.operationName || '';
|
|
672
|
+
}
|
|
673
|
+
referencedFieldsByType = Object.create(null);
|
|
674
|
+
} else {
|
|
675
|
+
const operationDerivedData = getOperationDerivedData();
|
|
676
|
+
statsReportKey = `# ${requestContext.operationName || '-'}\n${
|
|
677
|
+
operationDerivedData.signature
|
|
678
|
+
}`;
|
|
679
|
+
referencedFieldsByType =
|
|
680
|
+
operationDerivedData.referencedFieldsByType;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const protobufError = Trace.verify(trace);
|
|
684
|
+
if (protobufError) {
|
|
685
|
+
throw new Error(`Error encoding trace: ${protobufError}`);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (resolvedOperation) {
|
|
689
|
+
getReportWhichMustBeUsedImmediately(executableSchemaId)
|
|
690
|
+
.operationCount++;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
getReportWhichMustBeUsedImmediately(executableSchemaId).addTrace({
|
|
694
|
+
statsReportKey,
|
|
695
|
+
trace,
|
|
696
|
+
// We include the operation as a trace (rather than aggregated into stats) only if:
|
|
697
|
+
// * the user didn't set `sendTraces: false` AND
|
|
698
|
+
// * it's possible that the organization's plan allows for viewing traces AND
|
|
699
|
+
// * we captured this as a full trace AND
|
|
700
|
+
// * gateway reported no errors missing ftv1 data AND
|
|
701
|
+
// * sendOperationAsTrace says so
|
|
702
|
+
//
|
|
703
|
+
// (As an edge case, if the reason metrics.captureTraces is
|
|
704
|
+
// falsey is that this is an unexecutable operation and thus we
|
|
705
|
+
// never ran the code in didResolveOperation that sets
|
|
706
|
+
// metrics.captureTrace, we allow it to be sent as a trace. This
|
|
707
|
+
// means we'll still send some parse and validation failures as
|
|
708
|
+
// traces, for the sake of the Errors page.)
|
|
709
|
+
asTrace:
|
|
710
|
+
sendTraces &&
|
|
711
|
+
(!isExecutable || !!metrics.captureTraces) &&
|
|
712
|
+
!metrics.nonFtv1ErrorPaths?.length &&
|
|
713
|
+
sendOperationAsTrace(trace, statsReportKey),
|
|
714
|
+
referencedFieldsByType,
|
|
715
|
+
nonFtv1ErrorPaths: metrics.nonFtv1ErrorPaths ?? [],
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
// If the buffer gets big (according to our estimate), send.
|
|
719
|
+
if (
|
|
720
|
+
sendReportsImmediately ||
|
|
721
|
+
getReportWhichMustBeUsedImmediately(executableSchemaId)
|
|
722
|
+
.sizeEstimator.bytes >=
|
|
723
|
+
(options.maxUncompressedReportSize || 4 * 1024 * 1024)
|
|
724
|
+
) {
|
|
725
|
+
await sendReportAndReportErrors(executableSchemaId);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Calculates signature and referenced fields for the current document.
|
|
730
|
+
// Only call this when the document properly parses and validates and
|
|
731
|
+
// the given operation name (if any) is known!
|
|
732
|
+
function getOperationDerivedData(): OperationDerivedData {
|
|
733
|
+
if (!requestContext.document) {
|
|
734
|
+
// This shouldn't happen: no document means parse failure, which
|
|
735
|
+
// uses its own special statsReportKey.
|
|
736
|
+
throw new Error('No document?');
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
const cacheKey = operationDerivedDataCacheKey(
|
|
740
|
+
requestContext.queryHash,
|
|
741
|
+
requestContext.operationName || '',
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
// Ensure that the cache we have is for the right schema.
|
|
745
|
+
if (
|
|
746
|
+
!operationDerivedDataCache ||
|
|
747
|
+
operationDerivedDataCache.forSchema !== schema
|
|
748
|
+
) {
|
|
749
|
+
operationDerivedDataCache = {
|
|
750
|
+
forSchema: schema,
|
|
751
|
+
cache: createOperationDerivedDataCache({ logger }),
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// If we didn't have the signature in the cache, we'll resort to
|
|
756
|
+
// calculating it.
|
|
757
|
+
const cachedOperationDerivedData =
|
|
758
|
+
operationDerivedDataCache.cache.get(cacheKey);
|
|
759
|
+
if (cachedOperationDerivedData) {
|
|
760
|
+
return cachedOperationDerivedData;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const generatedSignature = (
|
|
764
|
+
options.calculateSignature || usageReportingSignature
|
|
765
|
+
)(requestContext.document, requestContext.operationName || '');
|
|
766
|
+
|
|
767
|
+
const generatedOperationDerivedData: OperationDerivedData = {
|
|
768
|
+
signature: generatedSignature,
|
|
769
|
+
referencedFieldsByType: calculateReferencedFieldsByType({
|
|
770
|
+
document: requestContext.document,
|
|
771
|
+
schema,
|
|
772
|
+
resolvedOperationName: requestContext.operationName ?? null,
|
|
773
|
+
}),
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
// Note that this cache is always an in-memory cache.
|
|
777
|
+
// If we replace it with a more generic async cache, we should
|
|
778
|
+
// not await the write operation.
|
|
779
|
+
operationDerivedDataCache.cache.set(
|
|
780
|
+
cacheKey,
|
|
781
|
+
generatedOperationDerivedData,
|
|
782
|
+
);
|
|
783
|
+
return generatedOperationDerivedData;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
return {
|
|
789
|
+
async serverWillStop() {
|
|
790
|
+
if (reportTimer) {
|
|
791
|
+
clearInterval(reportTimer);
|
|
792
|
+
reportTimer = undefined;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
stopped = true;
|
|
796
|
+
await sendAllReportsAndReportErrors();
|
|
797
|
+
},
|
|
798
|
+
};
|
|
799
|
+
},
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
export function makeHTTPRequestHeaders(
|
|
804
|
+
http: Trace.IHTTP,
|
|
805
|
+
headers: HeaderMap,
|
|
806
|
+
sendHeaders?: SendValuesBaseOptions,
|
|
807
|
+
): void {
|
|
808
|
+
if (
|
|
809
|
+
!sendHeaders ||
|
|
810
|
+
('none' in sendHeaders && sendHeaders.none) ||
|
|
811
|
+
('all' in sendHeaders && !sendHeaders.all)
|
|
812
|
+
) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
for (const [key, value] of headers) {
|
|
816
|
+
// Note that HeaderMap keys are already lower-case.
|
|
817
|
+
if (
|
|
818
|
+
('exceptNames' in sendHeaders &&
|
|
819
|
+
// We assume that most users only have a few headers to hide, or will
|
|
820
|
+
// just set {none: true} ; we can change this linear-time
|
|
821
|
+
// operation if it causes real performance issues.
|
|
822
|
+
sendHeaders.exceptNames.some((exceptHeader) => {
|
|
823
|
+
// Headers are case-insensitive, and should be compared as such.
|
|
824
|
+
return exceptHeader.toLowerCase() === key;
|
|
825
|
+
})) ||
|
|
826
|
+
('onlyNames' in sendHeaders &&
|
|
827
|
+
!sendHeaders.onlyNames.some((header) => {
|
|
828
|
+
return header.toLowerCase() === key;
|
|
829
|
+
}))
|
|
830
|
+
) {
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
switch (key) {
|
|
835
|
+
case 'authorization':
|
|
836
|
+
case 'cookie':
|
|
837
|
+
case 'set-cookie':
|
|
838
|
+
break;
|
|
839
|
+
default:
|
|
840
|
+
http!.requestHeaders![key] = new Trace.HTTP.Values({
|
|
841
|
+
value: [value],
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
function defaultGenerateClientInfo<TContext extends BaseContext>({
|
|
848
|
+
request,
|
|
849
|
+
}: GraphQLRequestContext<TContext>) {
|
|
850
|
+
const clientNameHeaderKey = 'apollographql-client-name';
|
|
851
|
+
const clientVersionHeaderKey = 'apollographql-client-version';
|
|
852
|
+
|
|
853
|
+
// Default to using the `apollo-client-x` header fields if present.
|
|
854
|
+
// If none are present, fallback on the `clientInfo` query extension
|
|
855
|
+
// for backwards compatibility.
|
|
856
|
+
// The default value if neither header values nor query extension is
|
|
857
|
+
// set is the empty String for all fields (as per protobuf defaults)
|
|
858
|
+
if (
|
|
859
|
+
request.http?.headers?.get(clientNameHeaderKey) ||
|
|
860
|
+
request.http?.headers?.get(clientVersionHeaderKey)
|
|
861
|
+
) {
|
|
862
|
+
return {
|
|
863
|
+
clientName: request.http?.headers?.get(clientNameHeaderKey),
|
|
864
|
+
clientVersion: request.http?.headers?.get(clientVersionHeaderKey),
|
|
865
|
+
};
|
|
866
|
+
} else if (request.extensions?.clientInfo) {
|
|
867
|
+
return request.extensions.clientInfo;
|
|
868
|
+
} else {
|
|
869
|
+
return {};
|
|
870
|
+
}
|
|
871
|
+
}
|