diff --git a/package.json b/package.json index 4110219..aef3b91 100644 --- a/package.json +++ b/package.json @@ -280,6 +280,10 @@ "SQL-Formatter-VSCode.paramTypes": { "type": "object", "markdownDescription": "Specifies parameter placeholders types to support." + }, + "SQL-Formatter-VSCode.configFilePath": { + "type": "string", + "markdownDescription": "Specifies the path to the configuration file to configure sql-formatter; takes precedence over other settings." } } } diff --git a/src/config.ts b/src/config.ts index 568eab8..fa94f69 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,7 @@ import { FormatOptionsWithLanguage, FormatOptions, } from 'sql-formatter'; +import { validateConfig } from 'sql-formatter/dist/cjs/validateConfig'; type ParamTypes = FormatOptions['paramTypes']; @@ -53,3 +54,19 @@ const createIndentationConfig = ( }; } }; + +export const getConfigFromPath = async ( + configFilePath: string, +): Promise => { + try { + const fileContent = await vscode.workspace.fs.readFile(vscode.Uri.file(configFilePath)); + const configString = Buffer.from(fileContent).toString('utf8'); + const parsed = JSON.parse(configString); + return validateConfig(parsed); + } catch (error) { + vscode.window.showErrorMessage( + `Unable to read config file from path ${configFilePath}:\n${error}`, + ); + return undefined; + } +}; diff --git a/src/formatSelection.ts b/src/formatSelection.ts index 6e7250c..b45159d 100644 --- a/src/formatSelection.ts +++ b/src/formatSelection.ts @@ -1,16 +1,17 @@ import * as vscode from 'vscode'; -import { createConfig } from './config'; +import { createConfig, getConfigFromPath } from './config'; import { sqlDialects } from './sqlDialects'; import { formatEditorText } from './formatEditorText'; -export function formatSelection() { +export async function formatSelection() { const editor = vscode.window.activeTextEditor; if (!editor) { return; } try { - replaceEachSelection(editor, text => formatEditorText(text, createConfigForEditor(editor))); + const config = await createConfigForEditor(editor); + replaceEachSelection(editor, text => formatEditorText(text, config)); } catch (e) { vscode.window.showErrorMessage('Unable to format SQL:\n' + e); } @@ -22,12 +23,16 @@ function replaceEachSelection(editor: vscode.TextEditor, fn: (code: string) => s }); } -const createConfigForEditor = (editor: vscode.TextEditor) => - createConfig( - vscode.workspace.getConfiguration('SQL-Formatter-VSCode'), - editorFormattingOptions(editor), - detectSqlDialect(editor), +const createConfigForEditor = async (editor: vscode.TextEditor) => { + const extensionConfiguration = vscode.workspace.getConfiguration('SQL-Formatter-VSCode'); + const configFilePath = extensionConfiguration.get('configFilePath'); + const configFromPath = configFilePath ? await getConfigFromPath(configFilePath) : undefined; + const formattingOptions = editorFormattingOptions(editor); + const detectedSqlDialect = detectSqlDialect(editor); + return ( + configFromPath ?? createConfig(extensionConfiguration, formattingOptions, detectedSqlDialect) ); +}; const detectSqlDialect = (editor: vscode.TextEditor) => sqlDialects[editor.document.languageId] ?? 'sql';