libpg-query-node

The real PostgreSQL parser, compiled to WebAssembly, for parsing SQL into ASTs in any JavaScript runtime.

Library
npm
v17.7.4
78stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
63/100Good
Development Activity80
Maintenance44
Community48
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
66/100Good
Architecture65
Code Quality78
Innovation75
Learning Curve45

libpg-query is a WebAssembly build of PostgreSQL’s own SQL parser (libpg_query), exposing the exact grammar and lexer the real Postgres server uses inside a Node.js- or browser-compatible JavaScript package. Rather than reimplementing SQL parsing with a hand-written grammar, it compiles the actual Postgres C parser to WASM, so the resulting abstract syntax tree matches what Postgres itself would produce, including edge cases, dialect quirks, and version-specific syntax.

The package ships as multiple npm dist-tags (pg13 through pg18), each built against a specific PostgreSQL major version’s grammar, letting consumers pin the parser to the SQL dialect their database actually runs. It exposes a minimal parse/parseSync API that returns a JSON parse tree, with structured SqlError details (cursor position, source file, line number) instead of an opaque parse failure, and requires no native compilation or node-gyp step on install.

What You Get

  • Full PostgreSQL grammar parsing via the real Postgres C parser compiled to WASM
  • Version-pinned builds (PG13 through PG18) selectable via npm dist-tags
  • Async parse() and synchronous parseSync() entry points with automatic or explicit WASM initialization
  • Structured SqlError objects carrying cursor position, filename, line number, and context for parse failures
  • Zero native runtime dependencies — no node-gyp, no platform-specific binaries to build

Common Use Cases

  • Building SQL linters and static-analysis tools that validate queries before execution
  • Powering query builders and ORMs (e.g. pgsql-parser) that need to construct or introspect SQL programmatically
  • Parsing DDL/DML for migration and schema-diffing tooling
  • Feeding SQL editors and IDE plugins with precise syntax-error positions while typing

Under The Hood

Architecture The repo is a pnpm monorepo where each supported PostgreSQL major version (13 through 18) lives in its own versions/<N> package, each with a generated src/index.ts (templated from the shared templates/ directory and synced via copy:templates) that wraps a thin C shim (src/wasm_wrapper.c) compiled to WASM via a per-version Makefile invoking Emscripten. The JS layer marshals strings across the WASM boundary manually (stringToPtr/ptrToString, _malloc/_free) and reads the PgQueryParseResult/PgQueryError C structs directly by pointer offset before JSON-parsing the returned parse tree. There is effectively one layer of indirection: JS API surface directly reflects the WASM export surface, so any change to wasm_wrapper.c or the underlying libpg_query fork propagates straight through to the public parse/parseSync functions.

Tech Stack TypeScript for the public API, C for the WASM wrapper around a constructive-io/libpg_query fork of the upstream pganalyze/libpg_query project, Emscripten (via a Dockerized emsdk image) for the C-to-WASM build, and pnpm workspaces to manage the six version packages plus companion @pgsql/types, @pgsql/enums, and @pgsql/parser packages in the same repo. The published libpg-query package (currently dist-tag latest = PG17, 17.7.4) depends only on @pgsql/types at runtime.

Code Quality Each version package has its own test suite using Node’s built-in node:test runner, covering sync/async parsing, multi-statement queries, and structured parse-error shapes (parsing.test.js, errors.test.js); the PG18 package additionally tests fingerprint, normalize, plpgsql, and scan since it ships the full API. CI runs a build+test matrix across all six PG versions on GitHub Actions, with a documented Docker-based WASM build path. Errors are explicit and typed via a custom SqlError class rather than swallowed, and the public API is fully typed. No dedicated lint config was found at the repo root.

API Design The public surface is intentionally tiny: parse() (async, auto-initializing) and parseSync() (requires an explicit loadModule() call first), plus a formatSqlError() helper for human-readable diagnostics. This removes the most common footgun with WASM modules — forgetting to await initialization — for the recommended async path, while still offering a synchronous escape hatch for hot loops. Multi-version support via npm dist-tags (pg13-pg18) is a deliberate DX choice: consumers get exact-version grammar matching without needing to depend on a differently-named package per PostgreSQL version.

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

Search