sql-formatter

A JavaScript/TypeScript library and CLI that pretty-prints SQL queries across 20+ dialects with configurable style options.

Library
npm
v15.9.0
2,899 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
82 /100 Excellent
Development Activity 72
Maintenance 88
Community 68
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
86 /100 Excellent
Architecture 85
Code Quality 88
Innovation 84
Learning Curve 88

sql-formatter is a whitespace formatter for SQL that turns cramped or inconsistently styled queries into readable, indented output. It ships as both an importable library (format(query, options)) and a standalone CLI, and understands the syntactic quirks of over twenty SQL dialects — from MySQL, PostgreSQL, and SQLite to BigQuery, Snowflake, Redshift, and Trino — so formatting decisions respect each engine’s actual grammar rather than applying one generic SQL style to everything.

Under the hood it tokenizes and parses each query into an AST using a Nearley-generated grammar, then walks that tree to lay out keywords, indentation, and line breaks according to caller-supplied options (keyword case, tab width, indent style, and more). It also supports placeholder/parameter substitution for prepared statements and disable/enable comment blocks for skipping SQL the parser can’t yet handle, making it a practical fit for SQL linters, query builders, ORMs, database GUIs, and editor/IDE tooling that need to render SQL consistently.

What You Get

  • A format() / formatDialect() API that formats a SQL string in one call, with a SqlLanguage union type covering 20+ dialects for TypeScript autocompletion.
  • A sql-formatter CLI (npx sql-formatter) that reads from stdin or a file, supports --fix in-place rewriting, and accepts a JSON/.sql-formatter.json config file.
  • Fine-grained style controls — keyword case, identifier/data-type/function case, tab width vs. tabs, indent style, expression width, and where logical operators break onto new lines.
  • Prepared-statement placeholder replacement (params option) so parameterized queries can be rendered with real values substituted in for readability.
  • /* sql-formatter-disable */ / /* sql-formatter-enable */ comment markers that let a section of SQL bypass parsing entirely, so one unsupported construct doesn’t block formatting the rest of a file.

Common Use Cases

  • Formatting SQL embedded in application code (template literals, ORM query builders) as part of a lint-staged or pre-commit hook.
  • Powering the ‘format query’ button in SQL editors, database GUIs, or internal admin tools.
  • Normalizing SQL style across a team or codebase via CI checks, independent of which dialect each service’s database uses.
  • Pretty-printing generated SQL (from query builders, migrations, or LLM output) before displaying it to a developer or end user.

Under The Hood

Architecture: The pipeline is a classic tokenize → parse → format chain. src/lexer/Tokenizer.ts and TokenizerEngine.ts turn raw SQL text into tokens using dialect-specific TokenizerOptions; src/parser/grammar.ne (a Nearley grammar, compiled to grammar.ts via the grammar build step) parses those tokens into an AST defined in src/parser/ast.ts. src/formatter/Formatter.ts and ExpressionFormatter.ts then walk the AST, applying Layout/Indentation/InlineLayout rules to produce the final string. Each of the 20+ entries under src/languages/<dialect>/ supplies a DialectOptions object (reserved keywords, operators, tokenizer quirks) that dialect.ts and allDialects.ts assemble into the dialect registry consumed by sqlFormatter.ts’s format()/formatDialect() entry points — new dialects are added by implementing this one config object rather than forking the formatter logic. Tech Stack: Written in strict TypeScript ("strict": true, noImplicitReturns) targeting ES6, built with tsc for dual CJS/ESM output plus a Webpack UMD bundle (dist/sql-formatter.min.js) for browser/unpkg use. Runtime dependencies are minimal — just nearley (parser runtime) and argparse (CLI argument parsing) — keeping the installed footprint small for a library with 4M+ weekly downloads. The build is orchestrated with pnpm workspaces and npm-run-all for parallel CJS/ESM/Webpack builds. Code Quality: The test suite (76 test files under test/) uses a shared-behavior pattern — behavesLikeMariaDbFormatter.ts, behavesLikeSqlFormatter.ts, etc. — so dialects that share grammar (e.g. MySQL/MariaDB, Redshift/PostgreSQL) reuse one behavior spec instead of duplicating assertions, plus feature-scoped modules under test/features/ and test/options/ (joins, window functions, CTEs, case sensitivity, etc.) that are mixed into every applicable dialect’s test file. CI runs ts:check, pretty:check, eslint, and the full Jest suite with coverage collection on every change (pnpm run check). API Design: The public surface is intentionally small — one format(query, options) call for the common case, with formatDialect() for consumers that want to pass a DialectOptions object directly instead of a string language name. Every dialect and option type is re-exported from src/index.ts for full TypeScript inference, defaults are sensible (keywordCase: 'preserve' avoids surprising rewrites), and each configuration option has its own dedicated doc page under docs/ with before/after examples, keeping the learning curve low despite the breadth of dialects supported.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers