@soda-gql/lsp 0.12.2 → 0.12.4
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/dist/bin.cjs +1 -1
- package/dist/bin.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -20
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -20
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{server-lBJEHSZu.mjs → server-6n4IOnC9.mjs} +7 -222
- package/dist/server-6n4IOnC9.mjs.map +1 -0
- package/dist/{server-DEK11kTC.cjs → server-BZEiUZua.cjs} +9 -224
- package/dist/server-BZEiUZua.cjs.map +1 -0
- package/package.json +5 -5
- package/dist/server-DEK11kTC.cjs.map +0 -1
- package/dist/server-lBJEHSZu.mjs.map +0 -1
|
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
let node_module = require("node:module");
|
|
29
29
|
let node_url = require("node:url");
|
|
30
30
|
let __soda_gql_common = require("@soda-gql/common");
|
|
31
|
+
let __soda_gql_common_template_extraction = require("@soda-gql/common/template-extraction");
|
|
31
32
|
let graphql = require("graphql");
|
|
32
33
|
let node_fs = require("node:fs");
|
|
33
34
|
let node_path = require("node:path");
|
|
@@ -158,13 +159,6 @@ const preprocessFragmentArgs = (content) => {
|
|
|
158
159
|
* Document manager: tracks open documents and extracts tagged templates using SWC.
|
|
159
160
|
* @module
|
|
160
161
|
*/
|
|
161
|
-
const OPERATION_KINDS = new Set([
|
|
162
|
-
"query",
|
|
163
|
-
"mutation",
|
|
164
|
-
"subscription",
|
|
165
|
-
"fragment"
|
|
166
|
-
]);
|
|
167
|
-
const isOperationKind = (value) => OPERATION_KINDS.has(value);
|
|
168
162
|
/**
|
|
169
163
|
* Collect gql identifiers from import declarations.
|
|
170
164
|
* Adapted from builder's collectGqlIdentifiers pattern.
|
|
@@ -199,177 +193,6 @@ const collectGqlIdentifiers = (module$1, filePath, helper) => {
|
|
|
199
193
|
return identifiers;
|
|
200
194
|
};
|
|
201
195
|
/**
|
|
202
|
-
* Check if a call expression is a gql.{schemaName}(...) call.
|
|
203
|
-
* Returns the schema name if it is, null otherwise.
|
|
204
|
-
*/
|
|
205
|
-
const getGqlCallSchemaName = (identifiers, call) => {
|
|
206
|
-
const callee = call.callee;
|
|
207
|
-
if (callee.type !== "MemberExpression") {
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
const member = callee;
|
|
211
|
-
if (member.object.type !== "Identifier" || !identifiers.has(member.object.value)) {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
if (member.property.type !== "Identifier") {
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
const firstArg = call.arguments[0];
|
|
218
|
-
if (!firstArg?.expression || firstArg.expression.type !== "ArrowFunctionExpression") {
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
return member.property.value;
|
|
222
|
-
};
|
|
223
|
-
/**
|
|
224
|
-
* Extract templates from a gql callback's arrow function body.
|
|
225
|
-
* Handles both expression bodies and block bodies with return statements.
|
|
226
|
-
*/
|
|
227
|
-
const extractTemplatesFromCallback = (arrow, schemaName, spanOffset, converter) => {
|
|
228
|
-
const templates = [];
|
|
229
|
-
const processExpression = (expr) => {
|
|
230
|
-
if (expr.type === "TaggedTemplateExpression") {
|
|
231
|
-
const tagged = expr;
|
|
232
|
-
extractFromTaggedTemplate(tagged, schemaName, spanOffset, converter, templates);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
if (expr.type === "CallExpression") {
|
|
236
|
-
const call = expr;
|
|
237
|
-
if (call.callee.type === "TaggedTemplateExpression") {
|
|
238
|
-
extractFromTaggedTemplate(call.callee, schemaName, spanOffset, converter, templates);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
if (arrow.body.type !== "BlockStatement") {
|
|
243
|
-
processExpression(arrow.body);
|
|
244
|
-
return templates;
|
|
245
|
-
}
|
|
246
|
-
for (const stmt of arrow.body.stmts) {
|
|
247
|
-
if (stmt.type === "ReturnStatement" && stmt.argument) {
|
|
248
|
-
processExpression(stmt.argument);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return templates;
|
|
252
|
-
};
|
|
253
|
-
const extractFromTaggedTemplate = (tagged, schemaName, spanOffset, converter, templates) => {
|
|
254
|
-
if (tagged.tag.type !== "CallExpression") {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
const tagCall = tagged.tag;
|
|
258
|
-
if (tagCall.callee.type !== "Identifier") {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
const kind = tagCall.callee.value;
|
|
262
|
-
if (!isOperationKind(kind)) {
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
let elementName;
|
|
266
|
-
let typeName;
|
|
267
|
-
const firstArg = tagCall.arguments[0]?.expression;
|
|
268
|
-
if (firstArg?.type === "StringLiteral") {
|
|
269
|
-
elementName = firstArg.value;
|
|
270
|
-
}
|
|
271
|
-
const secondArg = tagCall.arguments[1]?.expression;
|
|
272
|
-
if (secondArg?.type === "StringLiteral") {
|
|
273
|
-
typeName = secondArg.value;
|
|
274
|
-
}
|
|
275
|
-
const { quasis, expressions } = tagged.template;
|
|
276
|
-
if (quasis.length === 0) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
const parts = [];
|
|
280
|
-
let contentStart = -1;
|
|
281
|
-
let contentEnd = -1;
|
|
282
|
-
for (let i = 0; i < quasis.length; i++) {
|
|
283
|
-
const quasi = quasis[i];
|
|
284
|
-
if (!quasi) {
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
const quasiStart = converter.byteOffsetToCharIndex(quasi.span.start - spanOffset);
|
|
288
|
-
const quasiEnd = converter.byteOffsetToCharIndex(quasi.span.end - spanOffset);
|
|
289
|
-
if (contentStart === -1) {
|
|
290
|
-
contentStart = quasiStart;
|
|
291
|
-
}
|
|
292
|
-
contentEnd = quasiEnd;
|
|
293
|
-
const quasiContent = quasi.cooked ?? quasi.raw;
|
|
294
|
-
parts.push(quasiContent);
|
|
295
|
-
if (i < expressions.length) {
|
|
296
|
-
parts.push(`__FRAG_SPREAD_${i}__`);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (contentStart === -1 || contentEnd === -1) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const content = parts.join("");
|
|
303
|
-
templates.push({
|
|
304
|
-
contentRange: {
|
|
305
|
-
start: contentStart,
|
|
306
|
-
end: contentEnd
|
|
307
|
-
},
|
|
308
|
-
schemaName,
|
|
309
|
-
kind,
|
|
310
|
-
content,
|
|
311
|
-
...elementName !== undefined ? { elementName } : {},
|
|
312
|
-
...typeName !== undefined ? { typeName } : {}
|
|
313
|
-
});
|
|
314
|
-
};
|
|
315
|
-
/**
|
|
316
|
-
* Walk AST to find gql calls and extract templates.
|
|
317
|
-
* Adapted from builder's unwrapMethodChains + visit pattern.
|
|
318
|
-
*/
|
|
319
|
-
const walkAndExtract = (node, identifiers, spanOffset, converter) => {
|
|
320
|
-
const templates = [];
|
|
321
|
-
const visit$3 = (n) => {
|
|
322
|
-
if (!n || typeof n !== "object") {
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
if ("type" in n && n.type === "CallExpression") {
|
|
326
|
-
const gqlCall = findGqlCall(identifiers, n);
|
|
327
|
-
if (gqlCall) {
|
|
328
|
-
const schemaName = getGqlCallSchemaName(identifiers, gqlCall);
|
|
329
|
-
if (schemaName) {
|
|
330
|
-
const arrow = gqlCall.arguments[0]?.expression;
|
|
331
|
-
templates.push(...extractTemplatesFromCallback(arrow, schemaName, spanOffset, converter));
|
|
332
|
-
}
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
if (Array.isArray(n)) {
|
|
337
|
-
for (const item of n) {
|
|
338
|
-
visit$3(item);
|
|
339
|
-
}
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
for (const key of Object.keys(n)) {
|
|
343
|
-
if (key === "span" || key === "type") {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
const value = n[key];
|
|
347
|
-
if (value && typeof value === "object") {
|
|
348
|
-
visit$3(value);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
visit$3(node);
|
|
353
|
-
return templates;
|
|
354
|
-
};
|
|
355
|
-
/**
|
|
356
|
-
* Find the innermost gql call, unwrapping method chains like .attach().
|
|
357
|
-
*/
|
|
358
|
-
const findGqlCall = (identifiers, node) => {
|
|
359
|
-
if (!node || node.type !== "CallExpression") {
|
|
360
|
-
return null;
|
|
361
|
-
}
|
|
362
|
-
const call = node;
|
|
363
|
-
if (getGqlCallSchemaName(identifiers, call) !== null) {
|
|
364
|
-
return call;
|
|
365
|
-
}
|
|
366
|
-
const callee = call.callee;
|
|
367
|
-
if (callee.type !== "MemberExpression") {
|
|
368
|
-
return null;
|
|
369
|
-
}
|
|
370
|
-
return findGqlCall(identifiers, callee.object);
|
|
371
|
-
};
|
|
372
|
-
/**
|
|
373
196
|
* Index fragment definitions from extracted templates.
|
|
374
197
|
* Parses each fragment template to extract FragmentDefinitionNode for cross-file resolution.
|
|
375
198
|
*/
|
|
@@ -481,7 +304,11 @@ const createDocumentManager = (helper, swcOptions) => {
|
|
|
481
304
|
if (gqlIdentifiers.size === 0) {
|
|
482
305
|
return [];
|
|
483
306
|
}
|
|
484
|
-
|
|
307
|
+
const positionCtx = {
|
|
308
|
+
spanOffset,
|
|
309
|
+
converter
|
|
310
|
+
};
|
|
311
|
+
return (0, __soda_gql_common_template_extraction.walkAndExtract)(program, gqlIdentifiers, positionCtx);
|
|
485
312
|
};
|
|
486
313
|
return {
|
|
487
314
|
update: (uri, version, source) => {
|
|
@@ -3750,8 +3577,8 @@ const handleFormatting = (input) => {
|
|
|
3750
3577
|
if (formatted === template.content) {
|
|
3751
3578
|
continue;
|
|
3752
3579
|
}
|
|
3753
|
-
const baseIndent = detectBaseIndent(tsSource, template.contentRange.start);
|
|
3754
|
-
const reindented = reindent(formatted, baseIndent, template.content);
|
|
3580
|
+
const baseIndent = (0, __soda_gql_common_template_extraction.detectBaseIndent)(tsSource, template.contentRange.start);
|
|
3581
|
+
const reindented = (0, __soda_gql_common_template_extraction.reindent)(formatted, baseIndent, template.content);
|
|
3755
3582
|
if (reindented === template.content) {
|
|
3756
3583
|
continue;
|
|
3757
3584
|
}
|
|
@@ -3767,48 +3594,6 @@ const handleFormatting = (input) => {
|
|
|
3767
3594
|
}
|
|
3768
3595
|
return edits;
|
|
3769
3596
|
};
|
|
3770
|
-
/**
|
|
3771
|
-
* Detect the base indentation for a template by looking at the line
|
|
3772
|
-
* containing the opening backtick.
|
|
3773
|
-
*/
|
|
3774
|
-
const detectBaseIndent = (tsSource, contentStartOffset) => {
|
|
3775
|
-
let lineStart = contentStartOffset;
|
|
3776
|
-
while (lineStart > 0 && tsSource.charCodeAt(lineStart - 1) !== 10) {
|
|
3777
|
-
lineStart--;
|
|
3778
|
-
}
|
|
3779
|
-
let i = lineStart;
|
|
3780
|
-
while (i < tsSource.length && (tsSource.charCodeAt(i) === 32 || tsSource.charCodeAt(i) === 9)) {
|
|
3781
|
-
i++;
|
|
3782
|
-
}
|
|
3783
|
-
return tsSource.slice(lineStart, i);
|
|
3784
|
-
};
|
|
3785
|
-
/**
|
|
3786
|
-
* Re-indent formatted GraphQL to match the embedding context.
|
|
3787
|
-
*
|
|
3788
|
-
* The original template may start with a newline (common for multi-line templates)
|
|
3789
|
-
* or be inline. We match the original pattern:
|
|
3790
|
-
* - If original starts with newline, formatted output gets newline + indented lines
|
|
3791
|
-
* - If original is single-line, keep formatted as single-line if it fits
|
|
3792
|
-
*/
|
|
3793
|
-
const reindent = (formatted, baseIndent, originalContent) => {
|
|
3794
|
-
const trimmedFormatted = formatted.trim();
|
|
3795
|
-
if (!originalContent.includes("\n") && !trimmedFormatted.includes("\n")) {
|
|
3796
|
-
return trimmedFormatted;
|
|
3797
|
-
}
|
|
3798
|
-
const indent = `${baseIndent} `;
|
|
3799
|
-
const lines = trimmedFormatted.split("\n");
|
|
3800
|
-
const indentedLines = lines.map((line) => line.trim() === "" ? "" : indent + line);
|
|
3801
|
-
const startsWithNewline = originalContent.startsWith("\n");
|
|
3802
|
-
const endsWithNewline = originalContent.endsWith("\n");
|
|
3803
|
-
let result = indentedLines.join("\n");
|
|
3804
|
-
if (startsWithNewline) {
|
|
3805
|
-
result = `\n${result}`;
|
|
3806
|
-
}
|
|
3807
|
-
if (endsWithNewline) {
|
|
3808
|
-
result = `${result}\n${baseIndent}`;
|
|
3809
|
-
}
|
|
3810
|
-
return result;
|
|
3811
|
-
};
|
|
3812
3597
|
|
|
3813
3598
|
//#endregion
|
|
3814
3599
|
//#region packages/lsp/src/handlers/hover.ts
|
|
@@ -4448,4 +4233,4 @@ Object.defineProperty(exports, 'preprocessFragmentArgs', {
|
|
|
4448
4233
|
return preprocessFragmentArgs;
|
|
4449
4234
|
}
|
|
4450
4235
|
});
|
|
4451
|
-
//# sourceMappingURL=server-
|
|
4236
|
+
//# sourceMappingURL=server-BZEiUZua.cjs.map
|