All files / commands/sparql execute-describe-query.ts

89.28% Statements 25/28
95% Branches 19/20
100% Functions 3/3
88.88% Lines 24/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75              1x     9x 9x   9x 9x 9x 9x               9x     9x 1x 1x     8x   8x         8x 9x             9x 9x   8x     8x 1x 1x     7x               7x   7x            
import * as vscode from 'vscode';
import { render } from 'triplate';
import { container } from 'tsyringe';
import { ServiceToken } from '@src/services/tokens';
import { IDocumentConnectionService, ISparqlConnectionRegistry, ISparqlQueryService, ITripleStoreConfigService } from '@src/languages/sparql/services';
import { getLog } from '@src/utilities/vscode/log';
 
export const executeDescribeQuery = {
	id: 'mentor.command.executeDescribeQuery',
	handler: async (documentUri: vscode.Uri | string, resourceIri: string, graphIris?: string[], connectionId?: string) => {
		const uri = typeof documentUri === 'string' ? vscode.Uri.parse(documentUri) : documentUri;
		const document = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === uri.toString());
 
		const storeConfigService = container.resolve<ITripleStoreConfigService>(ServiceToken.StoreConfigService);
		const documentConnectionService = container.resolve<IDocumentConnectionService>(ServiceToken.DocumentConnectionService);
		const connectionRegistry = container.resolve<ISparqlConnectionRegistry>(ServiceToken.SparqlConnectionRegistry);
		const queryService = container.resolve<ISparqlQueryService>(ServiceToken.SparqlQueryService);
 
		// Reuse the exact connection the originating query ran against when it is known
		// (the results view forwards it for every binding-table describe). This keeps the
		// describe on the same store even for background/generated queries whose source
		// document targets a different connection. Otherwise fall back to the connection
		// configured for the source document (or notebook cell), defaulting to the
		// workspace store when none is set.
		const connection = (connectionId ? connectionRegistry.getConnection(connectionId) : undefined)
			?? (document ? documentConnectionService.getConnectionForDocument(document.uri) : undefined);
 
		if (!connection) {
			getLog().warn(`Unable to resolve a connection for describe query: ${uri.toString()}`);
			return;
		}
 
		const template = storeConfigService.getQueryTemplate(connection, 'describe');
 
		Iif (!template) {
			vscode.window.showErrorMessage('Could not resolve a "describe" query template for this connection.');
			return;
		}
 
		const query = render(template, { resourceIri, graphIris: graphIris ?? [] });
		const inferenceEnabled = document
			? documentConnectionService.getInferenceEnabledForDocument(document.uri)
			: undefined;
 
		// Run the query entirely in the background against the selected connection and only reveal
		// the resulting triples as a Turtle document. The SPARQL results panel is intentionally not
		// opened for a DESCRIBE — it would otherwise pop up empty while the quads open in an editor.
		try {
			const result = await vscode.window.withProgress(
				{ location: vscode.ProgressLocation.Window, title: `Describing ${resourceIri}…` },
				() => queryService.executeQueryOnConnection(query, connection, inferenceEnabled)
			);
 
			if (!result || result.type !== 'quads') {
				vscode.window.showInformationMessage(`No description found for ${resourceIri}.`);
				return;
			}
 
			const resultDocument = await vscode.workspace.openTextDocument({
				content: result.data,
				language: 'turtle'
			});
 
			// Bind the result document to the same connection the describe ran against, so its
			// connection indicator reflects the originating store and any follow-up queries run
			// from it target that store rather than defaulting to the workspace.
			await documentConnectionService.setQuerySourceForDocument(resultDocument.uri, connection.id);
 
			await vscode.window.showTextDocument(resultDocument, { preview: true });
		} catch (error: any) {
			vscode.window.showErrorMessage(`Failed to describe resource: ${error.message}`);
		}
	}
};