Skip to content

Commit

Permalink
fix exec and the dreaded code file loader bug
Browse files Browse the repository at this point in the history
  • Loading branch information
acao committed Jun 23, 2023
1 parent ae4ef39 commit fe84847
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 151 deletions.
2 changes: 1 addition & 1 deletion packages/graphql-language-service-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"dependencies": {
"@babel/parser": "^7.21.2",
"@babel/types": "^7.21.2",
"@graphql-tools/load": "^7.5.3",
"@graphql-tools/code-file-loader": "8.0.1",
"@vue/compiler-sfc": "^3.2.41",
"dotenv": "8.2.0",
"fast-glob": "^3.2.7",
Expand Down
17 changes: 16 additions & 1 deletion packages/graphql-language-service-server/src/GraphQLCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
loadConfig,
GraphQLConfig,
GraphQLProjectConfig,
GraphQLExtensionDeclaration
} from 'graphql-config';

import type { UnnormalizedTypeDefPointer } from '@graphql-tools/load';
Expand All @@ -42,6 +43,17 @@ import stringToHash from './stringToHash';
import glob from 'glob';
import { LoadConfigOptions } from './types';
import { URI } from 'vscode-uri';
import { CodeFileLoader } from '@graphql-tools/code-file-loader'

const LanguageServiceExtension: GraphQLExtensionDeclaration = api => {
// For schema
api.loaders.schema.register(new CodeFileLoader());
// For documents
api.loaders.documents.register(new CodeFileLoader());


return { name: 'languageService' };
}

// Maximum files to read when processing GraphQL files.
const MAX_READS = 200;
Expand All @@ -57,7 +69,10 @@ export async function getGraphQLCache({
loadConfigOptions: LoadConfigOptions;
config?: GraphQLConfig;
}): Promise<GraphQLCache> {
const graphQLConfig = config || (await loadConfig(loadConfigOptions));
const graphQLConfig = config || (await loadConfig({
...loadConfigOptions,
extensions: [LanguageServiceExtension]
}));
return new GraphQLCache({
configDir: loadConfigOptions.rootDir!,
config: graphQLConfig!,
Expand Down
5 changes: 3 additions & 2 deletions packages/vscode-graphql-execution/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@
"@urql/core": "2.6.1",
"capitalize": "2.0.4",
"dotenv": "10.0.0",
"graphql-config": "4.3.0",
"graphql-config": "5.0.2",
"graphql-tag": "2.12.6",
"graphql-ws": "5.10.0",
"@whatwg-node/fetch": "0.2.8",
"ws": "8.8.1",
"graphql": "16.6.0",
"nullthrows": "1.1.1"
"nullthrows": "1.1.1",
"@graphql-tools/code-file-loader": "8.0.1"
},
"resolutions": {
"cosmiconfig": "^5.0.1"
Expand Down
91 changes: 55 additions & 36 deletions packages/vscode-graphql-execution/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
languages,
Uri,
ViewColumn,
// Command,
// Disposable,
} from 'vscode';

import { GraphQLContentProvider } from './providers/exec-content';
Expand All @@ -29,7 +31,7 @@ export function activate(context: ExtensionContext) {

if (config.debug) {
// eslint-disable-next-line no-console
console.log('Extension "vscode-graphql" is now active!');
console.log('Extension "vscode-graphql-execution" is now active!');
}

const commandShowOutputChannel = commands.registerCommand(
Expand All @@ -41,7 +43,7 @@ export function activate(context: ExtensionContext) {
context.subscriptions.push(commandShowOutputChannel);

// const settings = workspace.getConfiguration("vscode-graphql-execution")

// let provider: GraphQLCodeLensProvider;
const registerCodeLens = () => {
context.subscriptions.push(
languages.registerCodeLensProvider(
Expand All @@ -53,51 +55,68 @@ export function activate(context: ExtensionContext) {
'graphql',
],
new GraphQLCodeLensProvider(outputChannel),
),
);
),
);
};


// if (settings.showExecCodelens !== false) {
registerCodeLens();
// }

workspace.onDidChangeConfiguration(() => {
// const newSettings = workspace.getConfiguration("vscode-graphql-execution")
// if (newSettings.showExecCodeLens !== false) {
registerCodeLens();
// }
});

const commandContentProvider = commands.registerCommand(
'vscode-graphql-execution.contentProvider',
(literal: ExtractedTemplateLiteral) => {
const uri = Uri.parse('graphql://authority/graphql');
// let commandContentProvider: Disposable;

const panel = window.createWebviewPanel(
'vscode-graphql-execution.results-preview',
'GraphQL Execution Result',
ViewColumn.Two,
{},
);
const registerContentProvider = () => {
return commands.registerCommand(
'vscode-graphql-execution.contentProvider',
(literal: ExtractedTemplateLiteral) => {
const uri = Uri.parse('graphql://authority/graphql');

const panel = window.createWebviewPanel(
'vscode-graphql-execution.results-preview',
'GraphQL Execution Result',
ViewColumn.Two,
{},
);

const contentProvider = new GraphQLContentProvider(
uri,
outputChannel,
literal,
panel,
);
const registration = workspace.registerTextDocumentContentProvider(
'graphql',
contentProvider,
);
context.subscriptions.push(registration);
panel.webview.html = contentProvider.getCurrentHtml();
},
);
}

const contentProvider = new GraphQLContentProvider(
uri,
outputChannel,
literal,
panel,
);
const registration = workspace.registerTextDocumentContentProvider(
'graphql',
contentProvider,
);
context.subscriptions.push(registration);
panel.webview.html = contentProvider.getCurrentHtml();
},
);
context.subscriptions.push(commandContentProvider);
const provider = registerContentProvider()
context.subscriptions.push(provider);

// workspace.onDidChangeConfiguration(async () => {
// // const newSettings = workspace.getConfiguration("vscode-graphql-execution")
// // if (newSettings.showExecCodeLens !== false) {
// commandContentProvider.dispose()
// // }
// });
workspace.onDidSaveTextDocument(async (e) =>{
await window.showErrorMessage('saved')
if (e.fileName.includes('graphql.config') || e.fileName.includes('graphqlrc')) {
await window.showErrorMessage('heyyy')
provider.dispose()
const newprovider = registerContentProvider()
context.subscriptions.push(newprovider);
}
})
}

export function deactivate() {
// eslint-disable-next-line no-console
console.log('Extension "vscode-graphql-execution" is now de-active!');
}
} // documents: ["./src/*.ts"],
16 changes: 9 additions & 7 deletions packages/vscode-graphql-execution/src/helpers/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,15 @@ export class NetworkHelper {
projectConfig,
);

const fragmentInfos = await getFragmentDependenciesForAST(
literal.ast,
fragmentDefinitions,
);

for (const fragmentInfo of fragmentInfos) {
literal.content = fragmentInfo.content + '\n' + literal.content;
if(fragmentDefinitions) {
const fragmentInfos = await getFragmentDependenciesForAST(
literal.ast,
fragmentDefinitions,
);

for (const fragmentInfo of fragmentInfos) {
literal.content = fragmentInfo.content + '\n' + literal.content;
}
}

const parsedOperation = gql`
Expand Down
42 changes: 23 additions & 19 deletions packages/vscode-graphql-execution/src/helpers/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,26 +123,30 @@ export class SourceHelper {
}
async getFragmentDefinitions(
projectConfig: GraphQLProjectConfig,
): Promise<Map<string, FragmentInfo>> {
const sources = await projectConfig.getDocuments();
const { fragmentDefinitions } = this;

for (const source of sources) {
visit(source.document as DocumentNode, {
FragmentDefinition(node) {
const existingDef = fragmentDefinitions.get(node.name.value);
const newVal = print(node);
if ((existingDef && existingDef.content !== newVal) || !existingDef) {
fragmentDefinitions.set(node.name.value, {
definition: node,
content: newVal,
filePath: source.location,
});
}
},
});
): Promise<Map<string, FragmentInfo> | void> {
try {
const sources = await projectConfig.getDocuments();
const { fragmentDefinitions } = this;

for (const source of sources) {
visit(source.document as DocumentNode, {
FragmentDefinition(node) {
const existingDef = fragmentDefinitions.get(node.name.value);
const newVal = print(node);
if ((existingDef && existingDef.content !== newVal) || !existingDef) {
fragmentDefinitions.set(node.name.value, {
definition: node,
content: newVal,
filePath: source.location,
});
}
},
});
}
return fragmentDefinitions;
} catch(err) {
this.outputChannel.append(`${err}`)
}
return fragmentDefinitions;
}

extractAllTemplateLiterals(
Expand Down
56 changes: 37 additions & 19 deletions packages/vscode-graphql-execution/src/providers/exec-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@ import {
WorkspaceFolder,
} from 'vscode';
import type { ExtractedTemplateLiteral } from '../helpers/source';
import { loadConfig, GraphQLProjectConfig } from 'graphql-config';
import { loadConfig, GraphQLProjectConfig, GraphQLExtensionDeclaration } from 'graphql-config';
import { visit, VariableDefinitionNode } from 'graphql';
import { NetworkHelper } from '../helpers/network';
import { SourceHelper, GraphQLScalarTSType } from '../helpers/source';
import type { Endpoints, Endpoint } from 'graphql-config/extensions/endpoints';
import { CodeFileLoader } from '@graphql-tools/code-file-loader'

const LanguageServiceExecutionExtension: GraphQLExtensionDeclaration = api => {
// For schema
api.loaders.schema.register(new CodeFileLoader());
// For documents
api.loaders.documents.register(new CodeFileLoader());

return { name: 'languageServiceExecution' };
}

export type UserVariables = { [key: string]: GraphQLScalarTSType };

Expand All @@ -29,6 +39,7 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {
private panel: WebviewPanel;
private rootDir: WorkspaceFolder | undefined;
private literal: ExtractedTemplateLiteral;
private _projectConfig: GraphQLProjectConfig | undefined;

// Event emitter which invokes document updates
private _onDidChange = new EventEmitter<Uri>();
Expand Down Expand Up @@ -127,10 +138,8 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {
this.updatePanel();
}

async loadEndpoint(
projectConfig?: GraphQLProjectConfig,
): Promise<Endpoint | null> {
let endpoints: Endpoints = projectConfig?.extensions?.endpoints;
async loadEndpoint(): Promise<Endpoint | null> {
let endpoints: Endpoints = this._projectConfig?.extensions?.endpoints;

if (!endpoints) {
endpoints = {
Expand All @@ -139,11 +148,11 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {

this.update(this.uri);
this.updatePanel();
if (projectConfig?.schema) {
if (this._projectConfig?.schema) {
this.outputChannel.appendLine(
"Warning: endpoints missing from graphql config. will try 'schema' value(s) instead",
);
const { schema } = projectConfig;
const { schema } = this._projectConfig;
if (schema && Array.isArray(schema)) {
for (const s of schema) {
if (this.validUrlFromSchema(s as string)) {
Expand Down Expand Up @@ -183,16 +192,17 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {
this.reportError('Error: this file is outside the workspace.');
return;
}
const config = await loadConfig({
rootDir: rootDir.uri.fsPath,
legacy: true,
});
const projectConfig = config?.getProjectForFile(this.literal.uri);


await this.loadConfig();
const projectConfig = this._projectConfig;

if (!projectConfig) {
return;
return
}

const endpoint = await this.loadEndpoint(projectConfig);

const endpoint = await this.loadEndpoint();
if (endpoint?.url) {
const variableDefinitionNodes: VariableDefinitionNode[] = [];
visit(this.literal.ast, {
Expand Down Expand Up @@ -249,14 +259,22 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {
this.reportError('Error: this file is outside the workspace.');
return;
}
const config = await loadConfig({ rootDir: rootDir.uri.fsPath });
const projectConfig = config?.getProjectForFile(literal.uri);
this.reportError(rootDir.uri.fsPath)

if (!projectConfig!.schema) {
const config = await loadConfig({
rootDir: rootDir.uri.fsPath,
throwOnEmpty: false,
throwOnMissing: false,
legacy: true,
extensions: [LanguageServiceExecutionExtension]
});
this._projectConfig = config?.getProjectForFile(literal.uri);
this.reportError(JSON.stringify(this._projectConfig?.schema ?? {}))

// eslint-disable-next-line unicorn/consistent-destructuring
if (!this._projectConfig?.schema) {
this.reportError('Error: schema from graphql config');
return;
}
return projectConfig;
}

get onDidChange(): Event<Uri> {
Expand Down
Loading

0 comments on commit fe84847

Please sign in to comment.