Skip to content

Commit 36c7f25

Browse files
authoredJan 25, 2024
fix typescript bundling for svelte2tsx, config loading (#3514)
1 parent a562c96 commit 36c7f25

File tree

8 files changed

+106
-40
lines changed

8 files changed

+106
-40
lines changed
 

‎.changeset/new-tips-sneeze.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'graphql-language-service-server': patch
3+
'vscode-graphql': patch
4+
---
5+
6+
fix svelte parsing, re-load config only on config changes
7+
8+
- fix esbuild bundling of `typescript` for `svelte2tsx`!
9+
- confirm with manual testing of the vsix extension bundle ✅
10+
- ensure that the server only attemps to parse opened/saved files when the server is activated or the file is a config file

‎packages/graphql-language-service-server/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@
5555
"nullthrows": "^1.0.0",
5656
"source-map-js": "1.0.2",
5757
"svelte": "^4.1.1",
58+
"svelte2tsx": "^0.7.0",
5859
"vscode-jsonrpc": "^8.0.1",
5960
"vscode-languageserver": "^8.0.1",
6061
"vscode-languageserver-types": "^3.17.2",
61-
"vscode-uri": "^3.0.2"
62+
"vscode-uri": "^3.0.2",
63+
"typescript": "^5.3.3"
6264
},
6365
"devDependencies": {
6466
"@types/glob": "^8.1.0",

‎packages/graphql-language-service-server/src/MessageProcessor.ts

+31-25
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,9 @@ export class MessageProcessor {
220220
require('dotenv').config({ path: settings.dotEnvPath });
221221
}
222222
this._settings = { ...settings, ...vscodeSettings };
223-
const rootDir =
224-
this._settings?.load?.rootDir ??
225-
this._loadConfigOptions?.rootDir ??
226-
this._rootPath;
223+
const rootDir = this._settings?.load?.rootDir.length
224+
? this._settings?.load?.rootDir
225+
: this._rootPath;
227226
this._rootPath = rootDir;
228227
this._loadConfigOptions = {
229228
...Object.keys(this._settings?.load ?? {}).reduce((agg, key) => {
@@ -247,9 +246,9 @@ export class MessageProcessor {
247246
this._graphQLCache,
248247
this._logger,
249248
);
250-
if (this._graphQLCache?.getGraphQLConfig()) {
251-
const config = (this._graphQLConfig =
252-
this._graphQLCache.getGraphQLConfig());
249+
if (this._graphQLConfig || this._graphQLCache?.getGraphQLConfig) {
250+
const config =
251+
this._graphQLConfig ?? this._graphQLCache.getGraphQLConfig();
253252
await this._cacheAllProjectFiles(config);
254253
}
255254
this._isInitialized = true;
@@ -296,6 +295,24 @@ export class MessageProcessor {
296295
`\nfor more information on using 'graphql-config' with 'graphql-language-service-server', \nsee the documentation at ${configDocLink}`,
297296
);
298297
}
298+
async _isGraphQLConfigFile(uri: string) {
299+
const configMatchers = ['graphql.config', 'graphqlrc', 'graphqlconfig'];
300+
if (this._settings?.load?.fileName?.length) {
301+
configMatchers.push(this._settings.load.fileName);
302+
}
303+
304+
const fileMatch = configMatchers
305+
.filter(Boolean)
306+
.some(v => uri.match(v)?.length);
307+
if (fileMatch) {
308+
return fileMatch;
309+
}
310+
if (uri.match('package.json')?.length) {
311+
const graphqlConfig = await import(URI.parse(uri).fsPath);
312+
return Boolean(graphqlConfig?.graphql);
313+
}
314+
return false;
315+
}
299316

300317
async handleDidOpenOrSaveNotification(
301318
params: DidSaveTextDocumentParams | DidOpenTextDocumentParams,
@@ -304,13 +321,16 @@ export class MessageProcessor {
304321
* Initialize the LSP server when the first file is opened or saved,
305322
* so that we can access the user settings for config rootDir, etc
306323
*/
324+
const isGraphQLConfigFile = await this._isGraphQLConfigFile(
325+
params.textDocument.uri,
326+
);
307327
try {
308328
if (!this._isInitialized || !this._graphQLCache) {
309329
// don't try to initialize again if we've already tried
310330
// and the graphql config file or package.json entry isn't even there
311-
// if (this._isGraphQLConfigMissing === true) {
312-
// return null;
313-
// }
331+
if (this._isGraphQLConfigMissing === true && !isGraphQLConfigFile) {
332+
return null;
333+
}
314334
// then initial call to update graphql config
315335
await this._updateGraphQLConfig();
316336
}
@@ -343,21 +363,7 @@ export class MessageProcessor {
343363

344364
await this._invalidateCache(textDocument, uri, contents);
345365
} else {
346-
const configMatchers = [
347-
'graphql.config',
348-
'graphqlrc',
349-
'graphqlconfig',
350-
].filter(Boolean);
351-
if (this._settings?.load?.fileName) {
352-
configMatchers.push(this._settings.load.fileName);
353-
}
354-
355-
const hasGraphQLConfigFile = configMatchers.some(
356-
v => uri.match(v)?.length,
357-
);
358-
const hasPackageGraphQLConfig =
359-
uri.match('package.json')?.length && require(uri)?.graphql;
360-
if (hasGraphQLConfigFile || hasPackageGraphQLConfig) {
366+
if (isGraphQLConfigFile) {
361367
this._logger.info('updating graphql config');
362368
await this._updateGraphQLConfig();
363369
return { uri, diagnostics: [] };

‎packages/graphql-language-service-server/src/__tests__/findGraphQLTags-test.ts

+43-2
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,7 @@ query {id}`);
361361
`);
362362

363363
expect(JSON.stringify(contents[0].range)).toEqual(
364-
// TODO: change back to 29 when we get svelte parser working again
365-
JSON.stringify(new Range(new Position(2, 27), new Position(12, 0))),
364+
JSON.stringify(new Range(new Position(2, 29), new Position(12, 0))),
366365
);
367366
});
368367

@@ -488,4 +487,46 @@ export function Example(arg: string) {}`;
488487
const contents = findGraphQLTags(text, '.js');
489488
expect(contents.length).toEqual(0);
490489
});
490+
it('handles full svelte example', () => {
491+
const text = `
492+
<script>
493+
import { ApolloClient, gql } from '@apollo/client';
494+
import { setClient, getClient, query } from 'svelte-apollo';
495+
import { onMount } from 'svelte';
496+
let country;
497+
const QUERY = gql\`
498+
query GetCountryData {
499+
countries(namePrefix: "America") {
500+
edges {
501+
node {
502+
name
503+
flagImageUri
504+
}
505+
}
506+
}
507+
}
508+
\`;
509+
const client = new ApolloClient({
510+
uri: 'https://geodb-cities-graphql.p.rapidapi.com/',
511+
});
512+
setClient(client);
513+
onMount(async () => {
514+
const response = query(client, { query: QUERY });
515+
country = response.data;
516+
});
517+
</script>
518+
<div>
519+
{#if country}
520+
<h2>
521+
{country.name}
522+
</h2>
523+
<img src={country.flagImageUri} alt="Country Flag" />
524+
{:else}
525+
<p>loading...</p>
526+
{/if}
527+
</div>
528+
`;
529+
const contents = findGraphQLTags(text, '.svelte');
530+
expect(contents.length).toEqual(1);
531+
});
491532
});

‎packages/graphql-language-service-server/src/findGraphQLTags.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import { Position, Range } from 'graphql-language-service';
1717

1818
import { TAG_MAP } from './constants';
1919
import { ecmaParser, tsParser } from './parsers/babel';
20-
// import { svelteParser } from './parsers/svelte';
2120
import { vueParser } from './parsers/vue';
2221
import { astroParser } from './parsers/astro';
2322
import type { Logger, NoopLogger } from './Logger';
2423
import { RangeMapper } from './parsers/types';
24+
import { svelteParser } from './parsers/svelte';
2525

2626
type TagResult = { tag: string; template: string; range: Range };
2727

@@ -41,9 +41,7 @@ const parserMap = {
4141
'.tsx': tsParser,
4242
'.cts': tsParser,
4343
'.mts': tsParser,
44-
// disabled for now, until we can figure out how to get svelte2tsx working in esbuild bundle
45-
// '.svelte': svelteParser,
46-
'.svelte': vueParser,
44+
'.svelte': svelteParser,
4745
'.vue': vueParser,
4846
'.astro': astroParser,
4947
};
@@ -90,7 +88,6 @@ export function findGraphQLTags(
9088
if (parsed) {
9189
result.push(parsed);
9290
}
93-
return;
9491
}
9592
}
9693

@@ -133,7 +130,7 @@ export function findGraphQLTags(
133130
// check if the template literal is prefixed with #graphql
134131
const hasGraphQLPrefix =
135132
node.quasis[0].value.raw.startsWith('#graphql\n');
136-
// check if the template expression has
133+
// check if the template expression has /* GraphQL */ comment
137134
const hasGraphQLComment = Boolean(
138135
node.leadingComments?.[0]?.value.match(/^\s*GraphQL\s*$/),
139136
);
@@ -148,7 +145,6 @@ export function findGraphQLTags(
148145
for (const ast of asts) {
149146
visit(ast, visitors);
150147
}
151-
152148
return result;
153149
}
154150

‎packages/graphql-language-service-server/src/parsers/svelte.ts

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { babelParser } from './babel';
2-
// TODO: Remove this when we have a working svelte parsing implementation
3-
// eslint-disable-next-line import/no-extraneous-dependencies
42
import { svelte2tsx } from 'svelte2tsx';
53
import { SourceMapConsumer } from 'source-map-js';
64
import { Position, Range } from 'graphql-language-service';
@@ -32,7 +30,6 @@ export const svelteParser: SourceParser = (text, uri, logger) => {
3230
new Position(end.line, end.column),
3331
);
3432
};
35-
3633
try {
3734
return {
3835
asts: [babelParser(svelteResult.code, ['typescript'])],

‎packages/vscode-graphql/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
"dependencies": {
175175
"graphql": "^16.8.1",
176176
"graphql-language-service-server": "^2.11.10",
177-
"vscode-languageclient": "8.0.2"
177+
"vscode-languageclient": "8.0.2",
178+
"typescript": "^5.3.3"
178179
}
179180
}

‎yarn.lock

+14-1
Original file line numberDiff line numberDiff line change
@@ -2387,7 +2387,7 @@
23872387
"@babel/parser" "^7.12.13"
23882388
"@babel/types" "^7.12.13"
23892389

2390-
"@babel/traverse@^7.16.8", "@babel/traverse@^7.17.3", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.22.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.23.7", "@babel/traverse@^7.7.2":
2390+
"@babel/traverse@^7.16.8", "@babel/traverse@^7.17.3", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.22.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.23.2", "@babel/traverse@^7.23.7", "@babel/traverse@^7.7.2":
23912391
version "7.23.7"
23922392
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305"
23932393
integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==
@@ -18452,6 +18452,14 @@ svelte2tsx@^0.6.16:
1845218452
dedent-js "^1.0.1"
1845318453
pascal-case "^3.1.1"
1845418454

18455+
svelte2tsx@^0.7.0:
18456+
version "0.7.0"
18457+
resolved "https://registry.yarnpkg.com/svelte2tsx/-/svelte2tsx-0.7.0.tgz#ac7b39f8b5fb9fe20994dfbce71c2d2442fb478e"
18458+
integrity sha512-qAelcydnmuiDvD1HsrWi23RWx24RZTKRv6n4JaGC/pkoJfbLkJPQT2wa1qN0ZyfKTNLSyoj2FW9z62l/AUzUNA==
18459+
dependencies:
18460+
dedent-js "^1.0.1"
18461+
pascal-case "^3.1.1"
18462+
1845518463
svelte@^4.1.1:
1845618464
version "4.1.1"
1845718465
resolved "https://registry.yarnpkg.com/svelte/-/svelte-4.1.1.tgz#468ed0377d3cae542b35df8a22a3ca188d93272a"
@@ -19048,6 +19056,11 @@ typescript@^4.6.3:
1904819056
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
1904919057
integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==
1905019058

19059+
typescript@^5.3.3:
19060+
version "5.3.3"
19061+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
19062+
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
19063+
1905119064
ua-parser-js@^1.0.2:
1905219065
version "1.0.33"
1905319066
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.33.tgz#f21f01233e90e7ed0f059ceab46eb190ff17f8f4"

0 commit comments

Comments
 (0)
Please sign in to comment.