vscode-apollo 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,55 @@
1
+ name: Bundle Extension as Artifact Download
2
+ on:
3
+ pull_request:
4
+ jobs:
5
+ test:
6
+ name: Bundle Extension as Artifact Download
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v4
10
+ - uses: actions/setup-node@v4
11
+ with:
12
+ cache: "npm"
13
+ - run: npm install
14
+ - run: echo PKG_VERSION="$(git show --no-patch --format=0.0.0-build.%ct.pr.${{ github.event.pull_request.number }}.commit.%h)" >> $GITHUB_ENV
15
+ - run: npm pkg set "version=${{ env.PKG_VERSION }}"
16
+ - run: npx -y @vscode/vsce package --out vscode-apollo-${{ env.PKG_VERSION }}.vsix
17
+
18
+ - uses: actions/upload-artifact@v4
19
+ id: artifact-upload-step
20
+ with:
21
+ name: vscode-apollo-${{ env.PKG_VERSION }}
22
+ path: vscode-apollo-${{ env.PKG_VERSION }}.vsix
23
+ retention-days: 14
24
+
25
+ - name: Output artifact URL
26
+ run: echo 'Artifact URL is ${{ steps.artifact-upload-step.outputs.artifact-url }}'
27
+
28
+ - name: Find Comment
29
+ uses: peter-evans/find-comment@v3
30
+ id: fc
31
+ with:
32
+ issue-number: ${{ github.event.pull_request.number }}
33
+ comment-author: "github-actions[bot]"
34
+ body-includes: <!-- ARTIFACT-DOWNLOAD -->
35
+
36
+ - name: Create comment
37
+ uses: peter-evans/create-or-update-comment@v4
38
+ with:
39
+ issue-number: ${{ github.event.pull_request.number }}
40
+ comment-id: ${{ steps.fc.outputs.comment-id }}
41
+ edit-mode: replace
42
+ body: |
43
+ <!-- ARTIFACT-DOWNLOAD -->
44
+ You can download the latest build of the extension for this PR here:
45
+ [vscode-apollo-${{ env.PKG_VERSION }}.zip](${{ steps.artifact-upload-step.outputs.artifact-url }}).
46
+
47
+ To install the extension, download the file, unzip it and install it in VS Code by selecting "Install from VSIX..." in the Extensions view.
48
+
49
+ Alternatively, run
50
+ ```sh
51
+ code --install-extension vscode-apollo-${{ env.PKG_VERSION }}.vsix --force
52
+ ```
53
+ from the command line.
54
+
55
+ For older builds, please see the edit history of this comment.
@@ -86,7 +86,7 @@ jobs:
86
86
  "type": "section",
87
87
  "text": {
88
88
  "type": "mrkdwn",
89
- "text": "A new version of `vscode-apollo` was released: <https://github.com/apollographql/vscode-apollo/releases/tag/v${{ fromJson(steps.changesets.outputs.publishedPackages)[0].version }}|v${{ fromJson(steps.changesets.outputs.publishedPackages)[0].version }}> :rocket:"
89
+ "text": "A new version of `vscode-apollo` was released: <https://github.com/apollographql/vscode-graphql/releases/tag/v${{ fromJson(steps.changesets.outputs.publishedPackages)[0].version }}|v${{ fromJson(steps.changesets.outputs.publishedPackages)[0].version }}> :rocket:"
90
90
  }
91
91
  }
92
92
  ]
package/.gitleaks.toml CHANGED
@@ -1,13 +1,13 @@
1
- # This file exists primarily to influence scheduled scans that Apollo runs of all repos in Apollo-managed orgs.
1
+ # This file exists primarily to influence scheduled scans that Apollo runs of all repos in Apollo-managed orgs.
2
2
  # This is an Apollo-Internal link, but more information about these scans is available here:
3
3
  # https://apollographql.atlassian.net/wiki/spaces/SecOps/pages/81330213/Everything+Static+Application+Security+Testing#Scheduled-Scans.1
4
- #
4
+ #
5
5
  # Apollo is using Gitleaks (https://github.com/gitleaks/gitleaks) to run these scans.
6
6
  # However, this file is not something that Gitleaks natively consumes. This file is an
7
7
  # Apollo-convention. Prior to scanning a repo, Apollo merges
8
8
  # our standard Gitleaks configuration (which is largely just the Gitleaks-default config) with
9
9
  # this file if it exists in a repo. The combined config is then used to scan a repo.
10
- #
10
+ #
11
11
  # We did this because the natively-supported allowlisting functionality in Gitleaks didn't do everything we wanted
12
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
13
  # on which a false positive secret exists to allowlist it. (https://github.com/gitleaks/gitleaks#gitleaksignore).
@@ -24,3 +24,10 @@
24
24
  # See https://github.com/apollographql/vscode-graphql/blob/a905280c143991b3fd675f8b4c3a7da277ccf095/packages/apollo-language-server/src/engine/index.ts#L86
25
25
  "a905280c143991b3fd675f8b4c3a7da277ccf095"
26
26
  ]
27
+
28
+ [[ rules ]]
29
+ id = "private-key"
30
+ [ rules.allowlist ]
31
+ paths = [
32
+ '''sampleWorkspace/httpSchema/self-signed.key$''',
33
+ ]
package/.vscodeignore CHANGED
@@ -10,7 +10,6 @@ src
10
10
  .prettierrc
11
11
  .gitattributes
12
12
  codegen.yml
13
- graphql.configuration.json
14
13
  jest.*.ts
15
14
  jest.*.js
16
15
  package-lock.json
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 2.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#198](https://github.com/apollographql/vscode-graphql/pull/198) [`3bebbdc4`](https://github.com/apollographql/vscode-graphql/commit/3bebbdc40faf8f9d62d0709de3312d5cb629af15) Thanks [@phryneas](https://github.com/phryneas)! - Change syntax highlighting of graphql object fields from "string" to "variable".
8
+
9
+ - [#199](https://github.com/apollographql/vscode-graphql/pull/199) [`7c1172be`](https://github.com/apollographql/vscode-graphql/commit/7c1172be690488dbf0510c2d412cba502acd1468) Thanks [@phryneas](https://github.com/phryneas)! - Fix "Toggle Line Comment"
10
+
11
+ - [#190](https://github.com/apollographql/vscode-graphql/pull/190) [`ec1e9927`](https://github.com/apollographql/vscode-graphql/commit/ec1e9927a178e75cae21d795d47426f40bf9d27b) Thanks [@phryneas](https://github.com/phryneas)! - Fix a bug that prevented `skipSSLValidation` from working.
12
+
3
13
  ## 2.2.0
4
14
 
5
15
  ### Minor Changes
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vscode-apollo",
3
3
  "displayName": "Apollo GraphQL",
4
4
  "description": "Rich editor support for GraphQL client and server development that seamlessly integrates with the Apollo platform",
5
- "version": "2.2.0",
5
+ "version": "2.2.1",
6
6
  "referenceID": "87197759-7617-40d0-b32e-46d378e907c7",
7
7
  "author": "Apollo GraphQL <opensource@apollographql.com>",
8
8
  "license": "MIT",
@@ -54,6 +54,7 @@
54
54
  "lz-string": "1.5.0",
55
55
  "minimatch": "10.0.1",
56
56
  "moment": "2.30.1",
57
+ "undici": "6.19.8",
57
58
  "vscode-languageclient": "9.0.1",
58
59
  "vscode-languageserver": "9.0.1",
59
60
  "vscode-languageserver-textdocument": "1.0.12",
@@ -3,6 +3,8 @@ export default {
3
3
  service: {
4
4
  name: "httpSchema",
5
5
  url: "http://localhost:7096/graphql",
6
+ // url: "https://localhost:7097/graphql",
7
+ // skipSSLValidation: true,
6
8
  },
7
9
  },
8
10
  };
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDkzCCAnugAwIBAgIUVNlDGdat5znvwWhOEFQLq7BWzNwwDQYJKoZIhvcNAQEL
3
+ BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4
+ GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X
5
+ DTI0MDkwMjA4MTgwNloXDTM0MDgzMTA4MTgwNlowWTELMAkGA1UEBhMCQVUxEzAR
6
+ BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
7
+ IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
8
+ MIIBCgKCAQEAvHLw9Ey0WoRLxjVIajxVAT4za1pUQw3E9mtl57DPHDcdGWR56S9w
9
+ KPjmND5lrtALZ5K+EKqslJdPf6Uxzxpf6phVnwpFwq5hPeY/Gpm77HxpPiJ61Q9r
10
+ fsYnLtGXiZta0kbdrisALB+3QykEHOerDUF3wGiVYVcpDu7WF/WcLaF+zUlgf1gQ
11
+ RTa5B3HpdCk34LiKPm9IZpWRpgLC90ro+HP+nBo7FoLYwu+WiPxg49qWEUY8fk+d
12
+ TuJVdH7lf8GxcfM2oCzhBGpT5O/t6lqYBkgZvvY3YAERmAxg/OSeuUa6ChOMLK2T
13
+ +2MRLy7eLaaeTmPMFjjrzFODCA2/ekfGVwIDAQABo1MwUTAdBgNVHQ4EFgQUpEu/
14
+ mbpTwcOGdPZ8NhTl1e16G84wHwYDVR0jBBgwFoAUpEu/mbpTwcOGdPZ8NhTl1e16
15
+ G84wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAhfSAl9VFS+Fk
16
+ Wkmsl1ndoXvLWVDy36YepbNfXUeB+iwebIgdyZhNu6VdpcHsPNBuUV4wr4mgZ7PK
17
+ Ksp3kKdqTDTAfBzHNBiOK7QgGyrDQJa0/Nn8ifmS+TYYCOs4FnkOXCUFipXCCMaS
18
+ KzFYc9Ls4jtAxiSN58NmwxW9fqRHqwHW4o2Z/aNx4EnCEat0x4QcAqq/qfEodmjH
19
+ jI7/AKb4UE+yEcJnZSlUDdpM4zPM3FcjmY7JVyfd/CziywR7rHGbLz7XQcCkYyDv
20
+ 5xqz0Lvk0ZtOC73cFWS41qfh8lrt34CNPoG7EaPFf+tMwhvjNooDHMQCb8y1A0Y3
21
+ 2yaDZNbCbQ==
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8cvD0TLRahEvG
3
+ NUhqPFUBPjNrWlRDDcT2a2XnsM8cNx0ZZHnpL3Ao+OY0PmWu0Atnkr4QqqyUl09/
4
+ pTHPGl/qmFWfCkXCrmE95j8ambvsfGk+InrVD2t+xicu0ZeJm1rSRt2uKwAsH7dD
5
+ KQQc56sNQXfAaJVhVykO7tYX9ZwtoX7NSWB/WBBFNrkHcel0KTfguIo+b0hmlZGm
6
+ AsL3Suj4c/6cGjsWgtjC75aI/GDj2pYRRjx+T51O4lV0fuV/wbFx8zagLOEEalPk
7
+ 7+3qWpgGSBm+9jdgARGYDGD85J65RroKE4wsrZP7YxEvLt4tpp5OY8wWOOvMU4MI
8
+ Db96R8ZXAgMBAAECggEAGRrrnHLZi2jY2sDUyF5dlAr6zlWcKHYITtceSNWmXyO9
9
+ Ky8BChPen9QPgFdDCZ0VX94jQaooeqqGa0K71ijf2ADPq0ky46LX4+dYHHhC762K
10
+ rGiV2kDceROh5bFYvFAniHWWE8gOalJsAjT6eMqo4DJgEeXSPMO1UxQguSlofdrX
11
+ 9PIkRmsmQVmVh17V4RJhhW/qg8r75OwpM1uFTknikaXwd9Rw5/HZhW4hXP5EeM2x
12
+ rcaYtXudhUyG/AWCrRPpHdGGNpHPmpwKUw3uADYAb2Hicjswx34kmWAbcwVJMs8d
13
+ 3QR/4hyrJnVSgYAB8/5oiNsnvaF/sO6/9KkDFpF03QKBgQDxrVJznfA0xgeVTGxt
14
+ sLRhbsUyVn5tHteEdbvbTGLfl80Dayzlht9rTrjYXgQUevw40+chQW8LPEA8gmyM
15
+ oCyAMouk+DJ5rl75jQnQh1/pob+ReyFi7Jl4D6Ro8J6gP6nds+wZ/BN5WLNtd/KI
16
+ BMwi4fEyKjT7nKTVFNQlrZEG6wKBgQDHng2nFYbSEKv1lb5HabSxJ1bbTHld0lzI
17
+ tn5zEmZ9PW6jBM0UJMEmkPRAvzhGGnzbRM0hYhiZR1FBR9T6BCJb+1N0HfT0Xo2X
18
+ MTOuz8auLRtH73SCRbRoxVbz+TFmLVQuwAXdwIT+p4AgEqoJ+QyMKwuwr70AGZmm
19
+ SkL08Bp7RQKBgQDYZfOgJtmAx5jerFGiXkkFvSPBkQUfPDCKIMmW8WzO/KPL3dmT
20
+ pBLFiPWmd3h7xiu1zrf0ZRzDGK4EAFymBn4SRDAaBUtc/S95kDoriCvvjK912qTo
21
+ aSZ6BLeYZ2wB3T+CjqpoEfh1/WCcMnzuIi2PRnSsEHLkoTxOt5nGKwXjBQKBgDve
22
+ o6mhQzZt2aVmrBMvGQqpCdvsK9p/5WQtl+9bbXHSowQxxHBuNaAjiZ6Bu5cLCreZ
23
+ Aw0oJsiSI0S5Dp+N7eA4mOcStQ017rGSCDY+CxDiZnRE1WTdEyb5SQMTkkVbAwyi
24
+ ex/vRfQ6uKrl7infkGvZ3T+49a65/uNpEnv0J30hAoGBAJwhlCGf3BhMPrXjXGsp
25
+ qxtCAbnaARErq0cI/nP6EKv8U0zOte09j/KKqFhckzsN3Df+P7dSuciIbFEDFY8Y
26
+ aWVRMDF/owMo7qrb/Hyvt72gRtRAeypN1Zf7Uy7JtP7PMqdvMynK0xSdrGAl4UCV
27
+ 6AOSsKQotsgA2R1PKV89Rn2R
28
+ -----END PRIVATE KEY-----
@@ -1,19 +1,43 @@
1
1
  // @ts-check
2
- const http = require("http");
3
2
  const {
4
3
  parseRequestParams,
5
4
  createHandler,
6
5
  } = require("graphql-http/lib/use/http");
7
6
  const { buildSchema } = require("graphql");
8
7
  const { Trie } = require("@wry/trie");
8
+ const { readFileSync } = require("fs");
9
+ const { join } = require("path");
9
10
 
10
- function runMockServer(
11
+ async function runMockServer(
11
12
  /** @type {number} */ port,
12
- onStart = (/** @type {number} */ port) => {},
13
+ useSelfSignedCert = false,
14
+ onStart = (/** @type {string} */ baseUri) => {},
13
15
  ) {
14
16
  const mocks = new Trie(false);
15
17
 
16
- const server = http.createServer(async (req, res) => {
18
+ /**
19
+ *
20
+ * @param {import('node:http').RequestListener} listener
21
+ * @returns
22
+ */
23
+ function createServer(listener) {
24
+ if (useSelfSignedCert) {
25
+ return require("node:https").createServer(
26
+ {
27
+ key: readFileSync(
28
+ join(__dirname, "../../sampleWorkspace/httpSchema/self-signed.key"),
29
+ ),
30
+ cert: readFileSync(
31
+ join(__dirname, "../../sampleWorkspace/httpSchema/self-signed.crt"),
32
+ ),
33
+ },
34
+ listener,
35
+ );
36
+ }
37
+ return require("node:http").createServer(listener);
38
+ }
39
+
40
+ const server = createServer(async (req, res) => {
17
41
  if (req.url === "/apollo") {
18
42
  if (req.method === "POST") {
19
43
  await handleApolloPost(req, res);
@@ -33,8 +57,9 @@ function runMockServer(
33
57
 
34
58
  console.log("Starting server...");
35
59
  server.listen(port);
36
- onStart(port);
37
- console.log(`Server ready at: http://localhost:${port}`);
60
+ const baseUri = `${useSelfSignedCert ? "https" : "http"}://localhost:${port}`;
61
+ await onStart(baseUri);
62
+ console.log(`Server ready at: ${baseUri}`);
38
63
  return {
39
64
  [Symbol.dispose]() {
40
65
  console.log("Closing server...");
@@ -45,8 +70,8 @@ function runMockServer(
45
70
 
46
71
  /**
47
72
  * Mock GraphQL Endpoint Handler
48
- * @param {http.IncomingMessage} req
49
- * @param {http.ServerResponse} res
73
+ * @param {import('node:http').IncomingMessage} req
74
+ * @param {import('node:http').ServerResponse} res
50
75
  */
51
76
  async function handleApolloPost(req, res) {
52
77
  const { operationName, variables } =
@@ -79,8 +104,8 @@ function runMockServer(
79
104
 
80
105
  /**
81
106
  * Handler to accept new GraphQL Mocks
82
- * @param {http.IncomingMessage} req
83
- * @param {http.ServerResponse} res
107
+ * @param {import('node:http').IncomingMessage} req
108
+ * @param {import('node:http').ServerResponse} res
84
109
  */
85
110
  async function handleApolloPut(req, res) {
86
111
  const body = await new Promise((resolve) => {
@@ -111,7 +136,8 @@ const schemaHandler = createHandler({
111
136
  });
112
137
 
113
138
  if (require.main === module) {
114
- runMockServer(7096, require("./mocks.js").loadDefaultMocks);
139
+ runMockServer(7096, false, require("./mocks.js").loadDefaultMocks);
140
+ runMockServer(7097, true, require("./mocks.js").loadDefaultMocks);
115
141
  }
116
142
 
117
143
  module.exports.runMockServer = runMockServer;
@@ -1,26 +1,30 @@
1
1
  // @ts-check
2
-
3
- async function loadDefaultMocks(/** @type {number} */ port) {
4
- await sendMock(port, FrontendUrlRoot);
5
- await sendMock(port, SchemaTagsAndFieldStats);
6
- await sendMock(port, GetSchemaByTag);
2
+ async function loadDefaultMocks(/** @type {string} */ baseUri) {
3
+ await sendMock(baseUri, FrontendUrlRoot);
4
+ await sendMock(baseUri, SchemaTagsAndFieldStats);
5
+ await sendMock(baseUri, GetSchemaByTag);
7
6
  }
8
7
 
9
8
  function sendMock(
10
- /** @type {number} */ port,
9
+ /** @type {string} */ baseUri,
11
10
  /** @type { { operationName: string, variables: Record<string, string>, response: unknown }} */ {
12
11
  operationName,
13
12
  variables,
14
13
  response,
15
14
  },
16
15
  ) {
17
- return fetch(`http://localhost:${port}/apollo`, {
16
+ return require("undici").fetch(`${baseUri}/apollo`, {
18
17
  method: "PUT",
19
18
  body: JSON.stringify({
20
19
  operationName,
21
20
  variables,
22
21
  response,
23
22
  }),
23
+ dispatcher: new (require("undici").Agent)({
24
+ connect: {
25
+ rejectUnauthorized: false,
26
+ },
27
+ }),
24
28
  });
25
29
  }
26
30
 
@@ -5,7 +5,7 @@ const { runMockServer } = require("./mockServer.js");
5
5
  const { loadDefaultMocks } = require("./mocks.js");
6
6
 
7
7
  async function main() {
8
- let disposable;
8
+ const disposables = /**{@type Disposable[]}*/ [];
9
9
  try {
10
10
  // The folder containing the Extension Manifest package.json
11
11
  // Passed to `--extensionDevelopmentPath`
@@ -18,8 +18,12 @@ async function main() {
18
18
  const TEST_PORT = 7096;
19
19
  process.env.APOLLO_ENGINE_ENDPOINT = "http://localhost:7096/apollo";
20
20
  process.env.MOCK_SERVER_PORT = String(TEST_PORT);
21
- disposable = runMockServer(TEST_PORT);
22
- await loadDefaultMocks(TEST_PORT);
21
+ disposables.push(
22
+ ...(await Promise.all([
23
+ runMockServer(TEST_PORT, false, loadDefaultMocks),
24
+ runMockServer(TEST_PORT + 1, true, loadDefaultMocks),
25
+ ])),
26
+ );
23
27
  // Download VS Code, unzip it and run the integration test
24
28
  const exitCode = await runTests({
25
29
  extensionDevelopmentPath,
@@ -35,9 +39,7 @@ async function main() {
35
39
  console.error("Failed to run tests");
36
40
  process.exit(1);
37
41
  } finally {
38
- if (disposable) {
39
- disposable[Symbol.dispose]();
40
- }
42
+ disposables.forEach((d) => d[Symbol.dispose]());
41
43
  }
42
44
  }
43
45
 
@@ -37,9 +37,10 @@ Get detailed profile information about the current user (including the current u
37
37
  });
38
38
 
39
39
  test("wrong token", async () => {
40
+ const baseUri = `http://localhost:${mockPort}`;
40
41
  try {
41
- await mocks.sendMock(mockPort, mocks.GetSchemaByTag_WRONG_TOKEN);
42
- await mocks.sendMock(mockPort, mocks.SchemaTagsAndFieldStats_WRONG_TOKEN);
42
+ await mocks.sendMock(baseUri, mocks.GetSchemaByTag_WRONG_TOKEN);
43
+ await mocks.sendMock(baseUri, mocks.SchemaTagsAndFieldStats_WRONG_TOKEN);
43
44
 
44
45
  const ext = getExtension();
45
46
  ext.outputChannel.clear();
@@ -59,7 +60,7 @@ Invalid credentials provided
59
60
  at new ApolloError`.trim(),
60
61
  );
61
62
  } finally {
62
- await mocks.loadDefaultMocks(mockPort);
63
+ await mocks.loadDefaultMocks(baseUri);
63
64
  await reloadService();
64
65
  }
65
66
  });
@@ -110,12 +110,12 @@ const roverConfig = z.object({
110
110
  .preprocess((value) => {
111
111
  if (value !== undefined) return value;
112
112
  const configPath = contextStore.getStore()?.configPath!;
113
- const supergraphConfig = join(configPath, "supergraph.yml");
113
+ const supergraphConfig = join(configPath, "supergraph.yaml");
114
114
  return existsSync(supergraphConfig) ? supergraphConfig : undefined;
115
115
  }, z.string().nullable().optional())
116
116
  .describe(
117
- "The path to your `supergraph.yml` file. \n" +
118
- "Defaults to a `supergraph.yml` in the folder of your `apollo.config.js`, if there is one.",
117
+ "The path to your `supergraph.yaml` file. \n" +
118
+ "Defaults to a `supergraph.yaml` in the folder of your `apollo.config.js`, if there is one.",
119
119
  ),
120
120
  extraArgs: z
121
121
  .array(z.string())
@@ -99,10 +99,17 @@ export class DocumentSynchronization {
99
99
  private pendingDocumentChanges = new Map<DocumentUri, TextDocument>();
100
100
  private knownFiles = new Map<
101
101
  DocumentUri,
102
- {
103
- full: TextDocument;
104
- parts: ReadonlyArray<FilePart>;
105
- }
102
+ | {
103
+ source: "editor";
104
+ full: TextDocument;
105
+ parts: ReadonlyArray<FilePart>;
106
+ }
107
+ | {
108
+ source: "lsp";
109
+ full: Pick<TextDocument, "uri">;
110
+ parts?: undefined;
111
+ diagnostics?: Diagnostic[];
112
+ }
106
113
  >();
107
114
 
108
115
  constructor(
@@ -158,7 +165,11 @@ export class DocumentSynchronization {
158
165
  const newObj = Object.fromEntries(
159
166
  newParts.map((p) => [p.fractionalIndex, p]),
160
167
  );
161
- this.knownFiles.set(document.uri, { full: document, parts: newParts });
168
+ this.knownFiles.set(document.uri, {
169
+ source: "editor",
170
+ full: document,
171
+ parts: newParts,
172
+ });
162
173
 
163
174
  for (const newPart of newParts) {
164
175
  const previousPart = previousObj[newPart.fractionalIndex];
@@ -198,7 +209,9 @@ export class DocumentSynchronization {
198
209
 
199
210
  async resendAllDocuments() {
200
211
  for (const file of this.knownFiles.values()) {
201
- await this.sendDocumentChanges(file.full, []);
212
+ if (file.source === "editor") {
213
+ await this.sendDocumentChanges(file.full, []);
214
+ }
202
215
  }
203
216
  }
204
217
 
@@ -208,7 +221,7 @@ export class DocumentSynchronization {
208
221
  this.documentDidChange(params.document);
209
222
  };
210
223
 
211
- onDidCloseTextDocument: NonNullable<GraphQLProject["onDidClose"]> = (
224
+ onDidCloseTextDocument: NonNullable<GraphQLProject["onDidClose"]> = async (
212
225
  params,
213
226
  ) => {
214
227
  const known = this.knownFiles.get(params.document.uri);
@@ -216,15 +229,15 @@ export class DocumentSynchronization {
216
229
  return;
217
230
  }
218
231
  this.knownFiles.delete(params.document.uri);
219
- return Promise.all(
220
- known.parts.map((part) =>
221
- this.sendNotification(DidCloseTextDocumentNotification.type, {
232
+ if (known.source === "editor") {
233
+ for (const part of known.parts) {
234
+ await this.sendNotification(DidCloseTextDocumentNotification.type, {
222
235
  textDocument: {
223
236
  uri: getUri(known.full, part),
224
237
  },
225
- }),
226
- ),
227
- );
238
+ });
239
+ }
240
+ }
228
241
  };
229
242
 
230
243
  async documentDidChange(document: TextDocument) {
@@ -254,7 +267,7 @@ export class DocumentSynchronization {
254
267
  ): Promise<T | undefined> {
255
268
  await this.synchronizedWithDocument(positionParams.textDocument.uri);
256
269
  const found = this.knownFiles.get(positionParams.textDocument.uri);
257
- if (!found) {
270
+ if (!found || found.source !== "editor") {
258
271
  return;
259
272
  }
260
273
  const match = findContainedSourceAndPosition(
@@ -274,11 +287,14 @@ export class DocumentSynchronization {
274
287
  handlePartDiagnostics(params: PublishDiagnosticsParams) {
275
288
  DEBUG && console.log("Received diagnostics", params);
276
289
  const uriDetails = splitUri(params.uri);
277
- if (!uriDetails) {
278
- return;
279
- }
280
290
  const found = this.knownFiles.get(uriDetails.uri);
281
- if (!found) {
291
+ if (!found || found.source === "lsp") {
292
+ this.knownFiles.set(uriDetails.uri, {
293
+ source: "lsp",
294
+ full: { uri: uriDetails.uri },
295
+ diagnostics: params.diagnostics,
296
+ });
297
+ this.sendDiagnostics(params);
282
298
  return;
283
299
  }
284
300
  const part = found.parts.find(
@@ -304,13 +320,19 @@ export class DocumentSynchronization {
304
320
  }
305
321
 
306
322
  get openDocuments() {
307
- return [...this.knownFiles.values()].map((f) => f.full);
323
+ return [...this.knownFiles.values()]
324
+ .filter((f) => f.source === "editor")
325
+ .map((f) => f.full);
308
326
  }
309
327
 
310
328
  clearAllDiagnostics() {
311
329
  for (const file of this.knownFiles.values()) {
312
- for (const part of file.parts) {
313
- part.diagnostics = [];
330
+ if (file.source === "editor") {
331
+ for (const part of file.parts) {
332
+ part.diagnostics = [];
333
+ }
334
+ } else {
335
+ file.diagnostics = [];
314
336
  }
315
337
  this.sendDiagnostics({ uri: file.full.uri, diagnostics: [] });
316
338
  }
@@ -332,7 +354,7 @@ export class DocumentSynchronization {
332
354
  ): Promise<SemanticTokens | null> {
333
355
  await this.synchronizedWithDocument(params.textDocument.uri);
334
356
  const found = this.knownFiles.get(params.textDocument.uri);
335
- if (!found) {
357
+ if (!found || found.source !== "editor") {
336
358
  return null;
337
359
  }
338
360
  const allParts = await Promise.all(
@@ -17,7 +17,16 @@ import { RemoteServiceConfig } from "../../config";
17
17
  import { GraphQLSchemaProvider, SchemaChangeUnsubscribeHandler } from "./base";
18
18
  import { Debug } from "../../utilities";
19
19
  import { isString } from "util";
20
-
20
+ import { fetch as undiciFetch, Agent } from "undici";
21
+
22
+ const skipSSLValidationFetchOptions = {
23
+ // see https://github.com/nodejs/undici/issues/1489#issuecomment-1543856261
24
+ dispatcher: new Agent({
25
+ connect: {
26
+ rejectUnauthorized: false,
27
+ },
28
+ }),
29
+ } satisfies import("undici").RequestInit;
21
30
  export class EndpointSchemaProvider implements GraphQLSchemaProvider {
22
31
  private schema?: GraphQLSchema;
23
32
  private federatedServiceSDL?: string;
@@ -28,11 +37,11 @@ export class EndpointSchemaProvider implements GraphQLSchemaProvider {
28
37
  const { skipSSLValidation, url, headers } = this.config;
29
38
  const options: HttpOptions = {
30
39
  uri: url,
40
+ fetch: undiciFetch as typeof fetch,
31
41
  };
42
+
32
43
  if (url.startsWith("https:") && skipSSLValidation) {
33
- options.fetchOptions = {
34
- agent: new HTTPSAgent({ rejectUnauthorized: false }),
35
- };
44
+ options.fetchOptions = skipSSLValidationFetchOptions;
36
45
  }
37
46
 
38
47
  const { data, errors } = (await toPromise(
@@ -92,12 +101,10 @@ export class EndpointSchemaProvider implements GraphQLSchemaProvider {
92
101
  const { skipSSLValidation, url, headers } = this.config;
93
102
  const options: HttpOptions = {
94
103
  uri: url,
95
- fetch,
104
+ fetch: undiciFetch as typeof fetch,
96
105
  };
97
106
  if (url.startsWith("https:") && skipSSLValidation) {
98
- options.fetchOptions = {
99
- agent: new HTTPSAgent({ rejectUnauthorized: false }),
100
- };
107
+ options.fetchOptions = skipSSLValidationFetchOptions;
101
108
  }
102
109
 
103
110
  const getFederationInfoQuery = `
@@ -601,8 +601,8 @@
601
601
  "graphql-object-field": {
602
602
  "match": "\\s*(([_A-Za-z][_0-9A-Za-z]*))\\s*(:)",
603
603
  "captures": {
604
- "1": { "name": "constant.object.key.graphql" },
605
- "2": { "name": "string.unquoted.graphql" },
604
+ "1": { "name": "string.unquoted.graphql" },
605
+ "2": { "name": "variable.object.key.graphql" },
606
606
  "3": { "name": "punctuation.graphql" }
607
607
  }
608
608
  },