├── .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 | Name / Type |
82 | Description |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | ###### `httpServer`
92 |
93 | [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server)
94 |
95 | |
96 |
97 |
98 | The server to drain; required.
99 |
100 | |
101 |
102 |
103 |
104 |
105 |
106 | ###### `stopGracePeriodMillis`
107 |
108 | `number`
109 |
110 | |
111 |
112 |
113 | How long to wait before forcefully closing non-idle connections. Defaults to `10_000` (ten seconds).
114 |
115 | |
116 |
117 |
118 |
119 |
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 |
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 |
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 |
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