sql-formatter-plus
A JavaScript library that pretty-prints Standard SQL, N1QL, DB2, and PL/SQL queries with configurable indentation and dialect-aware tokenization.
Repository Health
Technical Analysis
sql-formatter-plus is a fork of the original SQL Formatter library that reformats the whitespace in SQL queries so they’re readable, without altering the query’s semantics. It tokenizes the input string with a dialect-specific regex tokenizer, then walks the resulting tokens through a formatter that decides indentation, line breaks, and keyword casing based on token type (top-level reserved word, newline reserved word, opening/closing parenthesis, placeholder, comment, and so on).
Four dialects are supported out of the box — Standard SQL, Couchbase N1QL, IBM DB2, and Oracle PL/SQL — each implemented as its own class supplying dialect-specific reserved word lists to a shared Tokenizer/Formatter core. Beyond the upstream project, this fork adds an uppercase option to normalize keyword casing, a linesBetweenQueries option to control spacing between statements, and fixes for unicode handling, non-Unix line endings, and multi-statement indentation.
What You Get
- A single
format(query, cfg)entry point that accepts a dialect, indent string, uppercase flag, blank-line count, and named/indexed placeholder values - Dialect-aware tokenization that classifies reserved words, strings, comments, placeholders, and operators differently per SQL variant
- Automatic inline-block collapsing so short expressions like
COUNT(*)orDECIMAL(7,2)stay on one line instead of being split across indentation levels - Named (
@foo,:foo) and indexed (?) placeholder substitution via aparamsconfig object - A prebuilt UMD bundle in
dist/for use directly in a<script>tag aswindow.sqlFormatter, alongside the CommonJS build for bundler-based projects
Common Use Cases
- Pretty-printing raw SQL migration files before a code review so whitespace noise doesn’t obscure the actual schema change
- Formatting N1QL queries in Couchbase-backed admin tools using the same API as Standard SQL formatting
- Dropping the UMD build into a browser-based SQL editor or query-building tool with no bundler required
- Normalizing dynamically constructed SQL before writing it to application logs so slow-query output stays readable
Under The Hood
Architecture
Execution flows from src/sqlFormatter.js, which switches on cfg.language to select one of four dialect classes (StandardSqlFormatter, N1qlFormatter, Db2Formatter, PlSqlFormatter), each of which constructs a Tokenizer (src/core/Tokenizer.js) with its own reserved-word lists and hands the query to a shared Formatter (src/core/Formatter.js). The tokenizer turns the input into an ordered list of typed tokens (whitespace, comment, string, paren, placeholder, reserved word variants, operator), and the formatter walks that list maintaining two collaborator objects — Indentation (tracks top-level vs block-level indent depth as a stack) and InlineBlock (look-ahead bookkeeping that decides whether a parenthesized expression is short enough to stay on one line) — plus a Params helper for placeholder substitution. This is a clean, layered pipeline (tokenize -> classify -> emit) where the dialect classes are the only thing that would need to change to add a fifth SQL variant; the core tokenizer/formatter logic is dialect-agnostic and driven entirely by the reserved-word configuration passed in.
Tech Stack
The library itself has a minimal runtime footprint, depending only on lodash (used narrowly for isEmpty, escapeRegExp, repeat, and last) and @babel/polyfill. The build pipeline compiles ES modules to CommonJS via Babel (@babel/preset-env plus babel-plugin-add-module-exports) for the lib/ output consumed by Node/bundler users, and bundles a browser-ready UMD file via Webpack for the dist/ output referenced directly from index.html. There is no runtime parser-generator dependency — dialect grammars are expressed as plain reserved-word arrays consumed by hand-written regexes.
Code Quality
Testing is thorough for a library this size: a shared behavesLikeSqlFormatter.js helper (roughly 500 lines) defines a battery of formatting assertions that each dialect’s test file (StandardSqlFormatterTest.js, N1qlFormatterTest.js, Db2FormatterTest.js, PlSqlFormatterTest.js) runs against its own formatter instance, avoiding duplicated test logic across dialects. Jest is configured with coverage collection, and CI (Travis) runs npm run check — lint, Prettier format check, and tests — followed by a build step and a Coveralls upload. ESLint extends a shared config plus eslint-config-prettier, and every core class carries JSDoc comments describing its parameters. There’s no TypeScript, so type safety relies entirely on this test coverage and documentation rather than compile-time checks.
API Design
The public surface is intentionally small: a single format(query, cfg) function with a flat configuration object (language, indent, uppercase, linesBetweenQueries, params) and sensible defaults for every option, so the common case (sqlFormatter.format('SELECT * FROM table1')) requires no configuration at all. The default export bundles the function under a { format } object matching common formatter-library conventions, and an unsupported language value throws an explicit, descriptive error rather than failing silently or producing malformed output.