├── .cacert.pem ├── .changeset ├── README.md └── config.json ├── .circleci └── config.yml ├── .codesandbox └── ci.json ├── .config └── mise │ └── config.toml ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ └── feature-request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── lock.yml │ └── release-pr.yml ├── .gitignore ├── .gitleaks.toml ├── .npmrc ├── .prettierignore ├── .prettierrc.json5 ├── .vscode ├── extensions.json ├── settings.json └── tasks.json ├── CHANGELOG_historical.md ├── CONTRIBUTING.md ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── codecov.yml ├── codegen.yml ├── cspell-dict.txt ├── cspell.yaml ├── docs ├── README.md └── source │ ├── _sidebar.yaml │ ├── api │ ├── apollo-server.mdx │ ├── express-middleware.mdx │ ├── plugin │ │ ├── cache-control.mdx │ │ ├── drain-http-server.mdx │ │ ├── inline-trace.mdx │ │ ├── landing-pages.mdx │ │ ├── schema-reporting.mdx │ │ ├── subscription-callback.mdx │ │ └── usage-reporting.mdx │ └── standalone.mdx │ ├── builtin-plugins.md │ ├── data │ ├── context.mdx │ ├── errors.mdx │ ├── fetching-data.mdx │ ├── fetching-rest.mdx │ ├── resolvers.mdx │ └── subscriptions.mdx │ ├── deployment │ ├── heroku.md │ └── lambda.mdx │ ├── getting-started.mdx │ ├── images │ ├── as-landing-page-production.jpg │ ├── default-sandbox.jpg │ ├── deployment │ │ └── heroku │ │ │ ├── add-integration.png │ │ │ ├── automatic-deployment.png │ │ │ ├── config-vars.jpg │ │ │ ├── create-new-app.png │ │ │ ├── heroku-github-instructions.png │ │ │ ├── new-app.png │ │ │ └── set-app-name.png │ ├── introduction.jpg │ ├── playground.png │ ├── sandbox-mern-stack.jpg │ ├── sandbox-response.png │ └── sandbox.jpeg │ ├── index.mdx │ ├── integrations │ ├── building-integrations.md │ ├── integration-index.mdx │ ├── mern.mdx │ ├── plugins-event-reference.mdx │ └── plugins.mdx │ ├── migration.mdx │ ├── monitoring │ ├── health-checks.mdx │ └── metrics.mdx │ ├── performance │ ├── apq.mdx │ ├── cache-backends.mdx │ ├── caching.md │ └── response-cache-eviction.mdx │ ├── previous-versions.mdx │ ├── schema │ ├── custom-scalars.mdx │ ├── directives.md │ ├── schema.md │ └── unions-interfaces.md │ ├── security │ ├── authentication.mdx │ ├── cors.mdx │ ├── proxy-configuration.md │ └── terminating-ssl.mdx │ ├── shared │ ├── diagrams │ │ └── federation-architecture.mdx │ ├── integration-table.mdx │ └── top-level-await.mdx │ ├── testing │ ├── mocking.mdx │ └── testing.mdx │ ├── using-federation │ ├── api │ │ ├── apollo-gateway.mdx │ │ └── apollo-subgraph.mdx │ ├── apollo-gateway-setup.mdx │ ├── apollo-subgraph-setup.mdx │ └── gateway-performance.mdx │ └── workflow │ ├── build-run-queries.mdx │ ├── generate-types.mdx │ └── requests.md ├── jest.config.base.js ├── jest.setup.js ├── package-lock.json ├── package.json ├── packages ├── cache-control-types │ ├── .npmignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.cjs.json │ └── tsconfig.json ├── gateway-interface │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.cjs.json │ └── tsconfig.json ├── integration-testsuite │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── apolloFetch.ts │ │ ├── apolloServerTests.ts │ │ ├── httpServerTests.ts │ │ ├── httpSpecTests.ts │ │ ├── index.ts │ │ └── resolvable.ts │ └── tsconfig.cjs.json ├── plugin-response-cache │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── ApolloServerPluginResponseCache.ts │ │ ├── __tests__ │ │ │ ├── ApolloServerPluginResponseCache.test.ts │ │ │ ├── integration.test.ts │ │ │ └── tsconfig.json │ │ └── index.ts │ ├── tsconfig.cjs.json │ └── tsconfig.json ├── server │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── README_landingpages.md │ ├── errors │ │ └── package.json │ ├── express4 │ │ └── package.json │ ├── jest.config.js │ ├── package.json │ ├── plugin │ │ ├── cacheControl │ │ │ └── package.json │ │ ├── disableSuggestions │ │ │ └── package.json │ │ ├── disabled │ │ │ └── package.json │ │ ├── drainHttpServer │ │ │ └── package.json │ │ ├── inlineTrace │ │ │ └── package.json │ │ ├── landingPage │ │ │ └── default │ │ │ │ └── package.json │ │ ├── schemaReporting │ │ │ └── package.json │ │ ├── subscriptionCallback │ │ │ └── package.json │ │ └── usageReporting │ │ │ └── package.json │ ├── src │ │ ├── ApolloServer.ts │ │ ├── __tests__ │ │ │ ├── ApolloServer.test.ts │ │ │ ├── cachePolicy.test.ts │ │ │ ├── documentStore.test.ts │ │ │ ├── errors.test.ts │ │ │ ├── express4 │ │ │ │ ├── expressSpecific.test.ts │ │ │ │ ├── integration.test.ts │ │ │ │ └── integrationServerless.test.ts │ │ │ ├── logger.test.ts │ │ │ ├── mockLogger.ts │ │ │ ├── nockAssertions.ts │ │ │ ├── plugin │ │ │ │ ├── cacheControl │ │ │ │ │ ├── cacheControlDirective.test.ts │ │ │ │ │ ├── cacheControlPlugin.test.ts │ │ │ │ │ ├── cacheControlSupport.ts │ │ │ │ │ ├── collectCacheControlHints.ts │ │ │ │ │ └── dynamicCacheControl.test.ts │ │ │ │ ├── disableSuggestions │ │ │ │ │ └── disableSuggestions.test.ts │ │ │ │ ├── drainHttpServer │ │ │ │ │ ├── stoppable.test.ts │ │ │ │ │ └── stoppable │ │ │ │ │ │ ├── fixture.cert │ │ │ │ │ │ └── fixture.key │ │ │ │ ├── inlineTrace │ │ │ │ │ └── inlineTracePlugin.test.ts │ │ │ │ ├── landingPage │ │ │ │ │ ├── getEmbeddedExplorerHTML.test.ts │ │ │ │ │ ├── getEmbeddedSandboxHTML.test.ts │ │ │ │ │ └── plugin.test.ts │ │ │ │ ├── schemaIsSubgraph.test.ts │ │ │ │ ├── schemaReporting │ │ │ │ │ ├── index.test.ts │ │ │ │ │ └── schemaReporter.test.ts │ │ │ │ ├── subscriptionCallback │ │ │ │ │ └── index.test.ts │ │ │ │ └── usageReporting │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── stats.test.ts.snap │ │ │ │ │ ├── durationHistogram.test.ts │ │ │ │ │ ├── operationDerivedDataCache.test.ts │ │ │ │ │ ├── plugin.test.ts │ │ │ │ │ ├── stats.test.ts │ │ │ │ │ ├── statsErrors.test.ts │ │ │ │ │ └── traceDetails.test.ts │ │ │ ├── rollupCommonJs.test.ts │ │ │ ├── runQuery.test.ts │ │ │ ├── standalone │ │ │ │ ├── integration.test.ts │ │ │ │ └── standaloneSpecific.test.ts │ │ │ ├── tsconfig.json │ │ │ ├── utils │ │ │ │ ├── computeCoreSchemaHash.test.ts │ │ │ │ └── schemaInstrumentation.test.ts │ │ │ └── validationRules │ │ │ │ └── recursiveSelectionsLimit.test.ts │ │ ├── cachePolicy.ts │ │ ├── determineApolloConfig.ts │ │ ├── errorNormalize.ts │ │ ├── errors │ │ │ └── index.ts │ │ ├── express4 │ │ │ └── index.ts │ │ ├── externalTypes │ │ │ ├── constructor.ts │ │ │ ├── context.ts │ │ │ ├── graphql.ts │ │ │ ├── http.ts │ │ │ ├── incrementalDeliveryPolyfill.ts │ │ │ ├── index.ts │ │ │ ├── plugins.ts │ │ │ └── requestPipeline.ts │ │ ├── httpBatching.ts │ │ ├── incrementalDeliveryPolyfill.ts │ │ ├── index.ts │ │ ├── internalErrorClasses.ts │ │ ├── internalPlugin.ts │ │ ├── plugin │ │ │ ├── cacheControl │ │ │ │ └── index.ts │ │ │ ├── disableSuggestions │ │ │ │ └── index.ts │ │ │ ├── disabled │ │ │ │ └── index.ts │ │ │ ├── drainHttpServer │ │ │ │ ├── index.ts │ │ │ │ └── stoppable.ts │ │ │ ├── inlineTrace │ │ │ │ └── index.ts │ │ │ ├── landingPage │ │ │ │ └── default │ │ │ │ │ ├── getEmbeddedHTML.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ ├── schemaIsSubgraph.ts │ │ │ ├── schemaReporting │ │ │ │ ├── generated │ │ │ │ │ └── operations.d.ts │ │ │ │ ├── index.ts │ │ │ │ └── schemaReporter.ts │ │ │ ├── subscriptionCallback │ │ │ │ └── index.ts │ │ │ ├── traceTreeBuilder.ts │ │ │ └── usageReporting │ │ │ │ ├── defaultSendOperationsAsTrace.ts │ │ │ │ ├── durationHistogram.ts │ │ │ │ ├── index.ts │ │ │ │ ├── iterateOverTrace.ts │ │ │ │ ├── operationDerivedDataCache.ts │ │ │ │ ├── options.ts │ │ │ │ ├── plugin.ts │ │ │ │ ├── stats.ts │ │ │ │ └── traceDetails.ts │ │ ├── preventCsrf.ts │ │ ├── requestPipeline.ts │ │ ├── runHttpQuery.ts │ │ ├── standalone │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── HeaderMap.ts │ │ │ ├── UnreachableCaseError.ts │ │ │ ├── computeCoreSchemaHash.ts │ │ │ ├── invokeHooks.ts │ │ │ ├── isDefined.ts │ │ │ ├── makeGatewayGraphQLRequestContext.ts │ │ │ ├── resolvable.ts │ │ │ ├── schemaInstrumentation.ts │ │ │ ├── schemaManager.ts │ │ │ └── urlForHttpServer.ts │ │ └── validationRules │ │ │ ├── NoIntrospection.ts │ │ │ ├── RecursiveSelectionsLimit.ts │ │ │ └── index.ts │ ├── standalone │ │ └── package.json │ ├── tsconfig.cjs.json │ └── tsconfig.json └── usage-reporting-protobuf │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── generated │ ├── cjs │ │ ├── package.json │ │ ├── protobuf.d.ts │ │ └── protobuf.js │ └── esm │ │ ├── package.json │ │ ├── protobuf.d.ts │ │ └── protobuf.js │ ├── package.json │ └── src │ ├── .editorconfig │ └── reports.proto ├── renovate.json5 ├── scripts ├── deprecate-old-versions.sh ├── postcompile.mjs └── precompile.mjs ├── smoke-test ├── gateway-compatibility │ ├── smoke-test-gateway.mts │ └── tsconfig.json ├── nodenext │ ├── package.json │ ├── src │ │ └── smoke-test.ts │ └── tsconfig.json ├── package-lock.json ├── package.json ├── prepare.sh ├── rollup.config.mjs ├── smoke-test-no-express.mjs ├── smoke-test.cjs ├── smoke-test.cts ├── smoke-test.mjs ├── smoke-test.mts ├── smoke-test.sh ├── tsconfig.cjs-node16.json ├── tsconfig.cjs-nodenext.json ├── tsconfig.cjs.json └── tsconfig.esm.json ├── tsconfig.base.json ├── tsconfig.build.cjs.json ├── tsconfig.build.esm.json ├── tsconfig.build.json ├── tsconfig.esm.json ├── tsconfig.json ├── tsconfig.test.base.json └── tsconfig.test.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "apollographql/apollo-server" } 6 | ], 7 | "commit": false, 8 | "fixed": [["@apollo/server", "@apollo/server-integration-testsuite"]], 9 | "access": "public", 10 | "baseBranch": "main", 11 | "updateInternalDependencies": "patch", 12 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 13 | "onlyUpdatePeerDependentsWhenOutOfRange": true 14 | }, 15 | "ignore": [] 16 | } 17 | -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "compile", 3 | "packages": [ 4 | "packages/cache-control-types", 5 | "packages/gateway-interface", 6 | "packages/integration-testsuite", 7 | "packages/plugin-response-cache", 8 | "packages/server", 9 | "packages/usage-reporting-protobuf" 10 | ], 11 | "sandboxes": ["apollo-server-typescript-3opde","apollo-server"], 12 | "node": "18" 13 | } 14 | -------------------------------------------------------------------------------- /.config/mise/config.toml: -------------------------------------------------------------------------------- 1 | # This is a config file for "mise-en-place": https://mise.jdx.dev/ 2 | # It pins the version of Node and can be used to run other tools as well. 3 | # It's what we use to set up tools in CI. 4 | 5 | [tools] 6 | # This actually uses the copy of npm that comes with Node to install the version 7 | # of npm that we want. Since we test on ancient versions of Node like v14, we 8 | # want to use a slightly more modern npm. Listing it before "node" means we'll 9 | # actually use it instead of the version that comes with node. 10 | "npm:npm" = "9.9.4" 11 | node = "22.16.0" 12 | 13 | [env] 14 | # Put binaries from npm-installed packages on PATH (eg `changeset`). 15 | _.path = ["{{config_root}}/node_modules/.bin"] 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | max_line_length = 80 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | generated 3 | smoke-test 4 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint', 'import'], 5 | extends: ['plugin:import/typescript'], 6 | overrides: [ 7 | { 8 | // Enable import/extensions on all TS files because our ESM builds require 9 | // you to specify local imports as full paths with extensions. We don't 10 | // need this on tests because Jest doesn't require it. 11 | files: ['**/*.ts'], 12 | excludedFiles: '**/__tests__/**/*.ts', 13 | rules: { 14 | // Disallow importing a node module without it being specified in package.json 15 | 'import/no-extraneous-dependencies': 'error', 16 | 'import/extensions': ['error', 'ignorePackages'], 17 | '@typescript-eslint/consistent-type-imports': [ 18 | 'error', 19 | { 20 | prefer: 'type-imports', 21 | fixStyle: 'inline-type-imports', 22 | }, 23 | ], 24 | }, 25 | }, 26 | ], 27 | }; 28 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /docs/ @apollographql/docs @glasser @trevor-scheer 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug 2 | description: File a bug report 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: "Hello from the Apollo Server team! Hopefully we can help resolve your issue. To increase the chances of us being able to help, please take the time to fill out the form as completely as possible. A minimal, runnable reproduction is the best way to get us to help you quickly and in many cases we simply cannot help without one. Forking our [CodeSandbox](https://codesandbox.io/p/sandbox/apollo-server-typescript-3opde) is a great place to start." 7 | - type: textarea 8 | attributes: 9 | label: Issue Description 10 | description: Describe the issue you are experiencing 11 | validations: 12 | required: false 13 | - type: input 14 | attributes: 15 | label: Link to Reproduction 16 | description: GitHub or CodeSandbox link with runnable reproduction. Make sure this includes everything necessary (package.json, tsconfig.json, etc) so we don't have to guess anything! 17 | validations: 18 | required: true 19 | - type: textarea 20 | attributes: 21 | label: Reproduction Steps 22 | description: Please provide any non-trivial steps required to reproduce the issue 23 | validations: 24 | required: false 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: "Apollo Discourse Community" 4 | url: https://community.apollographql.com/tag/server 5 | about: >- 6 | The Apollo Server tag in our Apollo Discourse Community has many existing 7 | questions and answers. You can see if your question has already been 8 | answered there or ask a new one. 9 | - name: "Stack Overflow tagged \"apollo\"" 10 | url: https://stackoverflow.com/questions/tagged/apollo 11 | about: >- 12 | If you can't find what you're looking for, many questions are already 13 | answered on Stack Overflow. 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: Have a feature that you think is important? Help us understand it. 4 | --- 5 | 6 | - Some features can be built as plugins. 7 | 8 | We encourage exploring the plugin API prior to opening a feature request: 9 | 10 | https://www.apollographql.com/docs/apollo-server/integrations/plugins/ 11 | 12 | In the event that the plugin API doesn't allow you to build a feature, it 13 | may be that expanding the plugin API *itself* is the best place for the 14 | feature to be introduced! Consider this flexible solution when opening a 15 | new feature request since it also unlocks new opportunities. 16 | 17 | - Prior to opening a feature request, please search for existing requests. 18 | 19 | If you find an existing feature that matches your needs, use the 👍 emote 20 | to show your support for it. If the specifics of your use case are not 21 | covered in the existing feature request but the idea seems similar enough, 22 | please take the time to *add new conversation* which helps the feature's 23 | design evolve. 24 | 25 | - If you do not find any other existing requests for the feature you desire, 26 | you should open a new feature request. Please take the time to help us 27 | understand your use-case as precisely as possible. Be sure to demonstrate 28 | that you've evaluated existing features and found them unsuitable and were 29 | unable to implement the functionality with the plugin API. 30 | 31 | Be flexible in your design and consider slight variations which might 32 | necessitate a specific API design. We also hope you'll be willing to engage 33 | in the on-going design discussion prior to opening a pull-request. 34 | 35 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | First, 🌠 thank you 🌠 for taking the time to consider a contribution to Apollo! 2 | 3 | Here are some important details to follow: 4 | 5 | * ⏰ Your time is important 6 | To save your precious time, if the contribution you are making will take more 7 | than an hour, please make sure it has been discussed in an issue first. 8 | This is especially true for feature requests! 9 | * 💡 Features 10 | Feature requests can be created and discussed within a GitHub Issue. Be 11 | sure to search for existing feature requests (and related issues!) prior to 12 | opening a new request. If an existing issue covers the need, please upvote 13 | that issue by using the 👍 emote, rather than opening a new issue. 14 | * 🔌 Integrations 15 | Apollo Server has many web-framework integrations including Express, Koa, 16 | Hapi and more. When adding a new feature, or fixing a bug, please take a 17 | peak and see if other integrations are also affected. In most cases, the 18 | fix can be applied to the other frameworks as well. Please note that, 19 | since new web-frameworks have a high maintenance cost, pull-requests for 20 | new web-frameworks should be discussed with a project maintainer first. 21 | * 🕷 Bug fixes 22 | These can be created and discussed in this repository. When fixing a bug, 23 | please _try_ to add a test which verifies the fix. If you cannot, you should 24 | still submit the PR but we may still ask you (and help you!) to create a test. 25 | * 📖 Contribution guidelines 26 | Follow https://github.com/apollographql/apollo-server/blob/main/CONTRIBUTING.md 27 | when submitting a pull request. Make sure existing tests still pass, and add 28 | tests for all new behavior. 29 | * ✏️ Explain your pull request 30 | Describe the big picture of your changes here to communicate to what your 31 | pull request is meant to accomplish. Provide 🔗 links 🔗 to associated issues! 32 | 33 | We hope you will find this to be a positive experience! Open source contribution can be intimidating and we hope to alleviate that pain as much as possible. Without following these guidelines, you may be missing context that can help you succeed with your contribution, which is why we encourage discussion first. Ultimately, there is no guarantee that we will be able to merge your pull-request, but by following these guidelines we can try to avoid disappointment. 34 | -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: 'Lock Threads' 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | permissions: {} 8 | jobs: 9 | lock: 10 | permissions: 11 | issues: write # to lock issues (dessant/lock-threads) 12 | pull-requests: write # to lock PRs (dessant/lock-threads) 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: dessant/lock-threads@v4 16 | with: 17 | log-output: true 18 | github-token: ${{ secrets.GITHUB_TOKEN }} 19 | 20 | issue-inactive-days: '30' 21 | issue-comment: > 22 | This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. 23 | 24 | For general questions, we recommend using our [Community Forum](https://community.apollographql.com/tag/server) or [Stack Overflow](https://stackoverflow.com/questions/tagged/apollo-server). 25 | pr-inactive-days: '30' 26 | -------------------------------------------------------------------------------- /.github/workflows/release-pr.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'apollographql/apollo-server' 13 | steps: 14 | - name: Checkout Repo 15 | uses: actions/checkout@v4 16 | with: 17 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 18 | fetch-depth: 0 19 | 20 | - name: Install Node with Mise 21 | uses: jdx/mise-action@v2 22 | 23 | # Because Mise installs Node, this action mostly just caches node_modules. 24 | - name: Setup Node.js 25 | uses: actions/setup-node@v4 26 | with: 27 | cache: 'npm' 28 | 29 | - name: Install Dependencies 30 | run: npm ci 31 | 32 | - name: Create Release Pull Request / NPM Publish 33 | uses: changesets/action@v1 34 | with: 35 | publish: npm run changeset-publish 36 | version: npm run changeset-version 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the compiled output. 2 | dist/ 3 | 4 | # TypeScript incremental compilation cache 5 | *.tsbuildinfo 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Coverage (from Jest) 15 | coverage/ 16 | 17 | # JUnit Reports (used mainly in CircleCI) 18 | reports/ 19 | junit.xml 20 | 21 | # Node modules 22 | node_modules/ 23 | 24 | # Mac OS 25 | .DS_Store 26 | 27 | # Intellij Configuration Files 28 | .idea/ 29 | 30 | # Local Netlify folder 31 | .netlify 32 | 33 | # Generated by the smoke test. 34 | smoke-test/generated 35 | 36 | # This file is written by precompile scripts. 37 | packages/server/src/generated/packageVersion.ts 38 | 39 | # Lets you add more env vars. 40 | .env 41 | 42 | # Symlinks written by the Mise VSCode extension. 43 | .vscode/mise-tools 44 | -------------------------------------------------------------------------------- /.gitleaks.toml: -------------------------------------------------------------------------------- 1 | # This file exists primarily to influence scheduled scans that Apollo runs of all repos in Apollo-managed orgs. 2 | # This is an Apollo-Internal link, but more information about these scans is available here: 3 | # https://apollographql.atlassian.net/wiki/spaces/SecOps/pages/81330213/Everything+Static+Application+Security+Testing#Scheduled-Scans.1 4 | # 5 | # Apollo is using Gitleaks (https://github.com/gitleaks/gitleaks) to run these scans. 6 | # However, this file is not something that Gitleaks natively consumes. This file is an 7 | # Apollo-convention. Prior to scanning a repo, Apollo merges 8 | # our standard Gitleaks configuration (which is largely just the Gitleaks-default config) with 9 | # this file if it exists in a repo. The combined config is then used to scan a repo. 10 | # 11 | # We did this because the natively-supported allowlisting functionality in Gitleaks didn't do everything we wanted 12 | # or wasn't as robust as we needed. For example, one of the allowlisting options offered by Gitleaks depends on the line number 13 | # on which a false positive secret exists to allowlist it. (https://github.com/gitleaks/gitleaks#gitleaksignore). 14 | # This creates a fairly fragile allowlisting mechanism. This file allows us to leverage the full capabilities of the Gitleaks rule syntax 15 | # to create allowlisting functionality. 16 | 17 | 18 | [[ rules ]] 19 | id = "high-entropy-base64" 20 | [ rules.allowlist ] 21 | commits = [ 22 | # Allowlist https://github.com/apollographql/apollo-server/blob/48aa02fe3bd6bad0a61ef122acef5fda38920df1/docs/source/getting-started.md?plain=1#L175 23 | # This is a blob of data from StackEdit 24 | "48aa02fe3bd6bad0a61ef122acef5fda38920df1", 25 | # Allowlist https://github.com/apollographql/apollo-server/blob/213acbba32829c83f99f12d81ed9e88f3fe1c8cb/docs/_config.yml#L36 26 | # This is a segment key that Apollo SecOps was unable to utilize with Segment 27 | "213acbba32829c83f99f12d81ed9e88f3fe1c8cb", 28 | 29 | ] 30 | 31 | [[ rules ]] 32 | id = "generic-api-key" 33 | [ rules.allowlist ] 34 | commits = [ 35 | # Allowlist https://github.com/apollographql/apollo-server/blob/89da132450677ae69aef156ade4c3a11e3885a33/test/testApolloServer.js#L56 36 | # Code comments indicate the value being identified is not a secret 37 | "89da132450677ae69aef156ade4c3a11e3885a33", 38 | 39 | # Allowlist https://github.com/apollographql/apollo-server/blob/213acbba32829c83f99f12d81ed9e88f3fe1c8cb/docs/_config.yml#L38 40 | # Confirmed that the DocSearch value is not a secret 41 | "213acbba32829c83f99f12d81ed9e88f3fe1c8cb", 42 | 43 | # Allowlist https://github.com/apollographql/apollo-server/blob/4155e73ff8541b12944947236cb854d258e08746/packages/apollo-gateway/src/__tests__/integration/nockMocks.ts#L19 44 | # Allowlist https://github.com/apollographql/apollo-server/blob/efa9427dcca848eafc1fd37463bcb4ac1ceeca7d/packages/apollo-gateway/src/__tests__/integration/nockMocks.ts#L5 45 | # Based on file path, the detected value is part of a test and not actually in-use 46 | "4155e73ff8541b12944947236cb854d258e08746", 47 | "efa9427dcca848eafc1fd37463bcb4ac1ceeca7d", 48 | 49 | ] 50 | 51 | [[ rules ]] 52 | id = "private-key" 53 | [ rules.allowlist ] 54 | commits = [ 55 | # Allowlist https://github.com/apollographql/apollo-server/blob/aadbeb647485207b408f620a10d8c385ce4ee25f/packages/apollo-server/src/__tests__/stoppable/fixture.key#L1 56 | # Based on file path, the private key is part of a test and not actually in-use 57 | "aadbeb647485207b408f620a10d8c385ce4ee25f", 58 | 59 | ] 60 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.json 2 | *.json5 3 | *.yml 4 | *.md 5 | *.mdx 6 | *.snap 7 | 8 | dist/ 9 | 10 | # Don't format generated files! 11 | **/generated/** 12 | 13 | .volta 14 | _redirects 15 | -------------------------------------------------------------------------------- /.prettierrc.json5: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "singleQuote": true, 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["streetsidesoftware.code-spell-checker"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "editor.tabSize": 2, 4 | "editor.rulers": [80], 5 | "editor.wordWrapColumn": 80, 6 | "files.trimTrailingWhitespace": true, 7 | "files.insertFinalNewline": true, 8 | "typescript.tsdk": "./node_modules/typescript/lib", 9 | "typescript.enablePromptUseWorkspaceTsdk": true, 10 | "mise.configureExtensionsUseSymLinks": true, 11 | "python.defaultInterpreterPath": "${workspaceFolder}/.vscode/mise-tools/python", 12 | "debug.javascript.defaultRuntimeExecutable": { 13 | "pwa-node": "${workspaceFolder}/.vscode/mise-tools/node" 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "TypeScript watch", 6 | "type": "typescript", 7 | "tsconfig": "tsconfig.build.json", 8 | "option": "watch", 9 | "problemMatcher": ["$tsc-watch"], 10 | "presentation": { 11 | "clear": true, 12 | "group": "tsc-and-shell" 13 | }, 14 | "isBackground": true 15 | }, 16 | { 17 | "label": "Shell", 18 | "type": "shell", 19 | "command": "${SHELL}", 20 | "args": ["-l"], 21 | "isBackground": true, 22 | "presentation": { 23 | "group": "tsc-and-shell" 24 | } 25 | }, 26 | { 27 | "label": "TS and shell", 28 | "dependsOn": ["TypeScript watch", "Shell"], 29 | "group": { 30 | "kind": "build", 31 | "isDefault": true 32 | }, 33 | "runOptions": { 34 | "runOn": "folderOpen" 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2020 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | packages/server/README.md -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | threshold: 1% 6 | patch: 7 | default: 8 | # We should raise this, but we want to evaluate how 9 | # this looks in practice, first. We can do that for now 10 | # by observing the status checks on the PRs themselves. 11 | target: 0% 12 | 13 | # The charts can still be viewed by clicking on the status 14 | # checks, but they create a fair amount of noise by default. 15 | comment: off 16 | 17 | -------------------------------------------------------------------------------- /codegen.yml: -------------------------------------------------------------------------------- 1 | schema: https://graphql.api.apollographql.com/api/graphql 2 | config: 3 | namingConvention: 4 | enumValues: keep 5 | generates: 6 | ./packages/server/src/plugin/schemaReporting/generated/operations.d.ts: 7 | documents: packages/server/src/plugin/schemaReporting/schemaReporter.ts 8 | plugins: 9 | - typescript 10 | - typescript-operations 11 | -------------------------------------------------------------------------------- /cspell-dict.txt: -------------------------------------------------------------------------------- 1 | ACAO 2 | afterware 3 | Afterware 4 | afterwares 5 | Afterwares 6 | apng 7 | apolloexample 8 | apollographql 9 | appenders 10 | asgi 11 | asynciterable 12 | autodeploys 13 | automerge 14 | Automerge 15 | automerges 16 | autopolling 17 | backoff 18 | backported 19 | barbaz 20 | beyoncé 21 | blahblah 22 | Blocklist 23 | bodyparser 24 | boomify 25 | bwvllq 26 | cacheability 27 | cacheable 28 | Cacheable 29 | Carettoni 30 | Changesets 31 | cimg 32 | circleci 33 | cleartext 34 | CNCF 35 | codecov 36 | codegen 37 | codepaths 38 | codesandbox 39 | concat 40 | contravariance 41 | contravariantly 42 | createhash 43 | culted 44 | dataloaders 45 | datasource 46 | datasources 47 | deduplicates 48 | deduplicating 49 | deduplication 50 | deps 51 | deserialization 52 | direnv 53 | Direnv 54 | docset 55 | docstrings 56 | downleveled 57 | Doyensec 58 | DRYRUN 59 | eastus 60 | embeddable 61 | Embeddable 62 | endregion 63 | engineproxy 64 | Engineproxy 65 | errored 66 | esque 67 | evenodd 68 | fakeable 69 | falsey 70 | fastify 71 | Fastify 72 | Fastify's 73 | Fastly 74 | fauxpaque 75 | Fauxpaque 76 | Firestore 77 | Fitzwilliam 78 | FIXM 79 | functionapp 80 | Fuzzer 81 | gcloud 82 | genericized 83 | goofql 84 | graphiql 85 | graphqlcodegenerator 86 | GraphQLJSON 87 | gzipped 88 | hackily 89 | hapi 90 | herokuapp 91 | Hofmann 92 | hrtime 93 | htmls 94 | httpcache 95 | iframes 96 | IHTTP 97 | importability 98 | instanceof 99 | iosapp 100 | isnodelike 101 | iteratees 102 | jsdelivr 103 | keyv 104 | keyvadapter 105 | keyvaluecache 106 | KHTML 107 | Kubernetes 108 | linearizability 109 | linearizable 110 | Loftis 111 | loglevel 112 | Luca 113 | MAXAGE 114 | memjs 115 | MERN 116 | mget 117 | Mget 118 | microrouter 119 | middlewares 120 | Middlewares 121 | millis 122 | mkdir 123 | mktemp 124 | monodocs 125 | mygraph 126 | myvariant 127 | namespacing 128 | nanos 129 | nodenext 130 | npmrc 131 | nsolid 132 | Nuxt 133 | oneof 134 | onwarn 135 | opde 136 | paque 137 | parseurl 138 | pbjs 139 | pbts 140 | pook 141 | Pook 142 | pooks 143 | postcompile 144 | precompile 145 | preflighted 146 | preflighting 147 | prepended 148 | prestart 149 | Procfile 150 | promisified 151 | proto 152 | protobuf 153 | Protobuf 154 | proxied 155 | Quickstart 156 | Relatedly 157 | retryable 158 | revalidates 159 | roadmap 160 | ROADMAP 161 | rollup 162 | runtimes 163 | safelist 164 | safelisted 165 | safelisting 166 | Safelisting 167 | Scheer 168 | SCRIPTNAME 169 | SIGINT 170 | SIGTERM 171 | sinonjs 172 | sint 173 | sortby 174 | SQLDB 175 | stringifiable 176 | stringification 177 | subchain 178 | subclassing 179 | subpackage 180 | subqueries 181 | sumby 182 | supergraph 183 | Supergraph 184 | supergraphs 185 | technotes 186 | testful 187 | testonly 188 | testsuite 189 | triaging 190 | tsbuildinfo 191 | tsconfig 192 | tsconfigs 193 | Turbopack 194 | typecheck 195 | typeis 196 | typenames 197 | typeof 198 | typesafe 199 | unawaited 200 | unbreaking 201 | uncacheable 202 | undersupported 203 | undici 204 | unexecutable 205 | uninstrumented 206 | unparsable 207 | Unprefixed 208 | unref 209 | unsubscriber 210 | Unsubscriber 211 | Unversioned 212 | Uppercasing 213 | urlencode 214 | usagereporting 215 | USERCONFIG 216 | uuidv 217 | vendia 218 | Wallclock 219 | websockets 220 | whatwg 221 | Wheelock's 222 | withrequired 223 | xorby 224 | YOURNAME 225 | -------------------------------------------------------------------------------- /cspell.yaml: -------------------------------------------------------------------------------- 1 | # Configuration for the cspell command-line tool and the Code Spell Checker 2 | # VSCode extension 3 | # (https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker). 4 | 5 | # Add a repo-specific dictionary. Any new real words can be added to 6 | # cspell-dict.txt, one per line. 7 | dictionaryDefinitions: 8 | - name: workspace 9 | path: './cspell-dict.txt' 10 | description: Custom Workspace Dictionary 11 | addWords: true 12 | scope: workspace 13 | dictionaries: 14 | - workspace 15 | 16 | # Ignore files that aren't check in to git as well as files that aren't written 17 | # by hand. Note that we do want to check, say, JSON files (as package.json 18 | # contains English text like package descriptions). 19 | useGitignore: true 20 | ignorePaths: 21 | - '**/generated/**' 22 | - 'packages/usage-reporting-protobuf/src/reports.proto' 23 | - '**/*.sketch' 24 | - '**/*.svg' 25 | - cspell.yaml 26 | 27 | ignoreRegExpList: 28 | # GitHub Security Advisories 29 | - GHSA-[-\w]+ 30 | 31 | overrides: 32 | # Ignore anything in a changelog file that looks like a GitHub username. 33 | - filename: '**/CHANGELOG*.md' 34 | ignoreRegExpList: 35 | - "@[-\\w]+" 36 | # Ignore the targets of links in Markdown/MDX files. 37 | - filename: '**/*.md*' 38 | ignoreRegExpList: 39 | - "\\]\\([^)]+\\)" 40 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | This is the documentation **source** for this repository. 4 | 5 | The **deployed** version of the documentation for this repository is available at: 6 | 7 | * https://www.apollographql.com/docs/apollo-server/ 8 | 9 | See the [docs site README](https://github.com/apollographql/docs) for local installation and development. 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/source/api/plugin/drain-http-server.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'API Reference: Drain HTTP Server Plugin' 3 | api_reference: true 4 | --- 5 | 6 | import TopLevelAwait from "../../shared/top-level-await.mdx" 7 | 8 | ## Using the plugin 9 | 10 | 11 | 12 | This article documents the options for the `ApolloServerPluginDrainHttpServer` plugin, which you can import from `@apollo/server/plugin/drainHttpServer`. 13 | 14 | This plugin is designed for use with `expressMiddleware` and other [framework integrations](../../integrations/integration-index) built on top of [Node `http.Server`s](https://nodejs.org/api/http.html#http_class_http_server). **We highly recommend** using this plugin to ensure your server shuts down gracefully. 15 | 16 | > You do not need to use this plugin with the `startStandaloneServer` function; it automatically handles server draining. 17 | 18 | When you use this plugin, Apollo Server will drain your HTTP server when you call the `stop()` method (which is also called for you when the `SIGTERM` and `SIGINT` signals are received, unless disabled with the [`stopOnTerminationSignals` constructor option](../apollo-server/#stoponterminationsignals)). 19 | 20 | Specifically, it will: 21 | 22 | - Stop listening for new connections 23 | - Close idle connections (i.e., connections with no current HTTP request) 24 | - Close active connections whenever they become idle 25 | - Wait for all connections to be closed 26 | - After a grace period, if any connections remain active, forcefully close them. 27 | 28 | This plugin is exported from the `@apollo/server` package. Here's a basic example of how to use it with Express: 29 | 30 | 31 | 32 | ```ts title="index.ts" 33 | import { ApolloServer } from '@apollo/server'; 34 | import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'; 35 | import { expressMiddleware } from '@as-integrations/express5'; 36 | import express from 'express'; 37 | import http from 'http'; 38 | import cors from 'cors'; 39 | import { typeDefs, resolvers } from './schema'; 40 | 41 | interface MyContext { 42 | token?: String; 43 | } 44 | 45 | const app = express(); 46 | // Our httpServer handles incoming requests to our Express app. 47 | // Below, we tell Apollo Server to "drain" this httpServer, 48 | // enabling our servers to shut down gracefully. 49 | const httpServer = http.createServer(app); 50 | 51 | const server = new ApolloServer({ 52 | typeDefs, 53 | resolvers, 54 | plugins: [ApolloServerPluginDrainHttpServer({ httpServer })], 55 | }); 56 | await server.start(); 57 | 58 | app.use( 59 | '/graphql', 60 | cors(), 61 | express.json(), 62 | expressMiddleware(server, { 63 | context: async ({ req }) => ({ token: req.headers.token }), 64 | }), 65 | ); 66 | 67 | await new Promise((resolve) => 68 | httpServer.listen({ port: 4000 }, resolve), 69 | ); 70 | 71 | console.log(`🚀 Server ready at http://localhost:4000/graphql`); 72 | ``` 73 | 74 | 75 | 76 | ## Options 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 96 | 101 | 102 | 103 | 104 | 111 | 116 | 117 | 118 | 119 |
Name /
Type
Description
90 | 91 | ###### `httpServer` 92 | 93 | [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server) 94 | 95 | 97 | 98 | The server to drain; required. 99 | 100 |
105 | 106 | ###### `stopGracePeriodMillis` 107 | 108 | `number` 109 | 110 | 112 | 113 | How long to wait before forcefully closing non-idle connections. Defaults to `10_000` (ten seconds). 114 | 115 |
120 | -------------------------------------------------------------------------------- /docs/source/builtin-plugins.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Built-In Plugins 3 | --- 4 | 5 | **Plugins** extend Apollo Server's functionality by performing custom operations in response to certain events. These events correspond to individual phases of the GraphQL request lifecycle, and to the lifecycle of Apollo Server itself. 6 | 7 | Certain Apollo Server features are provided as built-in plugins that are exported from within the `@apollo/server` package. Apollo Server installs certain plugins automatically, but you can also install them _manually_ to override their default settings. See each plugin's documentation for details. 8 | 9 | You can also [create custom plugins](./integrations/plugins/). 10 | 11 | ## List of built-in plugins 12 | 13 | | Name | Description | Location | 14 | |------|---------|-------------| 15 | | [Usage reporting](./api/plugin/usage-reporting/) | Gathers helpful operation usage data and reports it to [GraphOS](/graphos/) for visualization, alerting, and more. |`@apollo/server/plugin/usageReporting` | 16 | | [Schema reporting](./api/plugin/schema-reporting/) | Automatically reports the server's schema to [GraphOS](/graphos/) on startup to enable schema history and up-to-date metrics. | `@apollo/server/plugin/schemaReporting` | 17 | | [Inline trace](./api/plugin/inline-trace/) | Used primarily by [federated subgraphs](https://www.apollographql.com/docs/federation/) to include operation trace data in responses to the gateway. | `@apollo/server/plugin/inlineTrace` | 18 | | [Cache control](./api/plugin/cache-control/) | Calculates caching behavior for operation responses. | `@apollo/server/plugin/cacheControl` | 19 | | [Landing page (multiple)](./api/plugin/landing-pages) | Handle displaying a default or custom landing page at Apollo Server's base URL. | `@apollo/server/plugin/landingPage/default` | 20 | | [Draining an HTTP server](./api/plugin/drain-http-server) | Used to ensure your Node.js servers gracefully shut down. | `@apollo/server/plugin/drainHttpServer`| 21 | | [Enable federated subscriptions](./api/plugin/subscription-callback) | Enables your server to handle federated subscription requests from Apollo Router via the callback protocol. | `@apollo/server/plugin/subscriptionCallback`| 22 | 23 | ## Installing plugins 24 | 25 | You can install a plugin that isn't installed by default (or customize a default plugin) by providing a `plugins` configuration option to the ApolloServer constructor, like so: 26 | 27 | 28 | 29 | ```ts 30 | import { ApolloServer } from "@apollo/server"; 31 | import { ApolloServerPluginUsageReporting } from '@apollo/server/plugin/usageReporting'; 32 | 33 | const server = new ApolloServer({ 34 | typeDefs, 35 | resolvers, 36 | plugins: [ 37 | // Sets a non-default option on the usage reporting plugin 38 | ApolloServerPluginUsageReporting({ 39 | sendVariableValues: { all: true }, 40 | }), 41 | ], 42 | }); 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/source/images/as-landing-page-production.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/as-landing-page-production.jpg -------------------------------------------------------------------------------- /docs/source/images/default-sandbox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/default-sandbox.jpg -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/add-integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/add-integration.png -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/automatic-deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/automatic-deployment.png -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/config-vars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/config-vars.jpg -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/create-new-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/create-new-app.png -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/heroku-github-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/heroku-github-instructions.png -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/new-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/new-app.png -------------------------------------------------------------------------------- /docs/source/images/deployment/heroku/set-app-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/deployment/heroku/set-app-name.png -------------------------------------------------------------------------------- /docs/source/images/introduction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/introduction.jpg -------------------------------------------------------------------------------- /docs/source/images/playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/playground.png -------------------------------------------------------------------------------- /docs/source/images/sandbox-mern-stack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/sandbox-mern-stack.jpg -------------------------------------------------------------------------------- /docs/source/images/sandbox-response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/sandbox-response.png -------------------------------------------------------------------------------- /docs/source/images/sandbox.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apollographql/apollo-server/267e8eb49903d526e15b1a8ba03fea6f928c896c/docs/source/images/sandbox.jpeg -------------------------------------------------------------------------------- /docs/source/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction to Apollo Server 3 | subtitle: Learn how to build scalable, production-ready GraphQL APIs 4 | description: Learn how Apollo Server simplifies building GraphQL APIs with its straightforward setup and support for any data source or client. 5 | --- 6 | 7 | > 📣 **Apollo Server 4 is generally available!** 8 | > 9 | > [See what's new](/apollo-server/migration/) or check out the [tutorial for migrating from Apollo Server 3](https://www.apollographql.com/tutorials/side-quest-as4?referrer=docs-content). 10 | > 11 | > Docs for Apollo Server 3 are [available here](/apollo-server/v3/). 12 | 13 | **Apollo Server is an [open-source](https://github.com/apollographql/apollo-server), spec-compliant GraphQL server** that's compatible with any GraphQL client, including [Apollo Client](/react). It's the best way to build a production-ready, self-documenting GraphQL API that can use data from any source. 14 | 15 | Diagram showing Apollo Server bridging GraphQL Operations to web apps and frameworks 16 | 17 | #### You can use Apollo Server as: 18 | 19 | * The GraphQL server for a [subgraph](/apollo-server/using-federation/apollo-subgraph-setup) in a federated supergraph 20 | * An add-on to any new or existing Node.js apps—this includes apps running on [Express](/apollo-server/api/express-middleware) (including [MERN stack](/apollo-server/integrations/mern) apps), [AWS Lambda](https://www.npmjs.com/package/@as-integrations/aws-lambda), [Azure Functions](https://www.npmjs.com/package/@as-integrations/azure-functions), [Cloudflare](https://www.npmjs.com/package/@as-integrations/cloudflare-workers), [Fastify](https://www.npmjs.com/package/@as-integrations/fastify), and [more](/apollo-server/integrations/integration-index) 21 | 22 | #### Apollo Server provides: 23 | 24 | * **Straightforward setup**, so your client developers can start fetching data quickly 25 | * **Incremental adoption**, enabling you to add features as they're needed 26 | * **Universal compatibility** with any data source, any build tool, and any GraphQL client 27 | * **Production readiness**, enabling you to confidently run your graph in production 28 | 29 | #### Ready to try it out? 30 | 31 | 32 | Get started! 33 | 34 | -------------------------------------------------------------------------------- /docs/source/integrations/integration-index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Apollo Server Integrations 3 | --- 4 | 5 | import IntegrationTable from "../shared/integration-table.mdx" 6 | 7 | > Are you looking to build a new integration? Or help maintain an existing integration? See [Building Web Framework Integrations for Apollo Server](./building-integrations) for step-by-step guidance! 8 | 9 | Apollo Server 4's [`startStandaloneServer`](../api/standalone) function spins up a basic web server with sensible defaults. The server is a fully functional GraphQL server supporting all of Apollo Server's GraphQL-level customizations, but it offers minimal opportunities for HTTP-level configuration. 10 | 11 | If you need more control over how your GraphQL server speaks HTTP, you should instead use an _integration_. Integrations are packages which connect the Apollo Server API to your favorite web framework. 12 | 13 | Apollo maintains an [integration](../api/express-middleware) between Apollo Server and [Express](https://expressjs.com/), the most popular Node.js web framework. The integration with Express v4 is published as [`@as-integrations/express4`](https://www.npmjs.com/package/@as-integrations/express), and the integration with Express v5 is published as [`@as-integrations/express5`](https://www.npmjs.com/package/@as-integrations/express5). Both packages export the function [`expressMiddleware`](../api/express-middleware). 14 | 15 | > The Express v4 integration is also included in the main `@apollo/server` package, exported from `@apollo/server/express4`. Its behavior is identical to the `@as-integrations/express4`. Express v5 is only supported by the external package. (A future major version of Apollo Server will remove `@apollo/server/express4`.) 16 | 17 | > Have you built, or are you maintaining, an Apollo Server integration that isn't listed here? Please [submit a PR](https://github.com/apollographql/apollo-server/blob/main/docs/source/integrations/integration-index.mdx) to be added to this list! 18 | 19 | The larger community maintains the following open-source integrations for Apollo Server: 20 | 21 | 22 | 23 | > Apollo does not provide official support for the above community-maintained libraries. We cannot guarantee that community-maintained libraries adhere to best practices or that they will continue to be maintained. 24 | 25 | For those _building_ a new integration library, we'd like to welcome you (and your repository!) to the [`apollo-server-integrations`](https://github.com/apollo-server-integrations) Github organization alongside other community-maintained Apollo Server integrations. If you participate in our organization, you'll have the option to publish under our community's NPM scope `@as-integrations`, ensuring your integration is discoverable. 26 | -------------------------------------------------------------------------------- /docs/source/monitoring/health-checks.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Health Checks 3 | description: Determining the health status of Apollo Server 4 | --- 5 | 6 | > **Apollo Server 4 no longer [supports built-in health checks](../migration/#health-checks)**. Instead, we recommend performing [GraphQL-level health checks](#graphql-level-health-checks) to ensure your server successfully serves traffic _and_ performs GraphQL operations. 7 | 8 | Load balancers often use health checks to determine if a server is available and ready to serve traffic. 9 | 10 | ## GraphQL-level health checks 11 | 12 | The easiest way to determine if your GraphQL server is healthy is to run a GraphQL operation. 13 | 14 | Every GraphQL server supports a trivial query that requests the [`__typename`](../schema/schema/#the-__typename-field) of the top-level `Query` type. This means every GraphQL server can respond to a `GET` request to a URL such as: 15 | 16 | ``` 17 | https://your.server/graphql?query=%7B__typename%7D 18 | ``` 19 | 20 | Note that this health check will run an actual GraphQL operation. If your server requires special headers or cookies to run any query, you'll need to provide those with your request. 21 | 22 | > Sending an `apollo-require-preflight: true` header alongside your health check ensures that Apollo Server's [CSRF prevention](../security/cors/#preventing-cross-site-request-forgery-csrf) feature won't block it. 23 | 24 | If you want to create a health check for your HTTP server that is _unrelated_ to the health of the GraphQL execution engine (i.e., such as [Apollo Server 3's health check feature](/apollo-server/v3/monitoring/health-checks)), you can add a `GET` handler that always succeeds to your web framework. 25 | 26 | Below is an example of an HTTP server health check with [`expressMiddleware`](../api/express-middleware/): 27 | 28 | 29 | 30 | ```ts 31 | // imports, etc. 32 | 33 | const app = express(); 34 | const server = new ApolloServer({ 35 | typeDefs, 36 | resolvers 37 | }); 38 | 39 | await server.start(); 40 | app.use('/graphql', 41 | cors(), 42 | express.json(), 43 | expressMiddleware(server) 44 | ); 45 | await new Promise(resolve => app.listen({ port: 4000 }, resolve)); 46 | 47 | // Our GraphQL server is listening for GraphQL operations 48 | // on `http://localhost:4000/graphql` 49 | console.log(`🚀 Server ready at http://localhost:4000/graphql`); 50 | 51 | // Requests to `http://localhost:4000/health` now return "Okay!" 52 | app.get('/health', (req, res) => { 53 | res.status(200).send('Okay!'); 54 | }); 55 | ``` 56 | 57 | 58 | 59 | > If you are using `startStandaloneServer`, you must first [swap to using the `expressMiddleware` function](../api/standalone/#swapping-to-expressmiddleware) before creating an HTTP server health check. 60 | -------------------------------------------------------------------------------- /docs/source/previous-versions.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Previous Versions of Apollo Server 3 | --- 4 | 5 | ## Apollo Server 4 is generally available 6 | 7 | Apollo Server 4 is the latest version of Apollo Server and is [generally available](/graphos/reference/feature-launch-stages#general-availability). Apollo Server 4 is ready for use in a production environment, and Apollo provides official support for this library. There is currently no planned end-of-life date. 8 | 9 | ## Deprecated versions 10 | 11 | Deprecated versions continue to receive security patches and updates to address major regressions until their end-of-life date. They typically do not receive new features and other kinds of bug fixes may or may not be backported to deprecated versions at Apollo's discretion. 12 | 13 | There are currently no deprecated versions of Apollo Server. 14 | 15 | > [Learn more about deprecation and end-of-life.](/graphos/reference/feature-launch-stages#apollo-feature-retirement-stages) 16 | 17 | ## End-of-life versions 18 | 19 | Apollo no longer commits to providing any support for these versions. While you may still file issues about security concerns or significant regressions, Apollo may choose not to address them. 20 | 21 | End-of-life versions will remain available in the npm registry and can still be installed and used in your projects. However, Apollo doesn't guarantee any further support for them, nor does Apollo recommend their use. Additionally, Apollo doesn't guarantee that GraphOS features will continue to work for packages beyond their end-of-life date. 22 | 23 | > [Learn more about deprecation and end-of-life.](/graphos/reference/feature-launch-stages#apollo-feature-retirement-stages) 24 | 25 | ### Apollo Server 3 26 | 27 | [Apollo Server 3](/apollo-server/v3/) is end-of-life as of **October 22, 2024**. We encourage all Apollo Server 3 users to [**upgrade** to Apollo Server 4 now](./migration) as _soon as possible_. 28 | 29 | Note that Apollo Server 2 and 3 were distributed in various npm packages (such as `apollo-server`, `apollo-server-core`, and `apollo-server-express`); Apollo Server 4 combines these packages into a single new [`@apollo/server` package](./migration/#the-new-apolloserver-package). 30 | 31 | ### Apollo Server 2 32 | 33 | [Apollo Server 2](/apollo-server/v2/) is end-of-life as of **October 22, 2023**. We encourage all users of Apollo Server 2 to **upgrade** to Apollo Server 4 as _soon as possible_, first by following the [v3 migration guide](/apollo-server/v3/migration) and then following the [v4 migration guide](./migration). 34 | 35 | Note that Apollo Server 2 and 3 were distributed in various npm packages (such as `apollo-server`, `apollo-server-core`, and `apollo-server-express`); Apollo Server 4 combines these packages into a single new [`@apollo/server` package](./migration/#the-new-apolloserver-package). 36 | 37 | Depending on which Apollo Server features you use, the upgrade process might require several changes to your server. The most straightforward upgrade path is to first upgrade from Apollo Server 2 to 3, then once everything works, continue upgrading from Apollo Server 3 to 4. 38 | 39 | ### Apollo Server 1 40 | 41 | Apollo Server 1 was a significantly different project and has been considered end-of-life since 2018. 42 | -------------------------------------------------------------------------------- /docs/source/security/terminating-ssl.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Terminating SSL 3 | --- 4 | 5 | import TopLevelAwait from "../shared/top-level-await.mdx" 6 | 7 | 8 | 9 | Most production environments use a load balancer or HTTP proxy (such as nginx) to perform SSL termination on behalf of web applications in that environment. 10 | 11 | If you're using Apollo Server in an application that must perform its _own_ SSL termination, you can use the `https` module with the [`expressMiddleware` function](../api/express-middleware). 12 | 13 | Here's an example that uses HTTPS in production and HTTP in development: 14 | 15 | 16 | 17 | ```ts title="index.ts" 18 | import { ApolloServer } from '@apollo/server'; 19 | import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'; 20 | import { expressMiddleware } from '@as-integrations/express5'; 21 | import typeDefs from './graphql/schema'; 22 | import resolvers from './graphql/resolvers'; 23 | import cors from 'cors'; 24 | import express from 'express'; 25 | import http from 'http'; 26 | import https from 'https'; 27 | import fs from 'fs'; 28 | 29 | const configurations = { 30 | // Note: You may need sudo to run on port 443 31 | production: { ssl: true, port: 443, hostname: 'example.com' }, 32 | development: { ssl: false, port: 4000, hostname: 'localhost' }, 33 | }; 34 | 35 | const environment = process.env.NODE_ENV || 'production'; 36 | const config = configurations[environment]; 37 | 38 | const server = new ApolloServer({ 39 | typeDefs, 40 | resolvers, 41 | }); 42 | await server.start(); 43 | 44 | const app = express(); 45 | // our express server is mounted at /graphql 46 | app.use( 47 | '/graphql', 48 | cors(), 49 | express.json(), 50 | expressMiddleware(server), 51 | ); 52 | 53 | // Create the HTTPS or HTTP server, per configuration 54 | let httpServer; 55 | if (config.ssl) { 56 | // Assumes certificates are in a .ssl folder off of the package root. 57 | // Make sure these files are secured. 58 | httpServer = https.createServer( 59 | { 60 | key: fs.readFileSync(`./ssl/${environment}/server.key`), 61 | cert: fs.readFileSync(`./ssl/${environment}/server.crt`), 62 | }, 63 | 64 | app, 65 | ); 66 | } else { 67 | httpServer = http.createServer(app); 68 | } 69 | 70 | await new Promise((resolve) => httpServer.listen({ port: config.port }, resolve)); 71 | 72 | console.log('🚀 Server ready at', `http${config.ssl ? 's' : ''}://${config.hostname}:${config.port}/graphql`); 73 | ``` 74 | 75 | 76 | -------------------------------------------------------------------------------- /docs/source/shared/diagrams/federation-architecture.mdx: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | graph BT; 3 | webapp(Web app); 4 | iosapp(iOS app); 5 | subgraph " "; 6 | router([Graph router]); 7 | serviceA[Users
subgraph]; 8 | serviceB[Products
subgraph]; 9 | serviceC[Reviews
subgraph]; 10 | end; 11 | webapp & iosapp -.- router; 12 | router --- serviceA & serviceB & serviceC; 13 | class webapp,iosapp secondary; 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/source/shared/integration-table.mdx: -------------------------------------------------------------------------------- 1 | | Web Framework | Integration Package | 2 | |--------|-------------| 3 | | [AWS Lambda](https://aws.amazon.com/lambda/) | [`@as-integrations/aws-lambda`](https://www.npmjs.com/package/@as-integrations/aws-lambda) | 4 | | [Azure Functions](https://azure.microsoft.com/en-us/services/functions/) | [`@as-integrations/azure-functions`](https://www.npmjs.com/package/@as-integrations/azure-functions) | 5 | | [Cloudflare Workers](https://workers.cloudflare.com/) | [`@as-integrations/cloudflare-workers`](https://www.npmjs.com/package/@as-integrations/cloudflare-workers) | 6 | | [Fastify](https://fastify.io/) | [`@as-integrations/fastify`](https://www.npmjs.com/package/@as-integrations/fastify) | 7 | | [Hapi](https://hapi.dev/) | [`@as-integrations/hapi`](https://www.npmjs.com/package/@as-integrations/hapi) | 8 | | [Koa](https://koajs.com/) | [`@as-integrations/koa`](https://www.npmjs.com/package/@as-integrations/koa) | 9 | | [Next.js](https://nextjs.org) | [`@as-integrations/next`](https://www.npmjs.com/package/@as-integrations/next) | 10 | | [Nuxt](https://v3.nuxtjs.org/) / [h3](https://github.com/unjs/h3) | [`@as-integrations/h3`](https://www.npmjs.com/package/@as-integrations/h3) | 11 | -------------------------------------------------------------------------------- /docs/source/shared/top-level-await.mdx: -------------------------------------------------------------------------------- 1 | > In the examples below, we use top-level [`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await) calls to start our server asynchronously. Check out our [Getting Started](/apollo-server/getting-started#step-2-install-dependencies) guide to see how we configured our project to support this. 2 | -------------------------------------------------------------------------------- /jest.config.base.js: -------------------------------------------------------------------------------- 1 | import { defaults } from 'jest-config'; 2 | import { createRequire } from 'node:module'; 3 | 4 | export default { 5 | testEnvironment: 'node', 6 | setupFilesAfterEnv: ['/../../jest.setup.js'], 7 | preset: 'ts-jest', 8 | testMatch: null, 9 | testRegex: '/__tests__/.*\\.test\\.(js|ts)$', 10 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 11 | moduleFileExtensions: [...defaults.moduleFileExtensions, 'ts', 'tsx'], 12 | clearMocks: true, 13 | transform: { 14 | '^.+\\.test.ts$': [ 15 | 'ts-jest', 16 | { 17 | tsconfig: '/src/__tests__/tsconfig.json', 18 | diagnostics: true, 19 | }, 20 | ], 21 | }, 22 | moduleNameMapper: { 23 | // Ignore '.js' at the end of imports; part of ESM support. 24 | '^(\\.{1,2}/.*)\\.js$': '$1', 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | // It's awkward to read `npm test` output if it is littered with console logs. 2 | // This (from https://github.com/facebook/jest/issues/6121) makes the test fail 3 | // if it writes anything to console. (Feel free to set $ALLOW_CONSOLE if you are 4 | // logging while developing and want to see if your tests pass.) 5 | // 6 | // Typically you can turn off the info/debug in tests by passing a loglevel 7 | // logger with level WARN to the logger option to `new ApolloServer`. 8 | if (!process.env.ALLOW_CONSOLE) { 9 | let usedConsole = false; 10 | ['log', 'error', 'warn', 'info', 'debug'].forEach((key) => { 11 | const originalFn = console[key]; 12 | console[key] = (...args) => { 13 | usedConsole = true; 14 | originalFn(...args); 15 | }; 16 | }); 17 | 18 | afterEach(() => { 19 | if (usedConsole) { 20 | usedConsole = false; 21 | throw Error( 22 | 'To keep unit test output readable, tests should not write to the console. To test logging behavior, pass a logger to the class under test.', 23 | ); 24 | } 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /packages/cache-control-types/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !src/**/* 3 | !dist/**/* 4 | dist/**/*.test.* 5 | !package.json 6 | !README.md 7 | !LICENSE -------------------------------------------------------------------------------- /packages/cache-control-types/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @apollo/cache-control-types 2 | 3 | ## 1.0.3 4 | 5 | ### Patch Changes 6 | 7 | - [#7614](https://github.com/apollographql/apollo-server/pull/7614) [`4fadf3ddc`](https://github.com/apollographql/apollo-server/commit/4fadf3ddc9611e050dd0f08d51252ed9b0c0d9e1) Thanks [@Cellule](https://github.com/Cellule)! - Publish TypeScript typings for CommonJS modules output. 8 | 9 | This allows TypeScript projects that use CommonJS modules with 10 | `moduleResolution: "node16"` or 11 | `moduleResolution: "nodeNext"` 12 | to correctly resolves the typings of apollo's packages as CommonJS instead of ESM. 13 | 14 | ## 1.0.2 15 | 16 | ### Patch Changes 17 | 18 | - [#173](https://github.com/apollographql/apollo-utils/pull/173) [`b231e5d`](https://github.com/apollographql/apollo-utils/commit/b231e5d57d4598661f22cb7338ecd2fff0222b54) Thanks [@glasser](https://github.com/glasser)! - Fix build when combined with the old `declare module` 19 | 20 | ## 1.0.1 21 | 22 | ### Patch Changes 23 | 24 | - [#171](https://github.com/apollographql/apollo-utils/pull/171) [`e8d3a72`](https://github.com/apollographql/apollo-utils/commit/e8d3a72834b80930478d21e9bf1fa50d039c127a) Thanks [@glasser](https://github.com/glasser)! - Add missing "main" to package.json 25 | 26 | ## 1.0.0 27 | 28 | ### Major Changes 29 | 30 | - [#168](https://github.com/apollographql/apollo-utils/pull/168) [`9cc9b9a`](https://github.com/apollographql/apollo-utils/commit/9cc9b9a4ea9618907abdb485d0780f4444f959de) Thanks [@glasser](https://github.com/glasser)! - New package, extracted from Apollo Server 4 alpha 31 | -------------------------------------------------------------------------------- /packages/cache-control-types/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/cache-control-types/README.md: -------------------------------------------------------------------------------- 1 | # Cache Control types 2 | 3 | This package exports various TypeScript types related to Apollo Server's cache 4 | policy calculation. 5 | 6 | Specifically, it gives a type-safe way to get the `info.cacheControl` field in resolvers. Either declare your resolver's `info` argument to be of type `GraphQLResolveInfoWithCacheControl` (perhaps with the graphql-code-generator typescript-resolvers customResolveInfo option), or use the `maybeCacheControlFromInfo` or `cacheControlFromInfo` functions to extract `info.cacheControl` in a type-safe way. 7 | -------------------------------------------------------------------------------- /packages/cache-control-types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/cache-control-types", 3 | "version": "1.0.3", 4 | "description": "TypeScript types for Apollo Server info.cacheControl", 5 | "type": "module", 6 | "main": "dist/cjs/index.js", 7 | "module": "dist/esm/index.js", 8 | "types": "dist/esm/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": { 12 | "require": "./dist/cjs/index.d.ts", 13 | "default": "./dist/esm/index.d.ts" 14 | }, 15 | "import": "./dist/esm/index.js", 16 | "require": "./dist/cjs/index.js" 17 | } 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/apollographql/apollo-server.git", 22 | "directory": "packages/cache-control-types/" 23 | }, 24 | "keywords": [ 25 | "apollo", 26 | "graphql", 27 | "typescript", 28 | "node" 29 | ], 30 | "author": "Apollo ", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/apollographql/apollo-server/issues" 34 | }, 35 | "homepage": "https://github.com/apollographql/apollo-server#readme", 36 | "peerDependencies": { 37 | "graphql": "14.x || 15.x || 16.x" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/cache-control-types/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ".", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "./dist/cjs" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/cache-control-types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist/esm" 6 | }, 7 | "include": ["src/**/*"], 8 | "exclude": ["**/__tests__"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/gateway-interface/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !src/**/* 3 | !dist/**/* 4 | dist/**/*.test.* 5 | !package.json 6 | !README.md 7 | !LICENSE -------------------------------------------------------------------------------- /packages/gateway-interface/README.md: -------------------------------------------------------------------------------- 1 | # Apollo Server/Gateway interface 2 | 3 | This package defines TypeScript types for the interface between Apollo Server and Apollo Gateway. It contains no runtime code. 4 | 5 | The types in this package describe the API as of Gateway 0.35.0 (ie, with onSchemaLoadOrUpdate). It is extracted from the Apollo Server 3 `apollo-server-types` package. Most of the type names have been changed to start with `Gateway`, so that they coexist better with similarly-named types. (Because TypeScript is generally structurally typed, this is OK.) 6 | 7 | Note that the cache scope field (eg, on `requestContext.overallCachePolicy.scope`) is defined as `any` in this package. That's because in AS3 this type is an enum, and enums in TypeScript are _not_ structurally typed. So we can't actually create an object of this type without depending on AS3 (or updating AS3 to get its definition from somewhere shared). 8 | 9 | We have updated `@apollo/gateway` (v0 and v2) to define its types from this package rather than `apollo-server-types`. This allows Gateway to be compatible with both AS3 and AS4 (and even AS2, for Gateway 0.x) without needing to pull either package's code into the TypeScript build. 10 | 11 | Apollo Server 4 directly depends on this package and uses its types to construct its calls to the Gateway. 12 | -------------------------------------------------------------------------------- /packages/gateway-interface/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server-gateway-interface", 3 | "version": "1.1.1", 4 | "description": "Interface used to connect Apollo Gateway to Apollo Server", 5 | "type": "module", 6 | "main": "", 7 | "types": "dist/esm/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "types": { 11 | "require": "./dist/cjs/index.d.ts", 12 | "default": "./dist/esm/index.d.ts" 13 | } 14 | } 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/apollographql/apollo-server", 19 | "directory": "packages/gateway-interface" 20 | }, 21 | "keywords": [], 22 | "author": "Apollo ", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/apollographql/apollo-server/issues" 26 | }, 27 | "homepage": "https://github.com/apollographql/apollo-server#readme", 28 | "dependencies": { 29 | "@apollo/utils.fetcher": "^2.0.0", 30 | "@apollo/utils.logger": "^2.0.0", 31 | "@apollo/utils.keyvaluecache": "^2.1.0", 32 | "@apollo/usage-reporting-protobuf": "^4.1.1" 33 | }, 34 | "peerDependencies": { 35 | "graphql": "14.x || 15.x || 16.x" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/gateway-interface/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ".", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "./dist/cjs" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/gateway-interface/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist/esm" 6 | }, 7 | "include": ["src/**/*"], 8 | "exclude": ["**/__tests__"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/integration-testsuite/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !src/**/* 3 | !dist/**/* 4 | !package.json 5 | !README.md 6 | -------------------------------------------------------------------------------- /packages/integration-testsuite/README.md: -------------------------------------------------------------------------------- 1 | # Apollo Server Integration Testsuite 2 | 3 | This package serves as a set of Jest tests for Apollo Server integration 4 | authors. Any Node package which functions as the HTTP (or HTTP framework) 5 | binding and Apollo Server can run these tests to ensure parity with the 1st 6 | party Express integration. 7 | 8 | > Note: this package is only intended for integration _authors_. If your project 9 | > _runs_ an Apollo Server instance, you probably shouldn't use this. 10 | 11 | The version of this package will be published in lockstep with Apollo Server, so 12 | choose the same version of this package as the version of Apollo Server which 13 | you intend to support. The expected configuration for an integration should 14 | follow the pattern: 15 | 16 | ```json 17 | { 18 | "name": "my-server-integration", 19 | "devDependencies": { 20 | "@apollo/server": "4.1.0", 21 | "@apollo/server-integration-testsuite": "4.1.0" 22 | }, 23 | "peerDependencies": { 24 | "@apollo/server": "^4.0.0" 25 | } 26 | } 27 | ``` 28 | 29 | In the example above, the `peerDependencies` allow your configuration to be used 30 | with the full range of Apollo Server v4 packages. The `devDependencies` which 31 | your integration is built and tested against should stay up-to-date with the 32 | latest version of Apollo Server, and the server and testsuite packages should be 33 | in lockstep with each other. 34 | 35 | This package imposes dependency requirements on your project, however it should 36 | only require they be installed as `devDependencies`: 37 | * `@apollo/server`'s version must match the version of the test suite. 38 | * The test suite expects you to be running `jest@28`. It's possible that other 39 | versions of Jest may be compatible, but this use case is unsupported and might 40 | lead to unexpected behavior. It's fine for your project to use a testing 41 | framework other than Jest, but you'll still need to configure Jest in your 42 | project in order to run the test suite (so you'll have two test runners 43 | configured in your project). Because of this, we recommend using only Jest in 44 | your project for simplicity. 45 | * `graphql` must be installed in your project in `peerDependencies` and your 46 | version range should match that of `@apollo/server`. The test suite package's 47 | `graphql` dependency will match that of Apollo Server's. 48 | -------------------------------------------------------------------------------- /packages/integration-testsuite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server-integration-testsuite", 3 | "version": "4.12.1", 4 | "description": "Test suite for Apollo Server integrations", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/apollographql/apollo-server", 10 | "directory": "packages/integration-testsuite" 11 | }, 12 | "keywords": [ 13 | "GraphQL", 14 | "Apollo", 15 | "Server", 16 | "Javascript", 17 | "Jest" 18 | ], 19 | "author": "Apollo ", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/apollographql/apollo-server/issues" 23 | }, 24 | "homepage": "https://github.com/apollographql/apollo-server#readme", 25 | "engines": { 26 | "node": ">=14.16.0" 27 | }, 28 | "dependencies": { 29 | "@apollo/cache-control-types": "^1.0.3", 30 | "@apollo/client": "^3.6.9", 31 | "@apollo/server": "4.12.1", 32 | "@apollo/usage-reporting-protobuf": "^4.1.1", 33 | "@apollo/utils.createhash": "^2.0.2", 34 | "@apollo/utils.keyvaluecache": "^2.1.0", 35 | "express": "^4.21.1", 36 | "graphql-http": "1.22.4", 37 | "graphql-tag": "^2.12.6", 38 | "loglevel": "^1.8.0", 39 | "node-fetch": "^2.6.7", 40 | "superagent": "^10.0.0", 41 | "supertest": "^7.0.0" 42 | }, 43 | "peerDependencies": { 44 | "@jest/globals": "28.x || 29.x", 45 | "graphql": "^16.6.0", 46 | "jest": "28.x || 29.x" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/integration-testsuite/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ApolloServer, 3 | ApolloServerOptions, 4 | BaseContext, 5 | ContextThunk, 6 | } from '@apollo/server'; 7 | import { describe } from '@jest/globals'; 8 | import { defineIntegrationTestSuiteApolloServerTests } from './apolloServerTests.js'; 9 | import { defineIntegrationTestSuiteHttpServerTests } from './httpServerTests.js'; 10 | import { defineIntegrationTestSuiteHttpSpecTests } from './httpSpecTests.js'; 11 | 12 | export interface CreateServerForIntegrationTestsResult { 13 | server: ApolloServer; 14 | url: string; 15 | extraCleanup?: () => Promise; 16 | } 17 | 18 | export interface CreateServerForIntegrationTestsOptions { 19 | context?: ContextThunk; 20 | } 21 | 22 | export type CreateServerForIntegrationTests = ( 23 | config: ApolloServerOptions, 24 | options?: CreateServerForIntegrationTestsOptions, 25 | ) => Promise; 26 | 27 | export function defineIntegrationTestSuite( 28 | createServer: CreateServerForIntegrationTests, 29 | options: { 30 | serverIsStartedInBackground?: boolean; 31 | noIncrementalDelivery?: boolean; 32 | } = {}, 33 | ) { 34 | describe('integration tests', () => { 35 | defineIntegrationTestSuiteApolloServerTests(createServer, options); 36 | defineIntegrationTestSuiteHttpServerTests(createServer, options); 37 | defineIntegrationTestSuiteHttpSpecTests(createServer); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /packages/integration-testsuite/src/resolvable.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Joseph Gentle 2 | 3 | // Permission to use, copy, modify, and / or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | // FITNESS.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | // PERFORMANCE OF THIS SOFTWARE. 14 | 15 | export type Resolvable = Promise & { 16 | resolve: (t: T) => void; 17 | reject: (e: any) => void; 18 | }; 19 | 20 | export default (): Resolvable => { 21 | let resolve: (val: T) => void; 22 | let reject: (err: any) => void; 23 | const promise = new Promise((_resolve, _reject) => { 24 | resolve = _resolve; 25 | reject = _reject; 26 | }) as Resolvable; 27 | promise.resolve = resolve!; 28 | promise.reject = reject!; 29 | return promise; 30 | }; 31 | -------------------------------------------------------------------------------- /packages/integration-testsuite/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "rootDir": "./src", 8 | "outDir": "./dist", 9 | // DOM types needed for @apollo/client 10 | // Ref: https://github.com/apollographql/apollo-client/issues/6376 11 | "lib": ["es2020", "dom"] 12 | }, 13 | "include": ["src/**/*"], 14 | "references": [ 15 | { "path": "../cache-control-types"}, 16 | { "path": "../server" }, 17 | ], 18 | } 19 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @apollo/server-plugin-response-cache 2 | 3 | ## 4.1.4 4 | 5 | ### Patch Changes 6 | 7 | - [#8010](https://github.com/apollographql/apollo-server/pull/8010) [`f4228e8`](https://github.com/apollographql/apollo-server/commit/f4228e88509b4cd2f50cf10bc6376d48488e03c1) Thanks [@glasser](https://github.com/glasser)! - Compatibility with Next.js Turbopack. Fixes #8004. 8 | 9 | ## 4.1.3 10 | 11 | ### Patch Changes 12 | 13 | - [#7614](https://github.com/apollographql/apollo-server/pull/7614) [`4fadf3ddc`](https://github.com/apollographql/apollo-server/commit/4fadf3ddc9611e050dd0f08d51252ed9b0c0d9e1) Thanks [@Cellule](https://github.com/Cellule)! - Publish TypeScript typings for CommonJS modules output. 14 | 15 | This allows TypeScript projects that use CommonJS modules with 16 | `moduleResolution: "node16"` or 17 | `moduleResolution: "nodeNext"` 18 | to correctly resolves the typings of apollo's packages as CommonJS instead of ESM. 19 | 20 | ## 4.1.2 21 | 22 | ### Patch Changes 23 | 24 | - [#7454](https://github.com/apollographql/apollo-server/pull/7454) [`f6e3ae021`](https://github.com/apollographql/apollo-server/commit/f6e3ae021417c3b54200f8d3fcf4366dc3518998) Thanks [@trevor-scheer](https://github.com/trevor-scheer)! - Start building packages with TS 5.x, which should have no effect for users 25 | 26 | ## 4.1.1 27 | 28 | ### Patch Changes 29 | 30 | - [#7439](https://github.com/apollographql/apollo-server/pull/7439) [`4668f4594`](https://github.com/apollographql/apollo-server/commit/4668f4594d2a3775a3b52fae4e896ac8c607792a) Thanks [@Igloczek](https://github.com/Igloczek)! - Export types from response cache plugin 31 | 32 | ## 4.1.0 33 | 34 | ### Minor Changes 35 | 36 | - [#7241](https://github.com/apollographql/apollo-server/pull/7241) [`d7e9b9759`](https://github.com/apollographql/apollo-server/commit/d7e9b97595b063f1e796ec4449850a16d19e8b18) Thanks [@glasser](https://github.com/glasser)! - If the cache you provide to the `cache` option is created with `PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation` (new in `@apollo/utils.keyvaluecache@2.1.0`), the `fqc:` prefix will not be added to cache keys. 37 | 38 | ## 4.0.3 39 | 40 | ### Patch Changes 41 | 42 | - [#7187](https://github.com/apollographql/apollo-server/pull/7187) [`3fd7b5f26`](https://github.com/apollographql/apollo-server/commit/3fd7b5f26144a02e711037b7058a8471e9648bc8) Thanks [@trevor-scheer](https://github.com/trevor-scheer)! - Update `@apollo/utils.keyvaluecache` dependency to the latest patch which correctly specifies its version of `lru-cache`. 43 | 44 | ## 4.0.2 45 | 46 | ### Patch Changes 47 | 48 | - [#7170](https://github.com/apollographql/apollo-server/pull/7170) [`4ce738193`](https://github.com/apollographql/apollo-server/commit/4ce738193f8d073287c34f84c0346276ae2efc30) Thanks [@trevor-scheer](https://github.com/trevor-scheer)! - Update @apollo/utils packages to v2 (dropping node 12 support) 49 | 50 | ## 4.0.1 51 | 52 | ### Patch Changes 53 | 54 | - [#7049](https://github.com/apollographql/apollo-server/pull/7049) [`3daee02c6`](https://github.com/apollographql/apollo-server/commit/3daee02c6a0fa34ea0e6f4f18b9a7308539021e3) Thanks [@glasser](https://github.com/glasser)! - Raise minimum `engines` requirement from Node.js v14.0.0 to v14.16.0. This is the minimum version of Node 14 supported by the `engines` requirement of `graphql@16.6.0`. 55 | 56 | - Updated dependencies [[`3daee02c6`](https://github.com/apollographql/apollo-server/commit/3daee02c6a0fa34ea0e6f4f18b9a7308539021e3), [`3daee02c6`](https://github.com/apollographql/apollo-server/commit/3daee02c6a0fa34ea0e6f4f18b9a7308539021e3)]: 57 | - @apollo/server@4.0.1 58 | 59 | ## 4.0.0 60 | 61 | Initial release of `@apollo/server-plugin-response-cache` with support for Apollo Server 4. The version of this plugin designed for Apollo Server 2 and 3 was named `apollo-server-plugin-response-cache`. 62 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/README.md: -------------------------------------------------------------------------------- 1 | # Response Cache plugin 2 | 3 | This Apollo Server response cache plugin implements a full GraphQL query response cache. 4 | 5 | - Add the plugin to your ApolloServer's plugins list 6 | - Set `@cacheControl` hints on your schema or call `info.cacheControl.setCacheHint` in your resolvers 7 | - If the entire GraphQL response is covered by cache hints with non-zero maxAge, 8 | the whole response will be cached. 9 | 10 | This cache is a full query cache: cached responses are only used for identical requests. 11 | 12 | 13 | See [the docs](https://www.apollographql.com/docs/apollo-server/performance/caching/) for details. 14 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/jest.config.js: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../jest.config.base.js'; 2 | 3 | // This needs to be "cloned" since jest depends on the object's identity in some 4 | // way, whether it's via mutation or something else. 5 | export default { ...baseConfig }; 6 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server-plugin-response-cache", 3 | "version": "4.1.4", 4 | "description": "Apollo Server full query response cache", 5 | "type": "module", 6 | "main": "dist/cjs/index.js", 7 | "module": "dist/esm/index.js", 8 | "types": "dist/esm/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": { 12 | "require": "./dist/cjs/index.d.ts", 13 | "default": "./dist/esm/index.d.ts" 14 | }, 15 | "import": "./dist/esm/index.js", 16 | "require": "./dist/cjs/index.js" 17 | } 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/apollographql/apollo-server", 22 | "directory": "packages/plugin-response-cache" 23 | }, 24 | "keywords": [], 25 | "author": "Apollo ", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/apollographql/apollo-server/issues" 29 | }, 30 | "homepage": "https://github.com/apollographql/apollo-server#readme", 31 | "engines": { 32 | "node": ">=14.16.0" 33 | }, 34 | "dependencies": { 35 | "@apollo/utils.createhash": "^2.0.2", 36 | "@apollo/utils.keyvaluecache": "^2.1.0" 37 | }, 38 | "peerDependencies": { 39 | "@apollo/server": "^4.0.1", 40 | "graphql": "^16.6.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/src/__tests__/ApolloServerPluginResponseCache.test.ts: -------------------------------------------------------------------------------- 1 | import plugin from '../ApolloServerPluginResponseCache'; 2 | import { describe, it, expect } from '@jest/globals'; 3 | 4 | describe('Response cache plugin', () => { 5 | it('will instantiate when not called with options', () => { 6 | expect(plugin()).toHaveProperty('requestDidStart'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.test.base", 3 | "include": ["**/*"], 4 | "references": [ 5 | { "path": "../../" }, 6 | { "path": "../../../server" } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ApolloServerPluginResponseCache.js'; 2 | export * from './ApolloServerPluginResponseCache.js'; 3 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ".", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "./dist/cjs" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/plugin-response-cache/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist/esm" 6 | }, 7 | "include": ["src/**/*"], 8 | "exclude": ["**/__tests__"], 9 | "references": [ 10 | { 11 | "path": "../server" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/server/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | # Include the package.json files that give us deep imports. 3 | !**/package.json 4 | !src/**/* 5 | src/**/__tests__/** 6 | !dist/**/* 7 | dist/**/__tests__/** 8 | dist/**/*.tsbuildinfo 9 | !package.json 10 | !README.md 11 | -------------------------------------------------------------------------------- /packages/server/README_landingpages.md: -------------------------------------------------------------------------------- 1 | # How do the Apollo Server landing pages work? 2 | 3 | If users don't manually install any plugin that implements `renderLandingPage`, Apollo Server does the following by default: 4 | 5 | * In non-production environments (`NODE_ENV` is not `production`), Apollo Server installs `ApolloServerPluginLandingPageLocalDefault`. 6 | * In production environments (`NODE_ENV` _is_ `production`), Apollo Server installs `ApolloServerPluginLandingPageProductionDefault`. 7 | 8 | ## Non-embedded landing page 9 | 10 | The `ApolloServerPluginLandingPageProductionDefault` shows a minimalist landing page: 11 | 12 | Apollo Server default landing page 13 | 14 | This landing page is rendered via a [script](https://github.com/apollographql/apollo-server/blob/159d73ca5bac3313c3950743fefc03400263cb0a/packages/server/src/plugin/landingPage/default/index.ts#L76-L78) tag in the index of the landingPage directory. This tag references a CDN upload that contains the built version of the contents of the [studio-landing-page](https://github.com/apollographql/studio-landing-page) repo. This repo uploads versioned and latest CDN bundles on merge to main. 15 | 16 | Configuration params are passed from the user defined config in Apollo Server to the CDN bundle [via `window.landingPage`](https://github.com/apollographql/apollo-server/blob/159d73ca5bac3313c3950743fefc03400263cb0a/packages/server/src/plugin/landingPage/default/index.ts#L75). They are consumed in the studio-landing-page repo [here](https://github.com/apollographql/studio-landing-page/blob/e76e4acdc6207052b1599f4a0f66922976f57f2c/src/App.tsx#L42). 17 | 18 | ## Embedded landing pages 19 | 20 | ### Embedded local dev 21 | 22 | The `ApolloServerPluginLandingPageLocalDefault` shows an embedded Sandbox: 23 | 24 | Apollo Sandbox 25 | 26 | The embedded Sandbox is rendered via a [script](https://github.com/apollographql/apollo-server/blob/159d73ca5bac3313c3950743fefc03400263cb0a/packages/server/src/plugin/landingPage/default/getEmbeddedHTML.ts#L188-L192) tag in the index of the landingPage directory. This tag references a CDN upload that contains the built version of the contents of the [@apollo/sandbox](https://github.com/apollographql/embeddable-explorer/tree/main/packages/sandbox) package in the [embeddable-explorer repo](https://github.com/apollographql/embeddable-explorer). This repo uploads versioned and latest CDN bundles on merge to main. 27 | 28 | Configuration params are passed to the window.EmbeddedSandbox instance which creates an [EmbeddedSandbox](https://github.com/apollographql/embeddable-explorer/blob/main/packages/sandbox/src/EmbeddedSandbox.ts) instance. 29 | 30 | ### Embedded production with graphRef 31 | 32 | The `ApolloServerPluginLandingPageProductionDefault`, when configured with a [graphRef](https://github.com/apollographql/apollo-server/blob/159d73ca5bac3313c3950743fefc03400263cb0a/packages/server/src/plugin/landingPage/default/index.ts#L180-L181), shows an embedded Explorer. 33 | 34 | The embedded Explorer is rendered via a [script](https://github.com/apollographql/apollo-server/blob/159d73ca5bac3313c3950743fefc03400263cb0a/packages/server/src/plugin/landingPage/default/getEmbeddedHTML.ts#L113-L117) tag in the index of the landingPage directory. This tag references a CDN upload that contains the built version of the contents of the [@apollo/explorer](https://github.com/apollographql/embeddable-explorer/tree/main/packages/explorer) package in the [embeddable-explorer repo](https://github.com/apollographql/embeddable-explorer). This repo uploads versioned and latest CDN bundles on merge to main. 35 | 36 | Configuration params are passed to the window.EmbeddedExplorer instance which creates an [EmbeddedSandbox](https://github.com/apollographql/embeddable-explorer/blob/main/packages/explorer/src/EmbeddedExplorer.ts) instance. 37 | -------------------------------------------------------------------------------- /packages/server/errors/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/errors", 3 | "type": "module", 4 | "main": "../dist/cjs/errors/index.js", 5 | "module": "../dist/esm/errors/index.js", 6 | "types": "../dist/esm/errors/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/express4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/express4", 3 | "type": "module", 4 | "main": "../dist/cjs/express4/index.js", 5 | "module": "../dist/esm/express4/index.js", 6 | "types": "../dist/esm/express4/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/jest.config.js: -------------------------------------------------------------------------------- 1 | import baseConfig from '../../jest.config.base.js'; 2 | 3 | // This needs to be "cloned" since jest depends on the object's identity in some 4 | // way, whether it's via mutation or something else. 5 | export default { ...baseConfig }; 6 | -------------------------------------------------------------------------------- /packages/server/plugin/cacheControl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/cacheControl", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/cacheControl/index.js", 5 | "module": "../../dist/esm/plugin/cacheControl/index.js", 6 | "types": "../../dist/esm/plugin/cacheControl/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/disableSuggestions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/disableSuggestions", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/disableSuggestions/index.js", 5 | "module": "../../dist/esm/plugin/disableSuggestions/index.js", 6 | "types": "../../dist/esm/plugin/disableSuggestions/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/disabled/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/disabled", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/disabled/index.js", 5 | "module": "../../dist/esm/plugin/disabled/index.js", 6 | "types": "../../dist/esm/plugin/disabled/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/drainHttpServer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/drainHttpServer", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/drainHttpServer/index.js", 5 | "module": "../../dist/esm/plugin/drainHttpServer/index.js", 6 | "types": "../../dist/esm/plugin/drainHttpServer/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/inlineTrace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/inlineTrace", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/inlineTrace/index.js", 5 | "module": "../../dist/esm/plugin/inlineTrace/index.js", 6 | "types": "../../dist/esm/plugin/inlineTrace/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/landingPage/default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/landingPage/default", 3 | "type": "module", 4 | "main": "../../../dist/cjs/plugin/landingPage/default/index.js", 5 | "module": "../../../dist/esm/plugin/landingPage/default/index.js", 6 | "types": "../../../dist/esm/plugin/landingPage/default/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/schemaReporting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/schemaReporting", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/schemaReporting/index.js", 5 | "module": "../../dist/esm/plugin/schemaReporting/index.js", 6 | "types": "../../dist/esm/plugin/schemaReporting/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/subscriptionCallback/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/subscriptionCallback", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/subscriptionCallback/index.js", 5 | "module": "../../dist/esm/plugin/subscriptionCallback/index.js", 6 | "types": "../../dist/esm/plugin/subscriptionCallback/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/plugin/usageReporting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apollo/server/plugin/usageReporting", 3 | "type": "module", 4 | "main": "../../dist/cjs/plugin/usageReporting/index.js", 5 | "module": "../../dist/esm/plugin/usageReporting/index.js", 6 | "types": "../../dist/esm/plugin/usageReporting/index.d.ts", 7 | "sideEffects": false 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/cachePolicy.test.ts: -------------------------------------------------------------------------------- 1 | import type { CachePolicy } from '@apollo/cache-control-types'; 2 | import { newCachePolicy } from '../cachePolicy.js'; 3 | import { describe, it, expect, beforeEach } from '@jest/globals'; 4 | 5 | describe('newCachePolicy', () => { 6 | let cachePolicy: CachePolicy; 7 | beforeEach(() => { 8 | cachePolicy = newCachePolicy(); 9 | }); 10 | 11 | it('starts uncacheable', () => { 12 | expect(cachePolicy.maxAge).toBeUndefined(); 13 | expect(cachePolicy.scope).toBeUndefined(); 14 | }); 15 | 16 | it('restricting maxAge positive makes restricted', () => { 17 | cachePolicy.restrict({ maxAge: 10 }); 18 | }); 19 | 20 | it('restricting maxAge 0 makes restricted', () => { 21 | cachePolicy.restrict({ maxAge: 0 }); 22 | }); 23 | 24 | it('restricting scope to private makes restricted', () => { 25 | cachePolicy.restrict({ scope: 'PRIVATE' }); 26 | }); 27 | 28 | it('returns lowest max age value', () => { 29 | cachePolicy.restrict({ maxAge: 10 }); 30 | cachePolicy.restrict({ maxAge: 20 }); 31 | 32 | expect(cachePolicy.maxAge).toBe(10); 33 | }); 34 | 35 | it('returns lowest max age value in other order', () => { 36 | cachePolicy.restrict({ maxAge: 20 }); 37 | cachePolicy.restrict({ maxAge: 10 }); 38 | 39 | expect(cachePolicy.maxAge).toBe(10); 40 | }); 41 | 42 | it('maxAge 0 if any cache hint has a maxAge of 0', () => { 43 | cachePolicy.restrict({ maxAge: 120 }); 44 | cachePolicy.restrict({ maxAge: 0 }); 45 | cachePolicy.restrict({ maxAge: 20 }); 46 | 47 | expect(cachePolicy.maxAge).toBe(0); 48 | }); 49 | 50 | it('returns undefined if first cache hint has a maxAge of 0', () => { 51 | cachePolicy.restrict({ maxAge: 0 }); 52 | cachePolicy.restrict({ maxAge: 20 }); 53 | 54 | expect(cachePolicy.maxAge).toBe(0); 55 | }); 56 | 57 | it('only restricting maxAge keeps scope undefined', () => { 58 | cachePolicy.restrict({ maxAge: 10 }); 59 | 60 | expect(cachePolicy.scope).toBeUndefined(); 61 | }); 62 | 63 | it('returns PRIVATE scope if any cache hint has PRIVATE scope', () => { 64 | cachePolicy.restrict({ 65 | maxAge: 10, 66 | scope: 'PUBLIC', 67 | }); 68 | cachePolicy.restrict({ 69 | maxAge: 10, 70 | scope: 'PRIVATE', 71 | }); 72 | 73 | expect(cachePolicy).toHaveProperty('scope', 'PRIVATE'); 74 | }); 75 | 76 | it('policyIfCacheable', () => { 77 | expect(cachePolicy.policyIfCacheable()).toBeNull(); 78 | 79 | cachePolicy.restrict({ scope: 'PRIVATE' }); 80 | expect(cachePolicy.scope).toBe('PRIVATE'); 81 | expect(cachePolicy.policyIfCacheable()).toBeNull(); 82 | 83 | cachePolicy.restrict({ maxAge: 10 }); 84 | expect(cachePolicy).toMatchObject({ 85 | maxAge: 10, 86 | scope: 'PRIVATE', 87 | }); 88 | expect(cachePolicy.policyIfCacheable()).toStrictEqual({ 89 | maxAge: 10, 90 | scope: 'PRIVATE', 91 | }); 92 | 93 | cachePolicy.restrict({ maxAge: 0 }); 94 | expect(cachePolicy).toMatchObject({ 95 | maxAge: 0, 96 | scope: 'PRIVATE', 97 | }); 98 | expect(cachePolicy.policyIfCacheable()).toBeNull(); 99 | }); 100 | 101 | it('replace', () => { 102 | cachePolicy.restrict({ maxAge: 10, scope: 'PRIVATE' }); 103 | cachePolicy.replace({ maxAge: 20, scope: 'PUBLIC' }); 104 | 105 | expect(cachePolicy).toMatchObject({ 106 | maxAge: 20, 107 | scope: 'PUBLIC', 108 | }); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/express4/integration.test.ts: -------------------------------------------------------------------------------- 1 | import cors from 'cors'; 2 | import express, { json } from 'express'; 3 | import http from 'http'; 4 | import { ApolloServer, ApolloServerOptions, BaseContext } from '@apollo/server'; 5 | import { expressMiddleware } from '@apollo/server/express4'; 6 | import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'; 7 | import { urlForHttpServer } from '../../utils/urlForHttpServer'; 8 | import { 9 | defineIntegrationTestSuite, 10 | CreateServerForIntegrationTestsOptions, 11 | } from '@apollo/server-integration-testsuite'; 12 | 13 | defineIntegrationTestSuite(async function ( 14 | serverOptions: ApolloServerOptions, 15 | testOptions?: CreateServerForIntegrationTestsOptions, 16 | ) { 17 | const app = express(); 18 | const httpServer = http.createServer(app); 19 | const server = new ApolloServer({ 20 | ...serverOptions, 21 | plugins: [ 22 | ...(serverOptions.plugins ?? []), 23 | ApolloServerPluginDrainHttpServer({ 24 | httpServer, 25 | }), 26 | ], 27 | }); 28 | 29 | await server.start(); 30 | 31 | app.use( 32 | cors(), 33 | json(), 34 | expressMiddleware(server, { 35 | context: testOptions?.context, 36 | }), 37 | ); 38 | await new Promise((resolve) => { 39 | httpServer.listen({ port: 0 }, resolve); 40 | }); 41 | return { server, url: urlForHttpServer(httpServer) }; 42 | }); 43 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/express4/integrationServerless.test.ts: -------------------------------------------------------------------------------- 1 | import cors from 'cors'; 2 | import express, { json } from 'express'; 3 | import http from 'http'; 4 | import { ApolloServer, ApolloServerOptions, BaseContext } from '@apollo/server'; 5 | import { expressMiddleware } from '@apollo/server/express4'; 6 | import { urlForHttpServer } from '../../utils/urlForHttpServer'; 7 | import { 8 | defineIntegrationTestSuite, 9 | CreateServerForIntegrationTestsOptions, 10 | } from '@apollo/server-integration-testsuite'; 11 | 12 | defineIntegrationTestSuite( 13 | async function ( 14 | serverOptions: ApolloServerOptions, 15 | testOptions?: CreateServerForIntegrationTestsOptions, 16 | ) { 17 | const app = express(); 18 | const httpServer = http.createServer(app); 19 | // For started-in-background servers (ie serverless) we typically don't 20 | // drain in practice (serverless environments run one operation at a 21 | // time). Also, in certain tests where server startup fails we won't be 22 | // legally allowed to call stop() (because you can't stop something that 23 | // hasn't started)... but unlike in the started-in-foreground case, we 24 | // will have already started the http server listening. So we can't just 25 | // rely on the drain plugin to do our server-closing; we do it ourselves 26 | // in the extraCleanup block. 27 | const server = new ApolloServer(serverOptions); 28 | 29 | server.startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests(); 30 | 31 | app.use( 32 | cors(), 33 | json(), 34 | expressMiddleware(server, { 35 | context: testOptions?.context, 36 | }), 37 | ); 38 | await new Promise((resolve) => { 39 | httpServer.listen({ port: 0 }, resolve); 40 | }); 41 | return { 42 | server, 43 | url: urlForHttpServer(httpServer), 44 | async extraCleanup() { 45 | await new Promise((resolve) => { 46 | httpServer.close(resolve); 47 | }); 48 | }, 49 | }; 50 | }, 51 | { serverIsStartedInBackground: true }, 52 | ); 53 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/logger.test.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer } from '..'; 2 | import gql from 'graphql-tag'; 3 | import loglevel from 'loglevel'; 4 | import { mockLogger } from './mockLogger'; 5 | import { jest, describe, it, expect } from '@jest/globals'; 6 | 7 | const KNOWN_DEBUG_MESSAGE = 'The server is starting.'; 8 | 9 | describe('logger', () => { 10 | it('uses internal loglevel logger by default', async () => { 11 | const server = new ApolloServer({ 12 | typeDefs: gql` 13 | type Query { 14 | field: String! 15 | } 16 | `, 17 | plugins: [ 18 | { 19 | async serverWillStart({ logger }) { 20 | logger.debug(KNOWN_DEBUG_MESSAGE); 21 | }, 22 | }, 23 | ], 24 | }); 25 | 26 | const defaultLogger = server.logger as loglevel.Logger; 27 | const debugSpy = jest.spyOn(defaultLogger, 'debug'); 28 | await server.start(); 29 | 30 | expect(debugSpy).toHaveBeenCalledWith(KNOWN_DEBUG_MESSAGE); 31 | // checking the logger is the one from `loglevel`, we can't instance check 32 | // this since loglevel doesn't uses classes. 33 | expect(defaultLogger.levels).toEqual(loglevel.levels); 34 | }); 35 | 36 | it('uses custom logger when configured', async () => { 37 | const logger = mockLogger(); 38 | const server = new ApolloServer({ 39 | typeDefs: gql` 40 | type Query { 41 | field: String! 42 | } 43 | `, 44 | plugins: [ 45 | { 46 | async serverWillStart({ logger }) { 47 | logger.debug(KNOWN_DEBUG_MESSAGE); 48 | }, 49 | }, 50 | ], 51 | logger, 52 | }); 53 | 54 | await server.start(); 55 | expect(logger.debug).toHaveBeenCalledWith(KNOWN_DEBUG_MESSAGE); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/mockLogger.ts: -------------------------------------------------------------------------------- 1 | import { jest } from '@jest/globals'; 2 | 3 | export function mockLogger() { 4 | return { 5 | debug: jest.fn(), 6 | info: jest.fn(), 7 | warn: jest.fn(), 8 | error: jest.fn(), 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/nockAssertions.ts: -------------------------------------------------------------------------------- 1 | import { expect } from '@jest/globals'; 2 | import nock from 'nock'; 3 | 4 | // Ensures an active and clean nock before every test 5 | export function nockBeforeEach() { 6 | if (!nock.isActive()) { 7 | nock.activate(); 8 | } 9 | // Cleaning _before_ each test ensures that any mocks from a previous test 10 | // which failed don't affect the current test. 11 | nock.cleanAll(); 12 | } 13 | 14 | // Ensures a test is complete (all expected requests were run) and a clean 15 | // global state after each test. 16 | export function nockAfterEach() { 17 | // un-mock HTTP interceptor 18 | nock.restore(); 19 | // effectively nock.isDone() but with more helpful messages in test failures 20 | expect(nock.activeMocks()).toEqual([]); 21 | } 22 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/cacheControl/cacheControlSupport.ts: -------------------------------------------------------------------------------- 1 | import { buildSchema } from 'graphql'; 2 | import { 3 | makeExecutableSchema, 4 | IExecutableSchemaDefinition, 5 | } from '@graphql-tools/schema'; 6 | import { addMocksToSchema } from '@graphql-tools/mock'; 7 | 8 | export function augmentTypeDefsWithCacheControlSupport(typeDefs: string) { 9 | return ( 10 | ` 11 | enum CacheControlScope { 12 | PUBLIC 13 | PRIVATE 14 | } 15 | 16 | directive @cacheControl( 17 | maxAge: Int 18 | scope: CacheControlScope 19 | inheritMaxAge: Boolean 20 | ) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION 21 | ` + typeDefs 22 | ); 23 | } 24 | 25 | export function buildSchemaWithCacheControlSupport(source: string) { 26 | return buildSchema(augmentTypeDefsWithCacheControlSupport(source)); 27 | } 28 | 29 | export function makeExecutableSchemaWithCacheControlSupport( 30 | options: IExecutableSchemaDefinition & { typeDefs: string }, 31 | ) { 32 | return addMocksToSchema({ 33 | schema: makeExecutableSchema({ 34 | ...options, 35 | typeDefs: augmentTypeDefsWithCacheControlSupport(options.typeDefs), 36 | }), 37 | preserveResolvers: true, 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/cacheControl/collectCacheControlHints.ts: -------------------------------------------------------------------------------- 1 | import type { CacheHint } from '@apollo/cache-control-types'; 2 | import type { GraphQLSchema } from 'graphql'; 3 | import { ApolloServer } from '../../..'; 4 | import { 5 | ApolloServerPluginCacheControl, 6 | ApolloServerPluginCacheControlOptions, 7 | } from '../../../plugin/cacheControl'; 8 | import { expect } from '@jest/globals'; 9 | 10 | export async function collectCacheControlHintsAndPolicyIfCacheable( 11 | schema: GraphQLSchema, 12 | source: string, 13 | options: ApolloServerPluginCacheControlOptions = {}, 14 | ): Promise<{ 15 | hints: Map; 16 | policyIfCacheable: Required | null; 17 | }> { 18 | const cacheHints = new Map(); 19 | const server = new ApolloServer({ 20 | schema, 21 | plugins: [ 22 | ApolloServerPluginCacheControl({ 23 | ...options, 24 | __testing__cacheHints: cacheHints, 25 | }), 26 | { 27 | async requestDidStart() { 28 | return { 29 | async willSendResponse({ response, overallCachePolicy }) { 30 | if (!('singleResult' in response.body)) { 31 | throw Error('expected single result'); 32 | } 33 | 34 | if (!response.body.singleResult.extensions) { 35 | response.body.singleResult.extensions = {}; 36 | } 37 | response.body.singleResult.extensions.__policyIfCacheable__ = 38 | overallCachePolicy.policyIfCacheable(); 39 | }, 40 | }; 41 | }, 42 | }, 43 | ], 44 | }); 45 | await server.start(); 46 | const response = await server.executeOperation({ query: source }); 47 | await server.stop(); 48 | 49 | if (!('singleResult' in response.body)) { 50 | throw new Error('expected single result'); 51 | } 52 | 53 | expect(response.body.singleResult.errors).toBeUndefined(); 54 | 55 | return { 56 | hints: cacheHints, 57 | policyIfCacheable: response.body.singleResult.extensions! 58 | .__policyIfCacheable__ as any, 59 | }; 60 | } 61 | 62 | export async function collectCacheControlHints( 63 | ...args: Parameters 64 | ): Promise> { 65 | return (await collectCacheControlHintsAndPolicyIfCacheable(...args)).hints; 66 | } 67 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/disableSuggestions/disableSuggestions.test.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer, HeaderMap } from '../../..'; 2 | import { describe, it, expect } from '@jest/globals'; 3 | import assert from 'assert'; 4 | 5 | describe('ApolloServerPluginDisableSuggestions', () => { 6 | async function makeServer({ 7 | withPlugin, 8 | query, 9 | }: { 10 | withPlugin: boolean; 11 | query: string; 12 | }) { 13 | const server = new ApolloServer({ 14 | typeDefs: 'type Query {hello: String}', 15 | resolvers: { 16 | Query: { 17 | hello() { 18 | return 'asdf'; 19 | }, 20 | }, 21 | }, 22 | hideSchemaDetailsFromClientErrors: withPlugin, 23 | }); 24 | 25 | await server.start(); 26 | 27 | try { 28 | return await server.executeHTTPGraphQLRequest({ 29 | httpGraphQLRequest: { 30 | method: 'POST', 31 | headers: new HeaderMap([['apollo-require-preflight', 't']]), 32 | search: '', 33 | body: { 34 | query, 35 | }, 36 | }, 37 | context: async () => ({}), 38 | }); 39 | } finally { 40 | await server.stop(); 41 | } 42 | } 43 | 44 | it('should not hide suggestions when plugin is not enabled', async () => { 45 | const response = await makeServer({ 46 | withPlugin: false, 47 | query: `#graphql 48 | query { 49 | help 50 | } 51 | `, 52 | }); 53 | 54 | assert(response.body.kind === 'complete'); 55 | expect(JSON.parse(response.body.string).errors[0].message).toBe( 56 | 'Cannot query field "help" on type "Query". Did you mean "hello"?', 57 | ); 58 | }); 59 | 60 | it('should hide suggestions when plugin is enabled', async () => { 61 | const response = await makeServer({ 62 | withPlugin: true, 63 | query: `#graphql 64 | query { 65 | help 66 | } 67 | `, 68 | }); 69 | 70 | assert(response.body.kind === 'complete'); 71 | expect(JSON.parse(response.body.string).errors[0].message).toBe( 72 | 'Cannot query field "help" on type "Query".', 73 | ); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/drainHttpServer/stoppable/fixture.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDBzCCAe+gAwIBAgIJALpsaWTYcddKMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV 3 | BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzA1MTkxOTAwMzZaFw0yNzA1MTcxOTAw 4 | MzZaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB 5 | BQADggEPADCCAQoCggEBAOix4xb3jnIdWwqfT+vtoXadLuQJE21HN19Y2falkJuB 6 | k/ME0TKMeMjmQQZCO7G0K+5fMnQsEtQjcjY3XUXViliGfkAQplUD3Z9/xwsTSGN2 7 | ahBXE2W/GV+xJ6uX9KbJx2pMOXCuux6cKylYhmr8cTs2f9E6QpPji4LqtHv/9cAE 8 | QKRmv2rSAP1Q+1Ne2WYNbgHBuI35vuQsvZTN5QsozsferP9Qqtx8kpnBaLTgFZYD 9 | ZaEreYwFFYAQNfq2jOGEAAxStiXUpn3rT9T8KeOvLfWOifqYzDOTzL0t2py9bnvl 10 | x2fl8aJHc3NiU+4qlq3DuDEitiUoOkirGhFL7JFH4K0CAwEAAaNQME4wHQYDVR0O 11 | BBYEFAI/PRTwA3VKpSQAwXg2JDmDGVXxMB8GA1UdIwQYMBaAFAI/PRTwA3VKpSQA 12 | wXg2JDmDGVXxMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHfYOl+n 13 | qB0Oyq/2jXE33fR5+QsaDrciXH0BWCjIVM8ADLPjYPAD3StTIceg3wfCw2n9xuku 14 | pObukGbApSqvGBSAIsvbbNAwcFp31DCqGQdfVMJMG1TCp3J7y0WslYMqU7DM1jYt 15 | ybqF9ICuGdPZ0KVsv0/ZmbSs98/fSyjUYoHfD+GngVrguuU/v0XUi4hjVqFyMZQZ 16 | AxGNq4QIlKxdo55L45vCMzGiajT7BE0EnChvFpOGXF5/pk072RESI7uxJBiAssWP 17 | uCk0xHxLtacOQK3seFFw0d7t3769gVDNi732eTMhoFQj+loSgmnRwDKL7QPhZ8tj 18 | pRRUGV4sPR+ucpo= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/drainHttpServer/stoppable/fixture.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA6LHjFveOch1bCp9P6+2hdp0u5AkTbUc3X1jZ9qWQm4GT8wTR 3 | Mox4yOZBBkI7sbQr7l8ydCwS1CNyNjddRdWKWIZ+QBCmVQPdn3/HCxNIY3ZqEFcT 4 | Zb8ZX7Enq5f0psnHakw5cK67HpwrKViGavxxOzZ/0TpCk+OLguq0e//1wARApGa/ 5 | atIA/VD7U17ZZg1uAcG4jfm+5Cy9lM3lCyjOx96s/1Cq3HySmcFotOAVlgNloSt5 6 | jAUVgBA1+raM4YQADFK2JdSmfetP1Pwp468t9Y6J+pjMM5PMvS3anL1ue+XHZ+Xx 7 | okdzc2JT7iqWrcO4MSK2JSg6SKsaEUvskUfgrQIDAQABAoIBAE8UJRipCL+/OjFh 8 | 8sc6+qRUxpq4euGoUikVCP3JRluSrbTo7i8/jcy4c2CtIZxCnqtjrsHMOJnfcfD6 9 | 37fb2ig7jKw4/E3oAmkyA3LAGtmyZFkpPm5Vg0oB6nlmKr6D1EFLpjmlJ/I/IGvs 10 | qcGyCMkWvFlec0HPEpprKOr7EYkvQscy99ny7JswG1P9PELwo7tIeb0BioPYnFmF 11 | I0BPgI1lxDHKQTUPAao9rStiHsuPMCkw51qUgp/Z814ld4KDXCaWFQPy5riHDykH 12 | wm9n2hkM6pq4d6eHuMVj7CuBdp141k2BAnZdysMHpE9y1315+didoEcox8+zOLeO 13 | OC4XZAECgYEA/U98ld2YnVcSL9/Pr17SVG/q3iZaUueUkf+CEdj7LpvStedpky5W 14 | dOM7ad0kBcPqIafgn/O3teYjVl8FM0oOtOheMHHMkYxbXuECA5hkk7emu3oIJcAO 15 | +9Pb/uGdufWmAVyRueRam4tubiLxv46xeGUmscCnwG78bj+rq74ATjcCgYEA6ypd 16 | qt/b43y4SHY4LDuuJk5jfC5MNXztIi3sOtuGoJNUlzC/hI/NNhEDhP3Pzo9c/i0k 17 | aCzyjhRyiaFK2SHQ5SQdCFi44PM+MptwFjY1KPGv20m5omfBgJOoF+Ad13qrUQF/ 18 | b7/C5j3PZkOZfwaYO+erLeaayWKRJi2AEoXb9jsCgYEAnxAHuo/A4qQnXnqbDpNr 19 | Xew9Pqw0sbSLvbYFNjHbYKQmh2U+DVbeoV2DFHHxydEBN4sUaTyAUq+l5vmZ6WAK 20 | phz38FG1VHwfcA+41QsftQZwo274qMPWZNnfXkjMY1ZWnKpFM8aqAtxmRrCYv2Ha 21 | HTDfQGUqsZK/3ncK1LhltrcCgYBiJKk4wfpL42YpX6Ur2LBibj6Yud22SO/SXuYC 22 | 3lE+PJ6GBqM3GKilEs6sNxz98Nj3fzF9hJyp7SCsDbNmEPXUW5D+RcDKqNlhV3uc 23 | 2XywHMWuuAMQI0sfdQAnDrKFlj1fLkfYBGi7nDotTLMHz2HDRnkrS913hHpdO4oC 24 | sPjOtwKBgQDDiG7Vagk4SgPXt7zE0aSiFIIjJLpM28mES+k6zOtKAyOcTMHcDrI7 25 | YmSN1kq3w2g7RS5eMUpszqbUGoR6VDAjbgGAakDOno/uZWfEMjiQiKvRDSY1nmlc 26 | xSKubMZDf/OKUYTGasL1rqJJN7mxW2irptygc26NxMeAWZfgkmiPLg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/inlineTrace/inlineTracePlugin.test.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer, HeaderMap } from '@apollo/server'; 2 | import { gql } from 'graphql-tag'; 3 | import { buildSubgraphSchema } from '@apollo/subgraph'; 4 | import { describe, it, expect } from '@jest/globals'; 5 | import assert from 'assert'; 6 | import { Trace } from '@apollo/usage-reporting-protobuf'; 7 | import { ApolloServerPluginInlineTrace } from '@apollo/server/plugin/inlineTrace'; 8 | 9 | describe('ApolloServerPluginInlineTrace', () => { 10 | it('Adds errors within lists to the correct path rather than the root', async () => { 11 | const server = new ApolloServer({ 12 | schema: buildSubgraphSchema({ 13 | typeDefs: gql` 14 | type Query { 15 | a: A! 16 | } 17 | type A { 18 | brokenList: [String!]! 19 | } 20 | `, 21 | resolvers: { 22 | Query: { 23 | a: () => ({}), 24 | }, 25 | A: { 26 | brokenList() { 27 | return ['hello world!', null]; 28 | }, 29 | }, 30 | }, 31 | }), 32 | plugins: [ 33 | // silence logs about the plugin being enabled 34 | ApolloServerPluginInlineTrace(), 35 | ], 36 | }); 37 | await server.start(); 38 | const result = await server.executeHTTPGraphQLRequest({ 39 | httpGraphQLRequest: { 40 | body: { query: '{a{brokenList}}' }, 41 | headers: new HeaderMap([ 42 | ['content-type', 'application/json'], 43 | ['apollo-federation-include-trace', 'ftv1'], 44 | ]), 45 | method: 'POST', 46 | search: '', 47 | }, 48 | context: async () => ({}), 49 | }); 50 | assert(result.body.kind === 'complete'); 51 | const trace = Trace.decode( 52 | Buffer.from(JSON.parse(result.body.string).extensions?.ftv1, 'base64'), 53 | ); 54 | expect(trace.root?.error).toHaveLength(0); 55 | // error is found at path a.brokenList.1 56 | expect(trace.root?.child?.[0].child?.[0].child?.[0].error) 57 | .toMatchInlineSnapshot(` 58 | [ 59 | { 60 | "json": "{"message":"","locations":[{"line":1,"column":4}],"path":["a","brokenList",1],"extensions":{"maskedBy":"ApolloServerPluginInlineTrace"}}", 61 | "location": [ 62 | { 63 | "column": 4, 64 | "line": 1, 65 | }, 66 | ], 67 | "message": "", 68 | }, 69 | ] 70 | `); 71 | 72 | await server.stop(); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /packages/server/src/__tests__/plugin/landingPage/plugin.test.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServer, HeaderMap } from '@apollo/server'; 2 | import { 3 | ApolloServerPluginLandingPageLocalDefault, 4 | ApolloServerPluginLandingPageProductionDefault, 5 | } from '@apollo/server/plugin/landingPage/default'; 6 | import { describe, expect, test } from '@jest/globals'; 7 | import assert from 'assert'; 8 | import { mockLogger } from '../../mockLogger'; 9 | 10 | describe('ApolloServerPluginLandingPageDefault', () => { 11 | test(`nonce isn't reused between requests`, async () => { 12 | const server = new ApolloServer({ 13 | typeDefs: `#graphql 14 | type Query { 15 | hello: String! 16 | } 17 | `, 18 | }); 19 | await server.start(); 20 | 21 | async function requestLandingPage() { 22 | return server.executeHTTPGraphQLRequest({ 23 | httpGraphQLRequest: { 24 | headers: new HeaderMap([['accept', 'text/html']]), 25 | method: 'GET', 26 | body: undefined, 27 | search: '', 28 | }, 29 | context: async () => ({}), 30 | }); 31 | } 32 | 33 | const { body: request1 } = await requestLandingPage(); 34 | const { body: request2 } = await requestLandingPage(); 35 | 36 | assert(request1.kind === 'complete' && request2.kind === 'complete'); 37 | 38 | const nonce1 = request1.string.match(/nonce="([^"]+)"/)?.[1]; 39 | const nonce2 = request2.string.match(/nonce="([^"]+)"/)?.[1]; 40 | 41 | expect(nonce1).not.toEqual(nonce2); 42 | await server.stop(); 43 | }); 44 | 45 | test(`warns when using precomputedNonce`, async () => { 46 | const logger = mockLogger(); 47 | const server = new ApolloServer({ 48 | typeDefs: `#graphql 49 | type Query { 50 | hello: String! 51 | } 52 | `, 53 | plugins: [ 54 | ApolloServerPluginLandingPageLocalDefault({ 55 | precomputedNonce: 'abc123', 56 | }), 57 | ], 58 | logger, 59 | }); 60 | await server.start(); 61 | 62 | expect(logger.warn).toHaveBeenCalledWith( 63 | "The `precomputedNonce` landing page configuration option is deprecated. Removing this option is strictly an improvement to Apollo Server's landing page Content Security Policy (CSP) implementation for preventing XSS attacks.", 64 | ); 65 | await server.stop(); 66 | }); 67 | 68 | test(`nonce exists in non-embedded landing page`, async () => { 69 | const plugin = ApolloServerPluginLandingPageProductionDefault({ 70 | embed: false, 71 | }); 72 | 73 | // @ts-ignore not passing things to `serverWillStart` 74 | const { renderLandingPage } = await plugin.serverWillStart?.({}); 75 | const landingPageHtml = await (await renderLandingPage?.()).html(); 76 | 77 | expect(landingPageHtml).toMatch(/