{"_id":"@clickhouse/parser","_rev":"5-8971907d64279473a6cdaf9b358cdf9e","name":"@clickhouse/parser","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@clickhouse/parser","version":"0.1.0","keywords":["clickhouse","sql","parser","typescript"],"license":"Apache-2.0","_id":"@clickhouse/parser@0.1.0","maintainers":[{"name":"serdec","email":"sdecri@gmail.com"},{"name":"serge.klochkov","email":"hypnoash@gmail.com"},{"name":"mikhail.shustov-clickhouse","email":"mikhail.shustov@clickhouse.com"},{"name":"michael.anastasakis","email":"michael.anastasakis@clickhouse.com"},{"name":"4b819b88c84b","email":"peter.leonov@clickhouse.com"},{"name":"santrancisco","email":"san.tran@ebfe.pw"},{"name":"hoorayimhelping","email":"d.w.schwarz@gmail.com"},{"name":"tresleches","email":"julio@clickhouse.com"},{"name":"vineethasok","email":"vineeth.asokkumar@clickhouse.com"}],"dist":{"shasum":"4da731ead2eae65a00493ec96a0f53e40991ef6a","tarball":"https://registry.npmjs.org/@clickhouse/parser/-/parser-0.1.0.tgz","fileCount":9,"integrity":"sha512-HScEeTIv5e5nX/3eLddixFgtMNti53i/qBC38US+09OLutWq2GOXUCKzxCIEXMrfTHtLBqTZaVw/V/UgLZa4pQ==","signatures":[{"sig":"MEUCIQDwnGunGTxV/66/gKScQ2RlWD6GXG/14ogTvVYSyql0XAIgLGfTAMQ1x7HtV/RLElBFTXTWYjVF7LBt26nOhfmW2lw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15322235},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"b7d1648c671c95af9ba7ec880e01ab43841cbb6a","private":false,"scripts":{"lint":"eslint .","test":"npm run generate:parser && vitest run","build":"npm run generate:parser && tsup","parse":"tsx scripts/parse.ts","format":"tsx scripts/format.ts","explain":"tsx scripts/explain.ts","release":"npm publish --access public","diff:ast":"tsx scripts/diff-ast.ts","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","explain:ch":"node scripts/clickhouse-explain.js","test:watch":"vitest","diff:format":"tsx scripts/diff-format.ts","diff:explain":"tsx scripts/diff-explain.ts","prepublishOnly":"npm run typecheck && npm run lint && npm run test && npm run build","generate:parser":"peggy --cache --format commonjs --dts --output src/parser.js src/grammar.pegjs","test:update-snapshots":"vitest run tests/query-params.test.ts --update","generate:expected-outputs":"npx tsx scripts/generate-expected-outputs.ts"},"_npmUser":{"name":"4b819b88c84b","email":"peter.leonov@clickhouse.com"},"_npmVersion":"11.16.0","description":"A TypeScript parser for ClickHouse SQL","directories":{},"_nodeVersion":"24.6.0","dependencies":{"zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","diff":"^9.0.0","tsup":"^8.0.0","peggy":"^5.1.0","eslint":"^9.0.0","vitest":"^4.1.8","prettier":"^3.0.0","minimatch":"^10.2.5","@eslint/js":"^9.0.0","typescript":"^5.0.0","@types/diff":"^7.0.2","@types/node":"^25.9.2","typescript-eslint":"^8.0.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/parser_0.1.0_1780912641744_0.15215771560282976","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@clickhouse/parser","version":"0.2.1","keywords":["clickhouse","sql","parser","typescript"],"license":"Apache-2.0","_id":"@clickhouse/parser@0.2.1","maintainers":[{"name":"serdec","email":"sdecri@gmail.com"},{"name":"serge.klochkov","email":"hypnoash@gmail.com"},{"name":"mikhail.shustov-clickhouse","email":"mikhail.shustov@clickhouse.com"},{"name":"michael.anastasakis","email":"michael.anastasakis@clickhouse.com"},{"name":"4b819b88c84b","email":"peter.leonov@clickhouse.com"},{"name":"santrancisco","email":"san.tran@ebfe.pw"},{"name":"hoorayimhelping","email":"d.w.schwarz@gmail.com"},{"name":"tresleches","email":"julio@clickhouse.com"},{"name":"vineethasok","email":"vineeth.asokkumar@clickhouse.com"}],"homepage":"https://github.com/ClickHouse/clickhouse-js-parser#readme","bugs":{"url":"https://github.com/ClickHouse/clickhouse-js-parser/issues"},"dist":{"shasum":"b266a0e971400bb6db9908abd086fc77266e82b9","tarball":"https://registry.npmjs.org/@clickhouse/parser/-/parser-0.2.1.tgz","fileCount":9,"integrity":"sha512-Si87lKbiTuSF/eOthsT7vjPz6hXBpVEkBaeE0ay7G1WwbO8x6x0VnXWvelyrBYqPgD5xk145tTiog1tNKWBE0w==","signatures":[{"sig":"MEUCIGEGffM3IbSUtw3ppqPda7k1BzJpFVdojKPka+n54NiqAiEA0g4TGEJLYcJyL1143R5z+7YzxvLBWmQyjv9N08NsTJQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@clickhouse%2fparser@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":17096893},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"174e3fc945fc46f4c021332632ddd552d5ebc9c9","private":false,"scripts":{"lint":"eslint .","test":"npm run generate:parser && vitest run","build":"npm run generate:parser && tsup","parse":"tsx scripts/parse.ts","format":"tsx scripts/format.ts","explain":"tsx scripts/explain.ts","release":"npm publish --access public","diff:ast":"tsx scripts/diff-ast.ts","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","explain:ch":"node scripts/clickhouse-explain.js","test:watch":"vitest","diff:format":"tsx scripts/diff-format.ts","diff:explain":"tsx scripts/diff-explain.ts","prepublishOnly":"npm run typecheck && npm run lint && npm run test && npm run build","generate:parser":"peggy --cache --format commonjs --dts --output src/parser.js src/grammar.pegjs","test:update-snapshots":"vitest run tests/query-params.test.ts --update","generate:expected-outputs":"npx tsx scripts/generate-expected-outputs.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18b78e94-87c7-4680-acd5-55c4c1010306"}},"repository":{"url":"git+https://github.com/ClickHouse/clickhouse-js-parser.git","type":"git"},"_npmVersion":"11.13.0","description":"A TypeScript parser for ClickHouse SQL","directories":{},"_nodeVersion":"24.16.0","dependencies":{"zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","diff":"^9.0.0","tsup":"^8.0.0","peggy":"^5.1.0","eslint":"^9.0.0","vitest":"^4.1.8","prettier":"^3.0.0","minimatch":"^10.2.5","@eslint/js":"^9.0.0","typescript":"^5.0.0","@types/diff":"^7.0.2","@types/node":"^25.9.2","typescript-eslint":"^8.0.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/parser_0.2.1_1781006944941_0.810897873021166","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@clickhouse/parser","version":"0.3.0","description":"A TypeScript parser for ClickHouse SQL","private":false,"repository":{"type":"git","url":"git+https://github.com/ClickHouse/clickhouse-js-parser.git"},"bugs":{"url":"https://github.com/ClickHouse/clickhouse-js-parser/issues"},"homepage":"https://github.com/ClickHouse/clickhouse-js-parser#readme","publishConfig":{"access":"public"},"main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"generate:parser":"peggy --cache --format commonjs --dts --output src/parser.js src/grammar.pegjs","build":"npm run generate:parser && tsup","typecheck":"tsc --noEmit","test":"npm run generate:parser && vitest run","test:watch":"vitest","test:update-snapshots":"vitest run tests/query-params.test.ts --update","lint":"eslint .","lint:fix":"eslint . --fix","prepublishOnly":"npm run typecheck && npm run lint && npm run test && npm run build","release":"npm publish --access public","generate:expected-outputs":"npx tsx scripts/generate-expected-outputs.ts","parse":"tsx scripts/parse.ts","format":"tsx scripts/format.ts","explain":"tsx scripts/explain.ts","explain:ch":"node scripts/clickhouse-explain.js","diff:ast":"tsx scripts/diff-ast.ts","diff:format":"tsx scripts/diff-format.ts","diff:explain":"tsx scripts/diff-explain.ts"},"keywords":["clickhouse","sql","parser","typescript"],"license":"Apache-2.0","devDependencies":{"@eslint/js":"^9.0.0","@types/diff":"^7.0.2","@types/node":"^25.9.2","diff":"^9.0.0","eslint":"^9.0.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","minimatch":"^10.2.5","peggy":"^5.1.0","prettier":"^3.0.0","tsup":"^8.0.0","tsx":"^4.22.4","typescript":"^5.0.0","typescript-eslint":"^8.0.0","vitest":"^4.1.8"},"dependencies":{"zod":"^4.3.6"},"gitHead":"0495c31497b204eafc60838c895c55f0c07e616f","_id":"@clickhouse/parser@0.3.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-VoUfcKzKalCNUY92iYkLYGzNg5FrVID7iSFnqDjV4DYvu8X4mJl1z5486zl+RBqsmYZ+L7koPrNiv1bQ0hrxGQ==","shasum":"e552174f5a244f775c32d29121197f5037b39594","tarball":"https://registry.npmjs.org/@clickhouse/parser/-/parser-0.3.0.tgz","fileCount":9,"unpackedSize":18131392,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@clickhouse%2fparser@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFzW8TpY7gRcXqhXFKKjpolSwpDFop1yQb99XHTKYK0PAiAgNkcqIx7txS2OdPQ8fAQrLLH4p5GclcthMehZYaRAhw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18b78e94-87c7-4680-acd5-55c4c1010306"}},"directories":{},"maintainers":[{"name":"mikhail.shustov-clickhouse","email":"mikhail.shustov@clickhouse.com"},{"name":"michael.anastasakis","email":"michael.anastasakis@clickhouse.com"},{"name":"4b819b88c84b","email":"peter.leonov@clickhouse.com"},{"name":"santrancisco","email":"san.tran@clickhouse.com"},{"name":"hoorayimhelping","email":"d.w.schwarz@gmail.com"},{"name":"tresleches","email":"julio@clickhouse.com"},{"name":"vineethasok","email":"vineeth.asokkumar@clickhouse.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/parser_0.3.0_1783630897481_0.9713263970246901"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-08T09:57:21.524Z","modified":"2026-07-09T21:01:38.180Z","0.1.0":"2026-06-08T09:57:21.910Z","0.2.1":"2026-06-09T12:09:05.122Z","0.3.0":"2026-07-09T21:01:37.724Z"},"bugs":{"url":"https://github.com/ClickHouse/clickhouse-js-parser/issues"},"license":"Apache-2.0","homepage":"https://github.com/ClickHouse/clickhouse-js-parser#readme","keywords":["clickhouse","sql","parser","typescript"],"repository":{"type":"git","url":"git+https://github.com/ClickHouse/clickhouse-js-parser.git"},"description":"A TypeScript parser for ClickHouse SQL","maintainers":[{"name":"mikhail.shustov-clickhouse","email":"mikhail.shustov@clickhouse.com"},{"name":"michael.anastasakis","email":"michael.anastasakis@clickhouse.com"},{"name":"4b819b88c84b","email":"peter.leonov@clickhouse.com"},{"name":"santrancisco","email":"san.tran@clickhouse.com"},{"name":"hoorayimhelping","email":"d.w.schwarz@gmail.com"},{"name":"tresleches","email":"julio@clickhouse.com"},{"name":"vineethasok","email":"vineeth.asokkumar@clickhouse.com"}],"readme":"# @clickhouse/parser\n\nA TypeScript parser for ClickHouse SQL. Parses ClickHouse SQL into a typed AST, with support for formatting back to SQL.\n\nExplore the parser output in the [playground](https://clickhouse.github.io/clickhouse-js-parser/).\n\n**Note:** This is alpha-level Claudeware. The API and AST formats are subject to change.\n\n## Installation\n\n```bash\nnpm install @clickhouse/parser\n```\n\n## Usage\n\n### Parsing SQL to AST\n\n```typescript\nimport { parse } from '@clickhouse/parser';\n\nconst ast = parse('SELECT id, name FROM users WHERE active = 1 ORDER BY name');\n```\n\n`parse()` accepts a string containing one or more ClickHouse SQL statements (semicolon-separated) and returns a `Statement[]` array.\n\nThe AST for the query above:\n\n```json\n[\n  {\n    \"type\": \"SelectWithUnionQuery\",\n    \"selects\": [\n      {\n        \"type\": \"SelectQuery\",\n        \"select\": [\n          { \"type\": \"Identifier\", \"name\": \"id\" },\n          { \"type\": \"Identifier\", \"name\": \"name\" }\n        ],\n        \"from\": {\n          \"type\": \"TablesInSelectQuery\",\n          \"children\": [\n            {\n              \"type\": \"TablesInSelectQueryElement\",\n              \"table_expression\": {\n                \"type\": \"TableExpression\",\n                \"database_and_table_name\": {\n                  \"type\": \"TableIdentifier\",\n                  \"name\": \"users\"\n                }\n              }\n            }\n          ]\n        },\n        \"where\": {\n          \"type\": \"Function\",\n          \"name\": \"equals\",\n          \"arguments\": [\n            { \"type\": \"Identifier\", \"name\": \"active\" },\n            { \"type\": \"Literal\", \"value_type\": \"UInt64\", \"value\": \"1\" }\n          ],\n          \"is_operator\": true\n        },\n        \"order_by\": [\n          {\n            \"type\": \"OrderByElement\",\n            \"expression\": { \"type\": \"Identifier\", \"name\": \"name\" },\n            \"direction\": \"ASC\"\n          }\n        ]\n      }\n    ]\n  }\n]\n```\n\nEach node has a `type` discriminator field that mirrors ClickHouse's native AST.\nSee [ast.ts](src/ast.ts) for all node types and their Zod schemas.\n\n#### Parse options\n\n`parse()` accepts an optional second argument:\n\n```typescript\nparse(sql, {\n  // Attach a `location` (line/column/offset source range) to every node.\n  // Set to false for a leaner, fully JSON-serializable AST. Default: true.\n  locations: true,\n\n  // Set a `parent` reference on every node. This introduces circular\n  // references, which break `JSON.stringify`. Default: false.\n  setParents: false,\n});\n```\n\nWith locations enabled (the default) **every** AST node carries a `location`, so\nit is a **required** property — no `| undefined`, no `!`:\n\n```typescript\nconst ast = parse(sql); // Statement[]\nast[0].location.start.offset; // ✓ SourceLocation (always present)\n```\n\nWhen `locations: false` is passed as a literal, `parse()` returns\n`WithoutLocations<Statement>[]` — a type with `location` recursively removed, so\nreading `.location` is a compile-time error:\n\n```typescript\nconst ast = parse(sql, { locations: false });\nast[0].location; // ✗ type error: property does not exist\n```\n\nThe AST-consuming functions — `format`, `formatExplain`, `formatNode`, and\n`transformNodes` — accept `WithoutLocations<…>` inputs. Because a located AST is\nassignable to its location-free counterpart, they transparently accept ASTs both\nwith and without locations.\n\n### Formatting AST back to SQL\n\n```typescript\nimport { parse, format } from '@clickhouse/parser';\n\nconst ast = parse('SELECT id, name FROM users WHERE active = 1 ORDER BY name');\nconst sql = format(ast);\n```\n\nThe formatted output for the above:\n\n```sql\nSELECT\n    id,\n    name\nFROM users\nWHERE active = 1\nORDER BY name ASC;\n```\n\n`format()` converts the AST back into normalized, readable SQL. Parsing and formatting is round-trip safe — parsing the formatted output produces an identical AST.\n\n### EXPLAIN output\n\n```typescript\nimport { parse, formatExplain } from '@clickhouse/parser';\n\nconst ast = parse('SELECT a + b FROM t WHERE x = 1');\nconst explain = formatExplain(ast);\n```\n\n`formatExplain()` produces a tree representation matching ClickHouse's `EXPLAIN AST` output:\n\n```\nSelectWithUnionQuery (children 1)\n ExpressionList (children 1)\n  SelectQuery (children 3)\n   ExpressionList (children 1)\n    Function plus (children 1)\n     ExpressionList (children 2)\n      Identifier a\n      Identifier b\n   TablesInSelectQuery (children 1)\n    TablesInSelectQueryElement (children 1)\n     TableExpression (children 1)\n      TableIdentifier t\n   Function equals (children 1)\n    ExpressionList (children 2)\n     Identifier x\n     Literal UInt64_1\n```\n\n### Error handling\n\nWhen parsing fails, `parse()` throws a `ParseError` with structured information about where and why the parse failed.\n\n```typescript\nimport { parse, ParseError } from '@clickhouse/parser';\n\ntry {\n  parse('SELECT ???');\n} catch (e) {\n  if (e instanceof ParseError) {\n    e.message; // Human-readable error message\n    e.location; // { start: { line, column, offset }, end: { line, column, offset } }\n    e.expected; // What the parser expected (e.g. literals, token classes)\n    e.found; // What was found instead (string | null)\n  }\n}\n```\n\n## Supported SQL\n\nThe parser targets full coverage of the ClickHouse SQL surface and is verified\nagainst a corpus of ~7000 representative reference query files drawn from the\nofficial ClickHouse repository. For every reference, the AST, formatted SQL,\nand `EXPLAIN AST` projection match ClickHouse's own output exactly.\n\n### Limitations\n\n- **ClickHouse-only** — this is not a general SQL parser. Syntax from other dialects that ClickHouse doesn't support will not parse.\n- **KQL** — Kusto Query Language syntax is not supported.\n- **Inserted Values** are not parsed - the AST does not include literal values being inserted into a table.\n\n### Divergence from ClickHouse Reference AST\n\nThe AST parsed by this library is a superset of the JSON AST produced by ClickHouse introduced [here](https://github.com/peter-leonov-ch/ClickHouse/pull/1). Additional properties are described below.\n\n#### Location Metadata\n\nEvery node carries a `location: { start, end }` recording its source\nrange in the original SQL, where `start`/`end` are `{ offset, line, column }`\n(compatible with peggy's `LocationRange`). Locations are included by default;\npass `{ locations: false }` to `parse()` to omit them (see [Parse options](#parse-options)).\n\n#### Parent Metadata\n\nOptionally, every node can be returned with a `parent` reference to its enclosing node. Pass the\n`options: { setParents: true }` argument to `parse()` to enable this feature. This enables upward\ntraversal of the tree. It creates circular references, so exclude it when serializing or comparing\nthe AST.\n\n#### Comment Data\n\nComments are attached to the nearest node as arrays of their full source text\n(including `--`, `#`, or `/* */` delimiters):\n\n- `leadingComments` — comments appearing before the node.\n- `trailingComments` — inline comments on the same line as the end of the node.\n\n#### Semantic Fields not in Reference AST\n\nThese fields carry semantic information that the reference JSON AST discards but\nthat `format()` needs to reproduce the source faithfully.\n\n- `nonfinite` — Found on `Literal` and `LiteralElement` nodes, this is a discriminator\nfor `Float64` values that the native `value` float cannot represent in serialized JSON.\nNon-finite values (`inf`, `-inf`, `nan`, `-nan`) that each collapse to `null` can be\nrecovered using this flag.\n- `QueryParameter` nodes - represent query parameters (`{name:type}` syntax) in the source,\nwhich are not represented by the reference ClickHouse JSON AST.\n\n#### Non-Semantic Fields for Explain Formatting\n\nThese fields carry no semantic meaning and are **only** read by `formatExplain()`.\nThey exist because ClickHouse's `EXPLAIN AST` exposes internal child-vector ordering\nand duplication that the structured JSON AST discards. Like the semantic fields\nabove, they are absent from the reference AST, so `formatExplainJson()` strips them.\n\n- `with_trailing` — marks a `WITH` clause that ClickHouse appends *after* the\n  select body rather than before it (a `WITH` written before an enclosing\n  `INSERT`, or propagated into a non-leftmost `UNION`/`INTERSECT` member). The\n  reference AST stores the same `with` field in both positions, so the flag is\n  the only record of the trailing placement.\n- `agg_repeat` — marks the synthetic `SelectQuery` produced when lowering\n  `expr op ANY/ALL (subquery)`. ClickHouse's text dump emits this node's\n  projection and tables twice (`SelectQuery (children 4)`); the reference AST\n  keeps a single copy, indistinguishable from a user-written\n  `(SELECT agg(*) FROM (sub))`.\n- `settings_before_format` — records that `SETTINGS` preceded `FORMAT` in the\n  source. `format()` canonicalizes to `FORMAT ... SETTINGS ...`; the flag lets\n  the explain projection reproduce the original child order.\n- `settings_after_order_by` — records that a storage `SETTINGS` clause appeared\n  before the last clause in the source. `format()` canonicalizes it to the\n  required final position; the flag preserves the original `Set` child order.\n- `no_parens` — records that a codec/engine function was written without\n  parentheses (e.g. `Delta` vs `Delta()`). `format()` canonicalizes to the\n  empty-parens form; the flag reproduces ClickHouse's byte-exact AST.\n\n#### Filtered Storage Settings\n\nWhen ClickHouse emits `EXPLAIN AST json=1`, it filters a\n`CREATE TABLE`/`CREATE DATABASE ... SETTINGS` clause down to only the settings\nthat belong to the target engine's own registry (a version- and\nengine-specific set). Session- or query-level settings that were written into\nthe clause — e.g. `log_queries`, `allow_suspicious_low_cardinality_types`, or\n`use_hive_partitioning` on a table, or `distributed_ddl_task_timeout` on a\ndatabase — are dropped from the `Storage > Set` `changes` map, and if nothing\nremains the entire `Storage`/`settings` node is dropped.\n\nThis library does **not** replicate that engine-specific registry: it keeps\n**every** setting in the clause so `format()` can re-emit the original SQL\nfaithfully. The library AST may therefore carry extra `Storage` settings that\nthe reference AST omits.\n\n## Development\n\n```bash\nnpm run build           # Regenerate parser from grammar + build dist/\nnpm test                # Run test suite\n```\n\n### Inspecting output\n\n`parse`, `format`, and `explain` print this library's output. Each takes a raw SQL\nstring via `--sql`, or one or more reference cases from `tests/clickhouse-reference/`\n(a `.sql` filename — the suffix is optional — a comma-separated list, or a glob):\n\n```bash\nnpm run parse   -- --sql \"SELECT 1\"   # AST as JSON\nnpm run format  -- --sql \"SELECT 1\"   # re-formatted SQL\nnpm run explain -- --sql \"SELECT 1\"   # EXPLAIN AST output\n\nnpm run format  -- 00001_select_1     # output for a reference case\nnpm run explain -- '00001_*'          # output for every matching case\n```\n\n### Diffing against expected output\n\n`diff:ast`, `diff:format`, and `diff:explain` show this library's output, the expected\noutput committed in `tests/clickhouse-reference/`, and a diff between them — useful for\ndebugging reference test failures. They take the same reference selector (filename,\ncomma-separated list, or glob):\n\n```bash\nnpm run diff:format  -- 00001_select_1            # actual, expected, and diff\nnpm run diff:ast     -- '0001*' --diff-only       # just the diff\nnpm run diff:explain -- 00001_select_1,00002_count_visits --only-diffs\n```\n\nFlags: `--diff-only`, `--actual-only`, `--expected-only`, `--only-diffs`, `--no-color`.\nPass `-h` to any script for full usage.\n\nThe parser is built with [Peggy](https://peggyjs.org/) (PEG grammar) and produces ASTs validated by [Zod](https://zod.dev/) schemas. All AST types are exported for use in downstream tooling.\n","readmeFilename":"README.md"}