UNPKG

xy-sql-formatter

Version:

Format whitespace in a SQL query to make it more readable

64 lines (54 loc) 1.97 kB
import { FormatOptions } from '../FormatOptions.js'; import { indentString } from './config.js'; import Params from './Params.js'; import { createParser } from '../parser/createParser.js'; import { StatementNode } from '../parser/ast.js'; import { Dialect } from '../dialect.js'; import ExpressionFormatter from './ExpressionFormatter.js'; import Layout, { WS } from './Layout.js'; import Indentation from './Indentation.js'; /** Main formatter class that produces a final output string from list of tokens */ export default class Formatter { private dialect: Dialect; private cfg: FormatOptions; private params: Params; constructor(dialect: Dialect, cfg: FormatOptions) { this.dialect = dialect; this.cfg = cfg; this.params = new Params(this.cfg.params); } /** * Formats an SQL query. * @param {string} query - The SQL query string to be formatted * @return {string} The formatter query */ public format(query: string): string { const ast = this.parse(query); const formattedQuery = this.formatAst(ast); return formattedQuery.trimEnd(); } private parse(query: string): StatementNode[] { return createParser(this.dialect.tokenizer).parse(query, this.cfg.paramTypes || {}); } private formatAst(statements: StatementNode[]): string { return statements .map(stat => this.formatStatement(stat)) .join('\n'.repeat(this.cfg.linesBetweenQueries + 1)); } private formatStatement(statement: StatementNode): string { const layout = new ExpressionFormatter({ cfg: this.cfg, dialectCfg: this.dialect.formatOptions, params: this.params, layout: new Layout(new Indentation(indentString(this.cfg))), }).format(statement.children); if (!statement.hasSemicolon) { // do nothing } else if (this.cfg.newlineBeforeSemicolon) { layout.add(WS.NEWLINE, ';'); } else { layout.add(WS.NO_NEWLINE, ';'); } return layout.toString(); } }