Repository: apollographql/apollo-server
Pull request #7270 (2022-12-21 18:30:03)

docs: demo `contextValue` in `executeOperation`
This tripped up a customer, and we only document the values for the first argument below.

<!--
First, 🌠 thank you 🌠 for taking the time to consider a contribution to Apollo!

Here are some important details to follow:

* ⏰ Your time is important
          To save your precious time, if the contribution you are making will take more
          than an hour, please make sure it has been discussed in an issue first.
          This is especially true for feature requests!
* 💡 Features
          Feature requests can be created and discussed within a GitHub Issue.  Be
          sure to search for existing feature requests (and related issues!) prior to
          opening a new request.  If an existing issue covers the need, please upvote
          that issue by using the 👍 emote, rather than opening a new issue.
* 🔌 Integrations
          Apollo Server has many web-framework integrations including Express, Koa,
          Hapi and more.  When adding a new feature, or fixing a bug, please take a
          peak and see if other integrations are also affected.  In most cases, the
          fix can be applied to the other frameworks as well.  Please note that,
          since new web-frameworks have a high maintenance cost, pull-requests for
          new web-frameworks should be discussed with a project maintainer first.
* 🕷 Bug fixes
          These can be created and discussed in this repository. When fixing a bug,
          please _try_ to add a test which verifies the fix.  If you cannot, you should
          still submit the PR but we may still ask you (and help you!) to create a test.
* 📖 Contribution guidelines
          Follow https://github.com/apollographql/apollo-server/blob/main/CONTRIBUTING.md
          when submitting a pull request.  Make sure existing tests still pass, and add
          tests for all new behavior.
* ✏️ Explain your pull request
          Describe the big picture of your changes here to communicate to what your
          pull request is meant to accomplish.  Provide 🔗 links 🔗 to associated issues!

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.
-->


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *apollo-server-docs* processing.


|  Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | fb174126d37d17f4aa0a037d2d46ccdcb1cf115c |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/apollo-server-docs/deploys/63a350ad354da10009a13a25 |
codesandbox-ci[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/apollographql/apollo-server/pr/7270/builds/329142) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit fb174126d37d17f4aa0a037d2d46ccdcb1cf115c:

|Sandbox| Source |
|--|--|
|[Apollo Server Typescript](https://codesandbox.io/s/apollo-server-typescript-genih0)| Configuration |
|[Apollo Server](https://codesandbox.io/s/apollo-server-49pfcz)| Configuration |


Patch:
diff --git a/.changeset/quiet-pears-float.md b/.changeset/quiet-pears-float.md
new file mode 100644
index 000000000..b7feaa1aa
--- /dev/null
+++ b/.changeset/quiet-pears-float.md
@@ -0,0 +1,5 @@
+---
+'@apollo/server': patch
+---
+
+Update schemaIsSubgraph to also support non nullable \_Service.sdl
diff --git a/docs/source/api/apollo-server.mdx b/docs/source/api/apollo-server.mdx
index 1063da21c..a5b9a203f 100644
--- a/docs/source/api/apollo-server.mdx
+++ b/docs/source/api/apollo-server.mdx
@@ -581,6 +581,15 @@ The `executeOperation` method takes two arguments:
 - The first argument is an object describing the GraphQL operation to be executed.
   - Supported fields are listed in the table below.
 - The second argument is the optional options object. This object includes the operation's optional [`contextValue`](../data/context#the-contextvalue-object). This argument is only optional if your server _doesn't_ expect a context value (i.e., your server uses the default context because you didn't explicitly provide another one).
+  
+```js
+const response = await server.executeOperation({
+  query: 'query SayHelloWorld($name: String) { hello(name: $name) }',
+  variables: { name: 'world' },
+}, {
+  contextValue: { userId: 'test' },
+});
+```
 
 The `response` object returned from `executeOperation` is a `GraphQLResponse`, which has `body` and `http` fields.
 
diff --git a/package-lock.json b/package-lock.json
index 215845f2d..5df5146a2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,7 +20,7 @@
         "@graphql-tools/mock": "8.7.14",
         "@graphql-tools/schema": "9.0.12",
         "@josephg/resolvable": "1.0.1",
-        "@rollup/plugin-commonjs": "23.0.7",
+        "@rollup/plugin-commonjs": "24.0.0",
         "@types/async-retry": "1.4.5",
         "@types/body-parser": "1.19.2",
         "@types/compression": "1.7.2",
@@ -68,7 +68,7 @@
         "qs-middleware": "1.0.3",
         "requisition": "1.7.0",
         "rimraf": "3.0.2",
-        "rollup": "3.7.5",
+        "rollup": "3.8.1",
         "supertest": "6.3.3",
         "test-listen": "1.1.0",
         "ts-jest": "29.0.3",
@@ -3869,9 +3869,9 @@
       "license": "BSD-3-Clause"
     },
     "node_modules/@rollup/plugin-commonjs": {
-      "version": "23.0.7",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.7.tgz",
-      "integrity": "sha512-hsSD5Qzyuat/swzrExGG5l7EuIlPhwTsT7KwKbSCQzIcJWjRxiimi/0tyMYY2bByitNb3i1p+6JWEDGa0NvT0Q==",
+      "version": "24.0.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz",
+      "integrity": "sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==",
       "dev": true,
       "dependencies": {
         "@rollup/pluginutils": "^5.0.1",
@@ -3922,9 +3922,9 @@
       }
     },
     "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz",
-      "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
+      "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
@@ -11402,9 +11402,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "3.7.5",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.5.tgz",
-      "integrity": "sha512-z0ZbqHBtS/et2EEUKMrAl2CoSdwN7ZPzL17UMiKN9RjjqHShTlv7F9J6ZJZJNREYjBh3TvBrdfjkFDIXFNeuiQ==",
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.1.tgz",
+      "integrity": "sha512-4yh9eMW7byOroYcN8DlF9P/2jCpu6txVIHjEqquQVSx7DI0RgyCCN3tjrcy4ra6yVtV336aLBB3v2AarYAxePQ==",
       "dev": true,
       "bin": {
         "rollup": "dist/bin/rollup"
@@ -16445,9 +16445,9 @@
       "version": "1.1.0"
     },
     "@rollup/plugin-commonjs": {
-      "version": "23.0.7",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.7.tgz",
-      "integrity": "sha512-hsSD5Qzyuat/swzrExGG5l7EuIlPhwTsT7KwKbSCQzIcJWjRxiimi/0tyMYY2bByitNb3i1p+6JWEDGa0NvT0Q==",
+      "version": "24.0.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz",
+      "integrity": "sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==",
       "dev": true,
       "requires": {
         "@rollup/pluginutils": "^5.0.1",
@@ -16481,9 +16481,9 @@
           }
         },
         "minimatch": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz",
-          "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==",
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
+          "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==",
           "dev": true,
           "requires": {
             "brace-expansion": "^2.0.1"
@@ -21752,9 +21752,9 @@
       }
     },
     "rollup": {
-      "version": "3.7.5",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.5.tgz",
-      "integrity": "sha512-z0ZbqHBtS/et2EEUKMrAl2CoSdwN7ZPzL17UMiKN9RjjqHShTlv7F9J6ZJZJNREYjBh3TvBrdfjkFDIXFNeuiQ==",
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.1.tgz",
+      "integrity": "sha512-4yh9eMW7byOroYcN8DlF9P/2jCpu6txVIHjEqquQVSx7DI0RgyCCN3tjrcy4ra6yVtV336aLBB3v2AarYAxePQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.2"
diff --git a/package.json b/package.json
index 0ddc5f28d..ebb19b8ca 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "@graphql-tools/mock": "8.7.14",
     "@graphql-tools/schema": "9.0.12",
     "@josephg/resolvable": "1.0.1",
-    "@rollup/plugin-commonjs": "23.0.7",
+    "@rollup/plugin-commonjs": "24.0.0",
     "@types/async-retry": "1.4.5",
     "@types/body-parser": "1.19.2",
     "@types/compression": "1.7.2",
@@ -95,7 +95,7 @@
     "qs-middleware": "1.0.3",
     "requisition": "1.7.0",
     "rimraf": "3.0.2",
-    "rollup": "3.7.5",
+    "rollup": "3.8.1",
     "supertest": "6.3.3",
     "test-listen": "1.1.0",
     "ts-jest": "29.0.3",
diff --git a/packages/server/src/plugin/schemaIsSubgraph.ts b/packages/server/src/plugin/schemaIsSubgraph.ts
index 88e75aecb..580926d57 100644
--- a/packages/server/src/plugin/schemaIsSubgraph.ts
+++ b/packages/server/src/plugin/schemaIsSubgraph.ts
@@ -1,4 +1,9 @@
-import { GraphQLSchema, isObjectType, isScalarType } from 'graphql';
+import {
+  GraphQLSchema,
+  isObjectType,
+  isScalarType,
+  isNonNullType,
+} from 'graphql';
 
 // Returns true if it appears that the schema was appears to be of a subgraph
 // (eg, returned from @apollo/subgraph's buildSubgraphSchema). This strategy
@@ -24,7 +29,11 @@ export function schemaIsSubgraph(schema: GraphQLSchema): boolean {
   if (!sdlField) {
     return false;
   }
-  const sdlFieldType = sdlField.type;
+
+  let sdlFieldType = sdlField.type;
+  if (isNonNullType(sdlFieldType)) {
+    sdlFieldType = sdlFieldType.ofType;
+  }
   if (!isScalarType(sdlFieldType)) {
     return false;
   }


Test patch:
diff --git a/packages/server/src/__tests__/plugin/schemaIsSubgraph.test.ts b/packages/server/src/__tests__/plugin/schemaIsSubgraph.test.ts
new file mode 100644
index 000000000..0dcefdc80
--- /dev/null
+++ b/packages/server/src/__tests__/plugin/schemaIsSubgraph.test.ts
@@ -0,0 +1,122 @@
+import { schemaIsSubgraph } from '../../plugin/schemaIsSubgraph';
+import { describe, it, expect } from '@jest/globals';
+
+import {
+  GraphQLSchema,
+  GraphQLObjectType,
+  GraphQLString,
+  GraphQLInt,
+  GraphQLNonNull,
+} from 'graphql';
+
+describe('schemaIsSubgraph', () => {
+  it('returns false when there is no service field', async () => {
+    const schema = new GraphQLSchema({
+      query: new GraphQLObjectType({
+        name: 'QueryType',
+        fields: {
+          hello: {
+            type: GraphQLString,
+          },
+        },
+      }),
+    });
+
+    expect(schemaIsSubgraph(schema)).toBe(false);
+  });
+
+  it('returns false when the sdl field is a not string', async () => {
+    const schema = new GraphQLSchema({
+      query: new GraphQLObjectType({
+        name: 'QueryType',
+        fields: {
+          _service: {
+            type: new GraphQLObjectType({
+              name: '_Service',
+              fields: {
+                sdl: {
+                  type: GraphQLInt,
+                },
+              },
+            }),
+          },
+        },
+      }),
+    });
+
+    expect(schemaIsSubgraph(schema)).toBe(false);
+  });
+
+  it('returns false when the sdl field is a scalar', async () => {
+    const schema = new GraphQLSchema({
+      query: new GraphQLObjectType({
+        name: 'QueryType',
+        fields: {
+          _service: {
+            type: new GraphQLObjectType({
+              name: '_Service',
+              fields: {
+                sdl: {
+                  type: new GraphQLObjectType({
+                    name: 'Scalar',
+                    fields: {
+                      value: {
+                        type: GraphQLString,
+                      },
+                    },
+                  }),
+                },
+              },
+            }),
+          },
+        },
+      }),
+    });
+
+    expect(schemaIsSubgraph(schema)).toBe(false);
+  });
+
+  it('returns true when the sdl field is a string', async () => {
+    const schema = new GraphQLSchema({
+      query: new GraphQLObjectType({
+        name: 'QueryType',
+        fields: {
+          _service: {
+            type: new GraphQLObjectType({
+              name: '_Service',
+              fields: {
+                sdl: {
+                  type: GraphQLString,
+                },
+              },
+            }),
+          },
+        },
+      }),
+    });
+
+    expect(schemaIsSubgraph(schema)).toBe(true);
+  });
+
+  it('returns true when the sdl field is a non nullable string', async () => {
+    const schema = new GraphQLSchema({
+      query: new GraphQLObjectType({
+        name: 'QueryType',
+        fields: {
+          _service: {
+            type: new GraphQLObjectType({
+              name: '_Service',
+              fields: {
+                sdl: {
+                  type: new GraphQLNonNull(GraphQLString),
+                },
+              },
+            }),
+          },
+        },
+      }),
+    });
+
+    expect(schemaIsSubgraph(schema)).toBe(true);
+  });
+});
diff --git a/smoke-test/package.json b/smoke-test/package.json
index 4585f1020..e50e9e4c0 100644
--- a/smoke-test/package.json
+++ b/smoke-test/package.json
@@ -4,11 +4,11 @@
     "make-fetch-happen": "11.0.2"
   },
   "devDependencies": {
-    "@rollup/plugin-commonjs": "23.0.7",
-    "@rollup/plugin-json": "5.0.2",
+    "@rollup/plugin-commonjs": "24.0.0",
+    "@rollup/plugin-json": "6.0.0",
     "@rollup/plugin-node-resolve": "15.0.1",
     "@types/make-fetch-happen": "10.0.1",
-    "rollup": "3.7.5"
+    "rollup": "3.8.1"
   },
   "volta": {
     "extends": "../package.json"