@mo36924/graphql-plugin 1.6.4 → 5.0.69
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/LICENSE +1 -1
- package/dist/index.cjs +180 -255
- package/dist/index.d.ts +2 -2
- package/dist/index.js +180 -255
- package/package.json +24 -24
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -296
- package/dist/index.mjs.map +0 -1
package/LICENSE
CHANGED
package/dist/index.cjs
CHANGED
@@ -1,127 +1,90 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
const graphql = require('graphql');
|
7
|
-
const graphqlLanguageServiceInterface = require('graphql-language-service-interface');
|
8
|
-
const graphqlLanguageServiceUtils = require('graphql-language-service-utils');
|
9
|
-
const vscodeLanguageserverTypes = require('vscode-languageserver-types');
|
3
|
+
var graphql = require('@mo36924/graphql');
|
4
|
+
var graphql$1 = require('graphql');
|
5
|
+
var graphqlLanguageService = require('graphql-language-service');
|
10
6
|
|
11
|
-
const init = ({ typescript: ts })
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
7
|
+
const init = ({ typescript: ts })=>{
|
8
|
+
const isQueryTag = (node)=>ts.isTaggedTemplateExpression(node) && ts.isIdentifier(node.tag) && node.tag.escapedText === "gql";
|
9
|
+
const getScriptElementKind = (completionItemKind)=>{
|
10
|
+
switch(completionItemKind){
|
11
|
+
case graphqlLanguageService.CompletionItemKind.Function:
|
12
|
+
case graphqlLanguageService.CompletionItemKind.Constructor:
|
13
|
+
return ts.ScriptElementKind.functionElement;
|
14
|
+
case graphqlLanguageService.CompletionItemKind.Field:
|
15
|
+
case graphqlLanguageService.CompletionItemKind.Variable:
|
16
|
+
return ts.ScriptElementKind.memberVariableElement;
|
17
|
+
default:
|
18
|
+
return ts.ScriptElementKind.unknown;
|
19
|
+
}
|
20
|
+
};
|
21
|
+
const getDiagnosticCategory = (diagnosticSeverity)=>{
|
22
|
+
switch(diagnosticSeverity){
|
23
|
+
case graphqlLanguageService.DIAGNOSTIC_SEVERITY.Warning:
|
24
|
+
return ts.DiagnosticCategory.Warning;
|
25
|
+
case graphqlLanguageService.DIAGNOSTIC_SEVERITY.Information:
|
26
|
+
return ts.DiagnosticCategory.Message;
|
27
|
+
case graphqlLanguageService.DIAGNOSTIC_SEVERITY.Hint:
|
28
|
+
return ts.DiagnosticCategory.Suggestion;
|
29
|
+
default:
|
30
|
+
return ts.DiagnosticCategory.Error;
|
31
|
+
}
|
32
|
+
};
|
33
|
+
const getHoverQueryTag = (sourceFile, position)=>{
|
34
|
+
const tag = ts.forEachChild(sourceFile, function visitor(node) {
|
35
|
+
if (position < node.pos) {
|
36
|
+
return true;
|
38
37
|
}
|
39
|
-
|
40
|
-
|
41
|
-
try {
|
42
|
-
update();
|
43
|
-
fs.watch(watchPath, listener);
|
44
|
-
fs.unwatchFile(watchPath);
|
45
|
-
}
|
46
|
-
catch { }
|
47
|
-
});
|
38
|
+
if (position >= node.end) {
|
39
|
+
return;
|
48
40
|
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
case "subscription":
|
55
|
-
return true;
|
56
|
-
default:
|
57
|
-
return false;
|
58
|
-
}
|
59
|
-
};
|
60
|
-
const getDiagnosticCategory = (severity) => {
|
61
|
-
switch (severity) {
|
62
|
-
case vscodeLanguageserverTypes.DiagnosticSeverity.Error:
|
63
|
-
return ts.DiagnosticCategory.Error;
|
64
|
-
case vscodeLanguageserverTypes.DiagnosticSeverity.Warning:
|
65
|
-
return ts.DiagnosticCategory.Warning;
|
66
|
-
case vscodeLanguageserverTypes.DiagnosticSeverity.Information:
|
67
|
-
return ts.DiagnosticCategory.Message;
|
68
|
-
case vscodeLanguageserverTypes.DiagnosticSeverity.Hint:
|
69
|
-
return ts.DiagnosticCategory.Suggestion;
|
70
|
-
default:
|
71
|
-
return ts.DiagnosticCategory.Error;
|
72
|
-
}
|
73
|
-
};
|
74
|
-
const hover = (sourceFile, position) => {
|
75
|
-
const tag = ts.forEachChild(sourceFile, function visitor(node) {
|
76
|
-
if (position < node.pos) {
|
77
|
-
return true;
|
41
|
+
if (isQueryTag(node)) {
|
42
|
+
const template = node.template;
|
43
|
+
if (ts.isNoSubstitutionTemplateLiteral(template)) {
|
44
|
+
if (position >= template.getStart() + 1 && position < template.getEnd() - 1) {
|
45
|
+
return node;
|
78
46
|
}
|
79
|
-
|
80
|
-
|
47
|
+
} else {
|
48
|
+
const head = template.head;
|
49
|
+
if (position >= head.getStart() + 1 && position < head.getEnd() - 2) {
|
50
|
+
return node;
|
81
51
|
}
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
if (position >= template.getStart() + 1 && position < template.getEnd() - 1) {
|
86
|
-
return node;
|
87
|
-
}
|
88
|
-
}
|
89
|
-
else {
|
90
|
-
const head = template.head;
|
91
|
-
if (position >= head.getStart() + 1 && position < head.getEnd() - 2) {
|
92
|
-
return node;
|
93
|
-
}
|
94
|
-
for (const { literal } of template.templateSpans) {
|
95
|
-
if (position >= literal.getStart() + 1 &&
|
96
|
-
position < literal.getEnd() - (ts.isTemplateMiddle(literal) ? 2 : 1)) {
|
97
|
-
return node;
|
98
|
-
}
|
99
|
-
}
|
52
|
+
for (const { literal } of template.templateSpans){
|
53
|
+
if (position >= literal.getStart() + 1 && position < literal.getEnd() - (ts.isTemplateMiddle(literal) ? 2 : 1)) {
|
54
|
+
return node;
|
100
55
|
}
|
101
56
|
}
|
102
|
-
return ts.forEachChild(node, visitor);
|
103
|
-
});
|
104
|
-
if (tag === true) {
|
105
|
-
return;
|
106
57
|
}
|
107
|
-
|
108
|
-
|
109
|
-
|
58
|
+
}
|
59
|
+
return ts.forEachChild(node, visitor);
|
60
|
+
});
|
61
|
+
if (tag === true) {
|
62
|
+
return;
|
63
|
+
}
|
64
|
+
return tag;
|
65
|
+
};
|
66
|
+
return {
|
67
|
+
create (info) {
|
68
|
+
const { path, schema } = graphql.getConfig();
|
69
|
+
const languageService = info.languageService;
|
70
|
+
if (!path) {
|
71
|
+
return languageService;
|
72
|
+
}
|
73
|
+
const getSourceFile = (fileName)=>languageService.getProgram()?.getSourceFile(fileName);
|
74
|
+
const normalizeQuery = (node)=>{
|
110
75
|
const template = node.template;
|
111
76
|
let query = "";
|
112
|
-
let variables = "";
|
113
77
|
if (ts.isNoSubstitutionTemplateLiteral(template)) {
|
114
|
-
// 2
|
78
|
+
// 2 \`\`
|
115
79
|
const templateWidth = template.getWidth() - 2;
|
116
80
|
query = template.text.padStart(templateWidth);
|
117
|
-
}
|
118
|
-
else {
|
81
|
+
} else {
|
119
82
|
const head = template.head;
|
120
83
|
const templateSpans = template.templateSpans;
|
121
|
-
// 3
|
84
|
+
// 3 \`...\${
|
122
85
|
const templateWidth = head.getWidth() - 3;
|
123
86
|
query = head.text.padStart(templateWidth);
|
124
|
-
templateSpans.forEach((span, i)
|
87
|
+
templateSpans.forEach((span, i)=>{
|
125
88
|
const spanWidth = span.getFullWidth();
|
126
89
|
const literal = span.literal;
|
127
90
|
const literalWidth = literal.getWidth();
|
@@ -131,168 +94,130 @@ const init = ({ typescript: ts }) => {
|
|
131
94
|
const templateWidth = literalWidth - (ts.isTemplateTail(literal) ? 2 : 3);
|
132
95
|
const template = literal.text.padStart(templateWidth);
|
133
96
|
query += variable + template;
|
134
|
-
variables += variableName + ":Unknown";
|
135
97
|
});
|
136
98
|
}
|
137
|
-
const
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
offset -= tag.length + variables.length + 3;
|
143
|
-
}
|
144
|
-
else if (tag === "query") {
|
145
|
-
query = `{${query}}`;
|
146
|
-
offset -= 1;
|
147
|
-
}
|
148
|
-
else {
|
149
|
-
query = `${tag}{${query}}`;
|
150
|
-
offset -= tag.length + 1;
|
151
|
-
}
|
152
|
-
const documentNode = graphql.parse(query);
|
153
|
-
const errors = graphql.validate(schema, documentNode);
|
154
|
-
for (const error of errors) {
|
155
|
-
const match = error.message.match(/^Variable ".*?" of type "Unknown" used in position expecting type "(.*?)"\.$/);
|
156
|
-
if (match) {
|
157
|
-
query = query.replace("Unknown", match[1]);
|
158
|
-
offset += 7 - match[1].length;
|
159
|
-
}
|
160
|
-
}
|
99
|
+
const field = query.match(/\w+/)?.[0] ?? "";
|
100
|
+
const isMutation = !!schema.getMutationType()?.getFields()[field];
|
101
|
+
const operation = isMutation ? "mutation" : "query";
|
102
|
+
query = operation + query.replace(/\n|\r/g, " ");
|
103
|
+
const offset = -operation.length + template.getStart() + 1;
|
161
104
|
return {
|
162
105
|
query,
|
163
|
-
offset
|
106
|
+
offset
|
164
107
|
};
|
165
108
|
};
|
166
|
-
const proxy =
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
return
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
textSpan: {
|
196
|
-
start: offset + token.start,
|
197
|
-
length: token.end - token.start,
|
198
|
-
},
|
199
|
-
kindModifiers: "",
|
200
|
-
displayParts: [{ text: marked, kind: "" }],
|
201
|
-
};
|
202
|
-
};
|
203
|
-
proxy.getCompletionsAtPosition = (fileName, position, options) => {
|
204
|
-
const sourceFile = getSourceFile(fileName);
|
205
|
-
if (!sourceFile) {
|
206
|
-
return undefined;
|
207
|
-
}
|
208
|
-
const tag = hover(sourceFile, position);
|
209
|
-
if (!tag) {
|
210
|
-
return languageService.getCompletionsAtPosition(fileName, position, options);
|
211
|
-
}
|
212
|
-
let result;
|
213
|
-
try {
|
214
|
-
result = fix(tag);
|
215
|
-
}
|
216
|
-
catch {
|
217
|
-
return languageService.getCompletionsAtPosition(fileName, position, options);
|
218
|
-
}
|
219
|
-
const { query, offset } = result;
|
220
|
-
const cursor = new graphqlLanguageServiceUtils.Position(0, position - offset);
|
221
|
-
const items = graphqlLanguageServiceInterface.getAutocompleteSuggestions(schema, query, cursor);
|
222
|
-
if (!items.length) {
|
223
|
-
return;
|
224
|
-
}
|
225
|
-
return {
|
226
|
-
isGlobalCompletion: false,
|
227
|
-
isMemberCompletion: false,
|
228
|
-
isNewIdentifierLocation: false,
|
229
|
-
entries: items.map((item) => {
|
230
|
-
let kind;
|
231
|
-
switch (item.kind) {
|
232
|
-
case vscodeLanguageserverTypes.CompletionItemKind.Function:
|
233
|
-
case vscodeLanguageserverTypes.CompletionItemKind.Constructor:
|
234
|
-
kind = ts.ScriptElementKind.functionElement;
|
235
|
-
break;
|
236
|
-
case vscodeLanguageserverTypes.CompletionItemKind.Field:
|
237
|
-
case vscodeLanguageserverTypes.CompletionItemKind.Variable:
|
238
|
-
kind = ts.ScriptElementKind.memberVariableElement;
|
239
|
-
break;
|
240
|
-
default:
|
241
|
-
kind = ts.ScriptElementKind.unknown;
|
242
|
-
break;
|
243
|
-
}
|
244
|
-
return {
|
245
|
-
name: item.label,
|
246
|
-
kindModifiers: "",
|
247
|
-
kind,
|
248
|
-
sortText: "",
|
249
|
-
};
|
250
|
-
}),
|
251
|
-
};
|
252
|
-
};
|
253
|
-
proxy.getSemanticDiagnostics = (fileName) => {
|
254
|
-
const diagnostics = languageService.getSemanticDiagnostics(fileName);
|
255
|
-
const sourceFile = getSourceFile(fileName);
|
256
|
-
if (!sourceFile) {
|
257
|
-
return diagnostics;
|
258
|
-
}
|
259
|
-
ts.forEachChild(sourceFile, function visitor(node) {
|
260
|
-
if (ts.isTaggedTemplateExpression(node) && ts.isIdentifier(node.tag) && isGraphqlTag(node.tag.getText())) {
|
261
|
-
try {
|
262
|
-
const { query, offset } = fix(node);
|
263
|
-
const _diagnostics = graphqlLanguageServiceInterface.getDiagnostics(query, schema);
|
264
|
-
for (const { range: { start, end }, severity, message, } of _diagnostics) {
|
265
|
-
diagnostics.push({
|
266
|
-
category: getDiagnosticCategory(severity),
|
267
|
-
code: 9999,
|
268
|
-
messageText: message,
|
269
|
-
file: sourceFile,
|
270
|
-
start: start.character + offset,
|
271
|
-
length: end.character - start.character,
|
272
|
-
});
|
109
|
+
const proxy = {
|
110
|
+
...languageService,
|
111
|
+
getQuickInfoAtPosition (fileName, position) {
|
112
|
+
const sourceFile = getSourceFile(fileName);
|
113
|
+
if (!sourceFile) {
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
const tag = getHoverQueryTag(sourceFile, position);
|
117
|
+
if (!tag) {
|
118
|
+
return languageService.getQuickInfoAtPosition(fileName, position);
|
119
|
+
}
|
120
|
+
const { query, offset } = normalizeQuery(tag);
|
121
|
+
const cursor = new graphqlLanguageService.Position(0, position - offset);
|
122
|
+
const token = graphqlLanguageService.getTokenAtPosition(query, cursor);
|
123
|
+
const marked = graphqlLanguageService.getHoverInformation(schema, query, cursor, token);
|
124
|
+
if (marked === "" || typeof marked !== "string") {
|
125
|
+
return;
|
126
|
+
}
|
127
|
+
return {
|
128
|
+
kind: ts.ScriptElementKind.string,
|
129
|
+
textSpan: {
|
130
|
+
start: offset + token.start,
|
131
|
+
length: token.end - token.start
|
132
|
+
},
|
133
|
+
kindModifiers: "",
|
134
|
+
displayParts: [
|
135
|
+
{
|
136
|
+
text: marked,
|
137
|
+
kind: ""
|
273
138
|
}
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
139
|
+
]
|
140
|
+
};
|
141
|
+
},
|
142
|
+
getCompletionsAtPosition (fileName, position, options) {
|
143
|
+
const sourceFile = getSourceFile(fileName);
|
144
|
+
if (!sourceFile) {
|
145
|
+
return;
|
146
|
+
}
|
147
|
+
const tag = getHoverQueryTag(sourceFile, position);
|
148
|
+
if (!tag) {
|
149
|
+
return languageService.getCompletionsAtPosition(fileName, position, options);
|
150
|
+
}
|
151
|
+
const { query, offset } = normalizeQuery(tag);
|
152
|
+
const cursor = new graphqlLanguageService.Position(0, position - offset);
|
153
|
+
const items = graphqlLanguageService.getAutocompleteSuggestions(schema, query, cursor);
|
154
|
+
if (/^\s*\{\s*\}\s*$/.test(query)) {
|
155
|
+
const operation = "mutation";
|
156
|
+
const cursor = new graphqlLanguageService.Position(0, operation.length + position - offset);
|
157
|
+
const labels = new Set(items.map((item)=>item.label));
|
158
|
+
const mutationItems = graphqlLanguageService.getAutocompleteSuggestions(schema, operation + query, cursor).filter((item)=>!labels.has(item.label));
|
159
|
+
items.push(...mutationItems);
|
160
|
+
}
|
161
|
+
if (!items.length) {
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
return {
|
165
|
+
isGlobalCompletion: false,
|
166
|
+
isMemberCompletion: false,
|
167
|
+
isNewIdentifierLocation: false,
|
168
|
+
entries: items.map((item)=>({
|
169
|
+
name: item.label,
|
170
|
+
kindModifiers: "",
|
171
|
+
kind: getScriptElementKind(item.kind),
|
172
|
+
sortText: ""
|
173
|
+
}))
|
174
|
+
};
|
175
|
+
},
|
176
|
+
getSemanticDiagnostics (fileName) {
|
177
|
+
const diagnostics = languageService.getSemanticDiagnostics(fileName);
|
178
|
+
const sourceFile = getSourceFile(fileName);
|
179
|
+
if (!sourceFile) {
|
180
|
+
return diagnostics;
|
181
|
+
}
|
182
|
+
ts.forEachChild(sourceFile, function visitor(node) {
|
183
|
+
if (isQueryTag(node)) {
|
184
|
+
try {
|
185
|
+
const { query, offset } = normalizeQuery(node);
|
186
|
+
const _diagnostics = graphqlLanguageService.getDiagnostics(query, schema);
|
187
|
+
for (const { range: { start, end }, severity, message } of _diagnostics){
|
188
|
+
if (/Variable "\$.*?" is not defined/.test(message)) {
|
189
|
+
continue;
|
190
|
+
}
|
191
|
+
diagnostics.push({
|
192
|
+
category: getDiagnosticCategory(severity),
|
193
|
+
code: 9999,
|
194
|
+
messageText: message,
|
195
|
+
file: sourceFile,
|
196
|
+
start: start.character + offset,
|
197
|
+
length: end.character - start.character
|
198
|
+
});
|
199
|
+
}
|
200
|
+
} catch (error) {
|
201
|
+
if (error instanceof graphql$1.GraphQLError) {
|
202
|
+
diagnostics.push({
|
203
|
+
category: ts.DiagnosticCategory.Error,
|
204
|
+
code: 9999,
|
205
|
+
messageText: error.message,
|
206
|
+
file: sourceFile,
|
207
|
+
start: node.template.getStart() + 1,
|
208
|
+
length: node.template.getWidth() - 2
|
209
|
+
});
|
210
|
+
}
|
285
211
|
}
|
286
212
|
}
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
213
|
+
ts.forEachChild(node, visitor);
|
214
|
+
});
|
215
|
+
return diagnostics;
|
216
|
+
}
|
291
217
|
};
|
292
218
|
return proxy;
|
293
|
-
}
|
219
|
+
}
|
294
220
|
};
|
295
221
|
};
|
296
222
|
|
297
223
|
module.exports = init;
|
298
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED