vscode-apollo 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/E2E.yml +1 -1
- package/.nvmrc +1 -1
- package/.vscodeignore +3 -0
- package/CHANGELOG.md +6 -0
- package/images/apollo.svg +16 -0
- package/package.json +54 -3
- package/sampleWorkspace/sampleWorkspace.code-workspace +4 -1
- package/src/build.js +4 -0
- package/src/debug.ts +39 -0
- package/src/devtools/DevToolsViewProvider.ts +182 -0
- package/src/devtools/server.ts +86 -0
- package/src/extension.ts +80 -1
- package/start-ac.mjs +60 -0
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
- version: "stable"
|
|
17
17
|
os: "windows-latest"
|
|
18
18
|
steps:
|
|
19
|
-
- run: sudo apt update && sudo apt install -y
|
|
19
|
+
- run: sudo apt update && sudo apt install -y libasound2t64 libgbm1 libgtk-3-0 libnss3 xvfb expect
|
|
20
20
|
if: runner.os == 'Linux'
|
|
21
21
|
- uses: actions/checkout@v4
|
|
22
22
|
- uses: actions/setup-node@v4
|
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
22
|
package/.vscodeignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 2.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#188](https://github.com/apollographql/vscode-graphql/pull/188) [`595784f0`](https://github.com/apollographql/vscode-graphql/commit/595784f057de18d987768fa1aaa8c37a5fa802c7) Thanks [@phryneas](https://github.com/phryneas)! - Adds experimental integration of the Apollo Client DevTools
|
|
8
|
+
|
|
3
9
|
## 2.4.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<style>
|
|
3
|
+
g {
|
|
4
|
+
fill: black;
|
|
5
|
+
}
|
|
6
|
+
@media (prefers-color-scheme: dark) {
|
|
7
|
+
g {
|
|
8
|
+
fill: white;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
</style>
|
|
12
|
+
<g>
|
|
13
|
+
<polygon points="112.246 49 88.003 49 53 139.848 74.927 139.848 80.648 124.455 113.724 124.455 107.735 107.431 85.961 107.431 100.125 68.34 125.324 139.848 147.252 139.848"></polygon>
|
|
14
|
+
<path d="M196.313,73.038 C196.254,72.728 196.17,72.428 196.057,72.141 C196.03,72.041 195.937,71.856 195.937,71.856 C195.148,70.138 193.414,68.942 191.399,68.942 C188.637,68.942 186.399,71.181 186.399,73.942 C186.399,74.504 186.497,75.042 186.667,75.545 L186.653,75.55 C188.859,83.407 189.999,91.615 189.999,100.001 C189.999,124.04 180.637,146.642 163.64,163.641 C146.641,180.641 124.04,190.001 100,190.001 C75.961,190.001 53.358,180.639 36.361,163.641 C19.36,146.642 10,124.04 10,100.001 C10,75.961 19.362,53.36 36.361,36.361 C53.358,19.361 75.961,10.001 100,10.001 C121.466,10.001 141.781,17.471 157.987,31.174 C157.443,32.56 157.139,34.068 157.139,35.648 C157.139,42.399 162.611,47.869 169.363,47.869 C176.113,47.869 181.586,42.399 181.586,35.648 C181.586,28.897 176.113,23.424 169.363,23.424 C167.89,23.424 166.479,23.684 165.171,24.161 C147.666,9.107 124.9,0 100,0 C44.771,0 0,44.772 0,100.001 C0,155.23 44.771,200.002 100,200.002 C155.229,200.002 200,155.231 200,100.001 C200,90.659 198.709,81.617 196.313,73.038 Z"></path>
|
|
15
|
+
</g>
|
|
16
|
+
</svg>
|
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.
|
|
5
|
+
"version": "2.5.0",
|
|
6
6
|
"referenceID": "87197759-7617-40d0-b32e-46d378e907c7",
|
|
7
7
|
"author": "Apollo GraphQL <opensource@apollographql.com>",
|
|
8
8
|
"license": "MIT",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"vscode": "^1.90.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@apollo/client": "3.
|
|
40
|
+
"@apollo/client": "3.12.2",
|
|
41
|
+
"@apollo/client-devtools-vscode": "^4.19.0",
|
|
41
42
|
"@apollo/subgraph": "2.9.1",
|
|
42
43
|
"@graphql-tools/schema": "10.0.6",
|
|
43
44
|
"@wry/equality": "0.5.7",
|
|
@@ -62,6 +63,7 @@
|
|
|
62
63
|
"vscode-languageserver-textdocument": "1.0.12",
|
|
63
64
|
"vscode-uri": "3.0.8",
|
|
64
65
|
"which": "4.0.0",
|
|
66
|
+
"ws": "8.18.0",
|
|
65
67
|
"zod": "3.23.8",
|
|
66
68
|
"zod-validation-error": "3.4.0"
|
|
67
69
|
},
|
|
@@ -138,6 +140,23 @@
|
|
|
138
140
|
"default": true,
|
|
139
141
|
"markdownDescription": "Show a \"Run in Studio\" button to the right of Operation Signatures.",
|
|
140
142
|
"scope": "window"
|
|
143
|
+
},
|
|
144
|
+
"apollographql.devTools.showPanel": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"enum": [
|
|
147
|
+
"always",
|
|
148
|
+
"never",
|
|
149
|
+
"detect"
|
|
150
|
+
],
|
|
151
|
+
"default": "never",
|
|
152
|
+
"markdownDescription": "[Experimental Feature] If the Apollo Client DevTools panel should be shown. If set to `detect`, the panel will only be shown if a configuration file with a client project is found in the workspace.",
|
|
153
|
+
"scope": "window"
|
|
154
|
+
},
|
|
155
|
+
"apollographql.devTools.serverPort": {
|
|
156
|
+
"type": "number",
|
|
157
|
+
"default": 7095,
|
|
158
|
+
"markdownDescription": "The Apollo Client DevTools server port. The server will be started as soon as you start using the DevTools panels.",
|
|
159
|
+
"scope": "window"
|
|
141
160
|
}
|
|
142
161
|
}
|
|
143
162
|
},
|
|
@@ -279,8 +298,40 @@
|
|
|
279
298
|
"command": "apollographql/showStats",
|
|
280
299
|
"title": "Show Status",
|
|
281
300
|
"category": "Apollo"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"command": "apollographql/startDevToolsServer",
|
|
304
|
+
"title": "Start Apollo Client DevTools Server",
|
|
305
|
+
"category": "Apollo",
|
|
306
|
+
"when": "config.apollographql.devTools.showPanel=='always' || (config.apollographql.devTools.showPanel=='detect' && vscode-apollo.hasClientProject)"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"command": "apollographql/stopDevToolsServer",
|
|
310
|
+
"title": "Stop Apollo Client DevTools Server",
|
|
311
|
+
"category": "Apollo",
|
|
312
|
+
"when": "config.apollographql.devTools.showPanel=='always' || (config.apollographql.devTools.showPanel=='detect' && vscode-apollo.hasClientProject)"
|
|
282
313
|
}
|
|
283
|
-
]
|
|
314
|
+
],
|
|
315
|
+
"viewsContainers": {
|
|
316
|
+
"panel": [
|
|
317
|
+
{
|
|
318
|
+
"id": "client-devtools",
|
|
319
|
+
"title": "Apollo Client DevTools",
|
|
320
|
+
"icon": "images/apollo.svg"
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
"views": {
|
|
325
|
+
"client-devtools": [
|
|
326
|
+
{
|
|
327
|
+
"type": "webview",
|
|
328
|
+
"id": "vscode-apollo-client-devtools",
|
|
329
|
+
"name": "Apollo Client DevTools",
|
|
330
|
+
"icon": "images/apollo.svg",
|
|
331
|
+
"when": "config.apollographql.devTools.showPanel=='always' || (config.apollographql.devTools.showPanel=='detect' && vscode-apollo.hasClientProject)"
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
}
|
|
284
335
|
},
|
|
285
336
|
"galleryBanner": {
|
|
286
337
|
"color": "#1d127d",
|
package/src/build.js
CHANGED
|
@@ -11,6 +11,10 @@ async function main() {
|
|
|
11
11
|
entryPoints: [
|
|
12
12
|
"src/extension.ts",
|
|
13
13
|
"src/language-server/server.ts",
|
|
14
|
+
{
|
|
15
|
+
in: require.resolve("@apollo/client-devtools-vscode/panel"),
|
|
16
|
+
out: "panel",
|
|
17
|
+
},
|
|
14
18
|
"src/language-server/config/config.ts",
|
|
15
19
|
"src/language-server/config/cache-busting-resolver.js",
|
|
16
20
|
],
|
package/src/debug.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { OutputChannel } from "vscode";
|
|
2
|
+
import { TraceValues } from "vscode-languageclient";
|
|
3
|
+
import { format } from "node:util";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* for errors (and other logs in debug mode) we want to print
|
|
@@ -21,6 +23,21 @@ export class Debug {
|
|
|
21
23
|
this.outputConsole = outputConsole;
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
private static _traceLevel: Exclude<TraceValues, "compact"> = "off";
|
|
27
|
+
public static get traceLevel(): TraceValues {
|
|
28
|
+
return Debug._traceLevel;
|
|
29
|
+
}
|
|
30
|
+
public static set traceLevel(value: TraceValues | undefined) {
|
|
31
|
+
console.log("setting trace level to", value);
|
|
32
|
+
if (value === "compact") {
|
|
33
|
+
// we do not handle "compact" and it's not possible to set in settings, but it doesn't hurt to at least map
|
|
34
|
+
// it to another value
|
|
35
|
+
this._traceLevel = "messages";
|
|
36
|
+
} else {
|
|
37
|
+
this._traceLevel = value || "off";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
24
41
|
/**
|
|
25
42
|
* Displays an info message prefixed with [INFO]
|
|
26
43
|
*/
|
|
@@ -55,6 +72,28 @@ export class Debug {
|
|
|
55
72
|
this.outputConsole.appendLine(`[WARN] ${message}`);
|
|
56
73
|
}
|
|
57
74
|
|
|
75
|
+
public static traceMessage(
|
|
76
|
+
short: string,
|
|
77
|
+
verbose = short,
|
|
78
|
+
...verboseParams: any[]
|
|
79
|
+
) {
|
|
80
|
+
if (!this.outputConsole) return;
|
|
81
|
+
if (Debug.traceLevel === "verbose") {
|
|
82
|
+
this.outputConsole.appendLine(
|
|
83
|
+
`[Trace] ${format(verbose, ...verboseParams)}`,
|
|
84
|
+
);
|
|
85
|
+
} else if (Debug.traceLevel === "messages") {
|
|
86
|
+
this.outputConsole.appendLine(`[Trace] ${short}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public static traceVerbose(message: string, ...params: any[]) {
|
|
91
|
+
if (!this.outputConsole) return;
|
|
92
|
+
if (Debug.traceLevel === "verbose") {
|
|
93
|
+
this.outputConsole.appendLine(`[Trace] ${format(message, ...params)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
58
97
|
/**
|
|
59
98
|
* TODO: enable error reporting and telemetry
|
|
60
99
|
*/
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as vscode from "vscode";
|
|
2
|
+
import { devtoolsEvents, sendToDevTools, serverState } from "./server";
|
|
3
|
+
|
|
4
|
+
type ActorMessage = { type: "actor"; message: unknown };
|
|
5
|
+
|
|
6
|
+
export function isActorMessage(message: any): message is ActorMessage {
|
|
7
|
+
return message && message.type === "actor";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type DevToolsOpenCommandMessage = {
|
|
11
|
+
type: "vscode:executeCommand";
|
|
12
|
+
command: string;
|
|
13
|
+
arguments?: unknown[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function isDevToolsExecuteCommandMessage(
|
|
17
|
+
message: any,
|
|
18
|
+
): message is DevToolsOpenCommandMessage {
|
|
19
|
+
return message && message.type === "vscode:executeCommand";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type DevToolsOpenExternalMessage = {
|
|
23
|
+
type: "vscode:openExternal";
|
|
24
|
+
uri: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function isDevToolsOpenExternalMessage(
|
|
28
|
+
message: any,
|
|
29
|
+
): message is DevToolsOpenExternalMessage {
|
|
30
|
+
return message && message.type === "vscode:openExternal";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class DevToolsViewProvider implements vscode.WebviewViewProvider {
|
|
34
|
+
public static readonly viewType = "vscode-apollo-client-devtools";
|
|
35
|
+
|
|
36
|
+
constructor(private readonly _extensionUri: vscode.Uri) {}
|
|
37
|
+
|
|
38
|
+
async resolveWebviewView(
|
|
39
|
+
panel: vscode.WebviewView,
|
|
40
|
+
context: vscode.WebviewViewResolveContext,
|
|
41
|
+
token: vscode.CancellationToken,
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
vscode.commands.executeCommand("apollographql/startDevToolsServer");
|
|
44
|
+
panel.webview.options = {
|
|
45
|
+
enableScripts: true,
|
|
46
|
+
localResourceRoots: [this._extensionUri],
|
|
47
|
+
};
|
|
48
|
+
panel.webview.html = DevToolsViewProvider._getHtmlForWebview(
|
|
49
|
+
panel.webview,
|
|
50
|
+
this._extensionUri,
|
|
51
|
+
);
|
|
52
|
+
const panelDisposables: vscode.Disposable[] = [];
|
|
53
|
+
panel.webview.onDidReceiveMessage(
|
|
54
|
+
(data) => {
|
|
55
|
+
if (data.source === "apollo-client-devtools") {
|
|
56
|
+
devtoolsEvents.emit("fromDevTools", data);
|
|
57
|
+
}
|
|
58
|
+
if (data.source === "vscode-panel") {
|
|
59
|
+
if (data.type === "mounted") {
|
|
60
|
+
sendToDevTools({
|
|
61
|
+
type: "initializePanel",
|
|
62
|
+
initialContext: {
|
|
63
|
+
port:
|
|
64
|
+
serverState?.port ||
|
|
65
|
+
vscode.workspace
|
|
66
|
+
.getConfiguration("apollographql")
|
|
67
|
+
.get("devTools.serverPort", 0),
|
|
68
|
+
listening: !!serverState?.port,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
this,
|
|
75
|
+
panelDisposables,
|
|
76
|
+
);
|
|
77
|
+
function forwardToDevTools(data: unknown) {
|
|
78
|
+
panel.webview.postMessage(data);
|
|
79
|
+
}
|
|
80
|
+
devtoolsEvents.addListener("toDevTools", forwardToDevTools);
|
|
81
|
+
panel.onDidDispose(() => {
|
|
82
|
+
devtoolsEvents.removeListener("toDevTools", forwardToDevTools);
|
|
83
|
+
for (const disposable of panelDisposables) {
|
|
84
|
+
disposable.dispose();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private static _getHtmlForWebview(
|
|
90
|
+
webview: vscode.Webview,
|
|
91
|
+
extensionUri: vscode.Uri,
|
|
92
|
+
) {
|
|
93
|
+
// Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
|
|
94
|
+
const scriptUri = webview.asWebviewUri(
|
|
95
|
+
vscode.Uri.joinPath(extensionUri, "lib", "panel.js"),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// Use a nonce to only allow a specific script to be run.
|
|
99
|
+
const nonce = getNonce();
|
|
100
|
+
|
|
101
|
+
return `
|
|
102
|
+
<!doctype html>
|
|
103
|
+
<html lang="en">
|
|
104
|
+
<head>
|
|
105
|
+
<meta charset="utf-8" />
|
|
106
|
+
|
|
107
|
+
<!--
|
|
108
|
+
Use a content security policy to only allow loading images from https or from our extension directory,
|
|
109
|
+
and only allow scripts that have a specific nonce.
|
|
110
|
+
-->
|
|
111
|
+
<meta http-equiv="Content-Security-Policy" content="
|
|
112
|
+
default-src 'none';
|
|
113
|
+
style-src ${webview.cspSource} https://fonts.googleapis.com 'unsafe-inline';
|
|
114
|
+
font-src ${webview.cspSource} https://fonts.gstatic.com;
|
|
115
|
+
img-src ${webview.cspSource} https:;
|
|
116
|
+
connect-src ${webview.cspSource} https://*.github.com;
|
|
117
|
+
script-src 'nonce-${nonce}';
|
|
118
|
+
frame-src https://*.apollographql.com/;
|
|
119
|
+
">
|
|
120
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
121
|
+
|
|
122
|
+
<title>Apollo Client DevTools</title>
|
|
123
|
+
<style>
|
|
124
|
+
html,
|
|
125
|
+
body {
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
font-size: var(--vscode-font-size);
|
|
128
|
+
}
|
|
129
|
+
::-webkit-scrollbar {
|
|
130
|
+
display: none;
|
|
131
|
+
}
|
|
132
|
+
#devtools {
|
|
133
|
+
width: 100vw;
|
|
134
|
+
height: 100vh;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
137
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
138
|
+
<link
|
|
139
|
+
href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Inter:wght@400;500;600;700&display=swap"
|
|
140
|
+
rel="stylesheet"
|
|
141
|
+
/>
|
|
142
|
+
</head>
|
|
143
|
+
<body class="text-primary dark:text-primary-dark">
|
|
144
|
+
<div id="devtools"></div>
|
|
145
|
+
<script nonce="${nonce}">
|
|
146
|
+
const vscode = acquireVsCodeApi();
|
|
147
|
+
try {
|
|
148
|
+
// remove VSCode default styles
|
|
149
|
+
_defaultStyles.remove();
|
|
150
|
+
} catch {}
|
|
151
|
+
window.originalPostMessage = window.postMessage;
|
|
152
|
+
window.postMessage = function wrapPostMessage (...args) {
|
|
153
|
+
if (args.length>1 && args[1].startsWith("vscode-webview://")) {
|
|
154
|
+
return window.originalPostMessage(...args);
|
|
155
|
+
}
|
|
156
|
+
return vscode.postMessage(...args);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// window.addEventListener("message", (event) => { console.debug(event); });
|
|
160
|
+
</script>
|
|
161
|
+
<script nonce="${nonce}" src="${scriptUri}"></script>
|
|
162
|
+
<script nonce="${nonce}">
|
|
163
|
+
window.postMessage({
|
|
164
|
+
source: "vscode-panel",
|
|
165
|
+
type: "mounted",
|
|
166
|
+
});
|
|
167
|
+
</script>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function getNonce() {
|
|
175
|
+
let text = "";
|
|
176
|
+
const possible =
|
|
177
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
178
|
+
for (let i = 0; i < 32; i++) {
|
|
179
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
180
|
+
}
|
|
181
|
+
return text;
|
|
182
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
|
+
import { Disposable } from "vscode";
|
|
3
|
+
import { runServer } from "@apollo/client-devtools-vscode/vscode-server";
|
|
4
|
+
import { Debug } from "../debug";
|
|
5
|
+
import { EventEmitter } from "node:events";
|
|
6
|
+
|
|
7
|
+
export const devtoolsEvents = new EventEmitter<{
|
|
8
|
+
toDevTools: [unknown];
|
|
9
|
+
fromDevTools: [unknown];
|
|
10
|
+
}>();
|
|
11
|
+
devtoolsEvents.addListener("toDevTools", (msg) => {
|
|
12
|
+
Debug.traceMessage(
|
|
13
|
+
`WS > DevTools: ${
|
|
14
|
+
msg && typeof msg === "object" && "type" in msg ? msg.type : "unknown"
|
|
15
|
+
}`,
|
|
16
|
+
"WS > DevTools: %o",
|
|
17
|
+
msg,
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
devtoolsEvents.addListener("fromDevTools", (msg) => {
|
|
21
|
+
Debug.traceMessage(
|
|
22
|
+
`DevTools > WS: ${
|
|
23
|
+
msg && typeof msg === "object" && "type" in msg ? msg.type : "unknown"
|
|
24
|
+
}`,
|
|
25
|
+
"DevTools > WS: %o",
|
|
26
|
+
msg,
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
let id = 1;
|
|
31
|
+
|
|
32
|
+
export function sendToDevTools(message: unknown) {
|
|
33
|
+
devtoolsEvents.emit("toDevTools", {
|
|
34
|
+
id: `vscode-${id++}`,
|
|
35
|
+
source: "apollo-client-devtools",
|
|
36
|
+
type: "actor",
|
|
37
|
+
message,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export let serverState:
|
|
42
|
+
| { port: false | number; disposable: Disposable }
|
|
43
|
+
| undefined = undefined;
|
|
44
|
+
|
|
45
|
+
export function startServer(port: number) {
|
|
46
|
+
const state = {
|
|
47
|
+
port: false as false | number,
|
|
48
|
+
disposable: new Disposable(() => {
|
|
49
|
+
if (wss) {
|
|
50
|
+
wss.close();
|
|
51
|
+
wss = null;
|
|
52
|
+
}
|
|
53
|
+
if (serverState === state) {
|
|
54
|
+
serverState = undefined;
|
|
55
|
+
}
|
|
56
|
+
sendToDevTools({ type: "port.changed", port, listening: false });
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (serverState?.port === port) {
|
|
61
|
+
// nothing to do
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// changing port, stop the old server
|
|
65
|
+
serverState?.disposable.dispose();
|
|
66
|
+
serverState = state;
|
|
67
|
+
let wss: WebSocketServer | null = new WebSocketServer({ port });
|
|
68
|
+
wss.on("listening", () => {
|
|
69
|
+
state.port = port;
|
|
70
|
+
sendToDevTools({ type: "port.changed", port, listening: true });
|
|
71
|
+
});
|
|
72
|
+
wss.on("close", () => {
|
|
73
|
+
state.disposable.dispose();
|
|
74
|
+
});
|
|
75
|
+
runServer(wss, {
|
|
76
|
+
addListener: (listener) => {
|
|
77
|
+
devtoolsEvents.addListener("fromDevTools", listener);
|
|
78
|
+
return () => {
|
|
79
|
+
devtoolsEvents.removeListener("fromDevTools", listener);
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
postMessage: (message) => {
|
|
83
|
+
devtoolsEvents.emit("toDevTools", message);
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
package/src/extension.ts
CHANGED
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
DecorationOptions,
|
|
9
9
|
commands,
|
|
10
10
|
QuickPickItem,
|
|
11
|
-
Disposable,
|
|
12
11
|
OutputChannel,
|
|
13
12
|
MarkdownString,
|
|
14
13
|
Range,
|
|
14
|
+
env,
|
|
15
15
|
} from "vscode";
|
|
16
16
|
import StatusBar from "./statusBar";
|
|
17
17
|
import { getLanguageServerClient } from "./languageServerClient";
|
|
@@ -27,6 +27,13 @@ import {
|
|
|
27
27
|
printStatsToClientOutputChannel,
|
|
28
28
|
} from "./utils";
|
|
29
29
|
import { Debug } from "./debug";
|
|
30
|
+
import {
|
|
31
|
+
DevToolsViewProvider,
|
|
32
|
+
isActorMessage,
|
|
33
|
+
isDevToolsExecuteCommandMessage,
|
|
34
|
+
isDevToolsOpenExternalMessage,
|
|
35
|
+
} from "./devtools/DevToolsViewProvider";
|
|
36
|
+
import { devtoolsEvents, serverState, startServer } from "./devtools/server";
|
|
30
37
|
|
|
31
38
|
const { version } = require("../package.json");
|
|
32
39
|
|
|
@@ -157,6 +164,17 @@ export async function activate(
|
|
|
157
164
|
} else {
|
|
158
165
|
statusBar.showLoadedState({ hasActiveTextEditor });
|
|
159
166
|
}
|
|
167
|
+
|
|
168
|
+
const containsClientConfig = response.some(
|
|
169
|
+
(item) => item && !isError(item) && "client" in item,
|
|
170
|
+
);
|
|
171
|
+
if (containsClientConfig) {
|
|
172
|
+
commands.executeCommand(
|
|
173
|
+
"setContext",
|
|
174
|
+
"vscode-apollo.hasClientProject",
|
|
175
|
+
true,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
160
178
|
} else {
|
|
161
179
|
Debug.error(
|
|
162
180
|
`Invalid response type in message apollographql/configFilesFound:\n${JSON.stringify(
|
|
@@ -329,6 +347,67 @@ export async function activate(
|
|
|
329
347
|
},
|
|
330
348
|
});
|
|
331
349
|
|
|
350
|
+
const provider = new DevToolsViewProvider(context.extensionUri);
|
|
351
|
+
context.subscriptions.push(
|
|
352
|
+
window.registerWebviewViewProvider(DevToolsViewProvider.viewType, provider),
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
function devToolsEventListener(event: unknown) {
|
|
356
|
+
if (!isActorMessage(event)) return;
|
|
357
|
+
const message = event.message;
|
|
358
|
+
if (isDevToolsExecuteCommandMessage(message)) {
|
|
359
|
+
commands.executeCommand(message.command, ...(message.arguments || []));
|
|
360
|
+
}
|
|
361
|
+
if (isDevToolsOpenExternalMessage(message)) {
|
|
362
|
+
env.openExternal(
|
|
363
|
+
// if we `Uri.parse` here, we end up with something that somehow double-encodes some things like `#`
|
|
364
|
+
// interestingly enough, the implementation of `openExternal` also allows for strings to be passed in
|
|
365
|
+
// directly, and that works - so we just pass in the string directly
|
|
366
|
+
message.uri as any as Uri,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
devtoolsEvents.addListener("fromDevTools", devToolsEventListener);
|
|
371
|
+
context.subscriptions.push({
|
|
372
|
+
dispose: () =>
|
|
373
|
+
devtoolsEvents.removeListener("fromDevTools", devToolsEventListener),
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
context.subscriptions.push(
|
|
377
|
+
commands.registerCommand("apollographql/startDevToolsServer", () => {
|
|
378
|
+
const port = workspace
|
|
379
|
+
.getConfiguration("apollographql")
|
|
380
|
+
.get("devTools.serverPort", 0);
|
|
381
|
+
startServer(port);
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
384
|
+
context.subscriptions.push({
|
|
385
|
+
dispose() {
|
|
386
|
+
if (serverState) {
|
|
387
|
+
serverState.disposable.dispose();
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
context.subscriptions.push(
|
|
392
|
+
commands.registerCommand("apollographql/stopDevToolsServer", () => {
|
|
393
|
+
serverState?.disposable.dispose();
|
|
394
|
+
}),
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
Debug.traceLevel = workspace
|
|
398
|
+
.getConfiguration("apollographql")
|
|
399
|
+
.get("trace.server");
|
|
400
|
+
context.subscriptions.push(
|
|
401
|
+
workspace.onDidChangeConfiguration((event) => {
|
|
402
|
+
const affected = event.affectsConfiguration("apollographql.trace.server");
|
|
403
|
+
if (affected) {
|
|
404
|
+
Debug.traceLevel = workspace
|
|
405
|
+
.getConfiguration("apollographql")
|
|
406
|
+
.get("trace.server");
|
|
407
|
+
}
|
|
408
|
+
}),
|
|
409
|
+
);
|
|
410
|
+
|
|
332
411
|
await client.start();
|
|
333
412
|
return {
|
|
334
413
|
outputChannel,
|
package/start-ac.mjs
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// for testing, start a few of these, e.g. with
|
|
4
|
+
// while true; do echo "foo\nbar\nbaz" | parallel ./start-ac.mjs; sleep 1; done
|
|
5
|
+
|
|
6
|
+
import { connectApolloClientToVSCodeDevTools } from "@apollo/client-devtools-vscode";
|
|
7
|
+
import WebSocket from "ws";
|
|
8
|
+
import { ApolloClient, InMemoryCache } from "@apollo/client/core/index.js";
|
|
9
|
+
import { MockLink } from "@apollo/client/testing/core/index.js";
|
|
10
|
+
import gql from "graphql-tag";
|
|
11
|
+
|
|
12
|
+
globalThis.WebSocket ||= WebSocket;
|
|
13
|
+
|
|
14
|
+
const helloWorld = gql`
|
|
15
|
+
query {
|
|
16
|
+
hello
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const link = new MockLink([
|
|
21
|
+
{
|
|
22
|
+
request: { query: helloWorld },
|
|
23
|
+
result: { data: { hello: "world" } },
|
|
24
|
+
maxUsageCount: 1000,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
request: {
|
|
28
|
+
query: gql`
|
|
29
|
+
query {
|
|
30
|
+
hi
|
|
31
|
+
}
|
|
32
|
+
`,
|
|
33
|
+
},
|
|
34
|
+
result: { data: { hi: "universe" } },
|
|
35
|
+
maxUsageCount: 1000,
|
|
36
|
+
},
|
|
37
|
+
]);
|
|
38
|
+
const client = new ApolloClient({
|
|
39
|
+
link,
|
|
40
|
+
cache: new InMemoryCache(),
|
|
41
|
+
devtools: { name: process.argv[2] },
|
|
42
|
+
});
|
|
43
|
+
client.watchQuery({ query: helloWorld }).subscribe({ next() {} });
|
|
44
|
+
const { connectedPromise, disconnect, onCleanup } =
|
|
45
|
+
connectApolloClientToVSCodeDevTools(
|
|
46
|
+
client,
|
|
47
|
+
"ws://localhost:7095", // nosemgrep
|
|
48
|
+
);
|
|
49
|
+
console.log("connecting...");
|
|
50
|
+
onCleanup((reason) =>
|
|
51
|
+
console.log(
|
|
52
|
+
"disconnected",
|
|
53
|
+
reason,
|
|
54
|
+
/* referencing client here to prevent it from getting garbage connected */ client.version,
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
connectedPromise.then(() => {
|
|
58
|
+
console.log("connected");
|
|
59
|
+
// setTimeout(unregister, 5000, "USERLAND_TIMEOUT");
|
|
60
|
+
});
|