sqllens 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -367,7 +367,11 @@ that run on incomplete, mid-edit text. They never need a clean parse:
367
367
  - `SqlDocument` is a persistent, immutable, position-addressable per-file model.
368
368
  It runs `parse → resolveScopes` once (plus lazy `analyze(schema)`), caches the
369
369
  result, and answers `tokenAt` / `nodeAt`. An edit yields a new document; an
370
- O(log n) `LineIndex` maps positions to offsets.
370
+ O(log n) `LineIndex` maps positions to offsets. Its `statements` are the
371
+ per-statement cells; each cell's `span` carries the separator token that ends
372
+ it (`;`, or the `GO` word), so the statement's own text ends where that starts.
373
+ - `statementSpans(text, dialect, { templating? })`: the same cell spans without
374
+ the per-cell parses, for code lenses and run-at-cursor ranges on every change.
371
375
  - `completeAt(doc, offset, schema?)`: scope-aware completion (keywords, columns,
372
376
  tables, functions) from an ATN (Augmented Transition Network, the grammar's
373
377
  state-machine form) candidate walk over the grammar, our own, with no third-party
package/dist/api.d.ts CHANGED
@@ -116,6 +116,7 @@ export type { Token, TokenRole } from "./token/token.js";
116
116
  export { SqlDocument, type DocumentAnalysis, type StatementCell, type DocumentVariant, type UnionCte, } from "./document/document.js";
117
117
  export { LineIndex } from "./document/line-index.js";
118
118
  export type { StatementCellSpan } from "./document/split.js";
119
+ export { statementSpans } from "./document/spans.js";
119
120
  export { complete, completeAt, type Completion, type CompletionResult, type ReplaceRange, type CompleteOptions, type CandidateIdentity, type CandidateDecoration, type DecorateCandidate, } from "./completion/complete.js";
120
121
  export { jinjaSlotAt, type JinjaSlot } from "./completion/jinja-slot.js";
121
122
  export { signatureAt, type SignatureHelpInfo, type SignatureLabel } from "./signature/signature.js";
package/dist/api.js CHANGED
@@ -202,6 +202,9 @@ export { tokenize } from "./token/tokenize.js";
202
202
  // these at call time, never at module-eval time.
203
203
  export { SqlDocument, } from "./document/document.js";
204
204
  export { LineIndex } from "./document/line-index.js";
205
+ // The cell spans alone (plain or templated), for a consumer that needs statement ranges without
206
+ // the per-cell parses; identical to the spans the document's cells carry.
207
+ export { statementSpans } from "./document/spans.js";
205
208
  // Scope-aware completion over a SqlDocument — the broken-input editor feature (keywords + schema
206
209
  // tables/columns + function names at the caret). Total: never throws.
207
210
  export { complete, completeAt, } from "./completion/complete.js";
@@ -168,7 +168,8 @@ export class SqlDocument {
168
168
  const r = whole.cached.templated;
169
169
  const spans = opts.templating.parseCell ? splitStatements(r.placeholder, dialect) : [whole.cell.span];
170
170
  if (spans.length === 1) {
171
- cells = [whole.cell];
171
+ // The whole-text cell, under the split's own span so it carries its separator.
172
+ cells = [Object.freeze({ ...whole.cell, span: spans[0] })];
172
173
  backing = [whole.cached];
173
174
  templated = r;
174
175
  }
@@ -0,0 +1,14 @@
1
+ import type { Dialect } from "../dialect.js";
2
+ import type { TemplateProvider } from "../qualify/template-provider.js";
3
+ import type { TemplateEngine } from "../template/engine.js";
4
+ import { type StatementCellSpan } from "./split.js";
5
+ /**
6
+ * The statement cell spans `SqlDocument.create(text, dialect, opts)` would produce, without the
7
+ * per-cell parses. Plain text splits directly; with `templating` the engine's placeholder is
8
+ * split (its `placeholder` hook when it has one, else its full `parse`), and an engine without
9
+ * `parseCell` answers one whole-text span, exactly as the document door does. Total: never throws.
10
+ */
11
+ export declare function statementSpans(text: string, dialect: Dialect, opts?: {
12
+ templating?: TemplateEngine;
13
+ provider?: TemplateProvider;
14
+ }): StatementCellSpan[];
@@ -0,0 +1,34 @@
1
+ // ---------------------------------------------------------------------------
2
+ // statementSpans() — the statement cell spans of a text without building the
3
+ // document. The SqlDocument constructor derives its cells from exactly this
4
+ // split (the plain text, or the engine's placeholder for a templated one), so
5
+ // the spans answered here are the spans `doc.statements[i].span` would carry;
6
+ // a consumer that only needs "where do the statements start and end" (code
7
+ // lenses, run-at-cursor ranges) pays the lex and the split, not the parses.
8
+ // ---------------------------------------------------------------------------
9
+ import { debugRethrow } from "../debug.js";
10
+ import { splitStatements } from "./split.js";
11
+ /**
12
+ * The statement cell spans `SqlDocument.create(text, dialect, opts)` would produce, without the
13
+ * per-cell parses. Plain text splits directly; with `templating` the engine's placeholder is
14
+ * split (its `placeholder` hook when it has one, else its full `parse`), and an engine without
15
+ * `parseCell` answers one whole-text span, exactly as the document door does. Total: never throws.
16
+ */
17
+ export function statementSpans(text, dialect, opts = {}) {
18
+ const engine = opts.templating;
19
+ if (!engine)
20
+ return splitStatements(text, dialect);
21
+ if (!engine.parseCell)
22
+ return [{ start: 0, end: text.length }];
23
+ let placeholder;
24
+ try {
25
+ placeholder = engine.placeholder
26
+ ? engine.placeholder(text, dialect, { provider: opts.provider })
27
+ : engine.parse(text, dialect, { provider: opts.provider }).placeholder;
28
+ }
29
+ catch (e) {
30
+ debugRethrow(e);
31
+ placeholder = text;
32
+ }
33
+ return splitStatements(placeholder, dialect);
34
+ }
@@ -5,13 +5,23 @@ export interface StatementCellSpan {
5
5
  /** doc offset, exclusive — includes the trailing separator (`;` / GO line); the document's last
6
6
  * cell also includes whatever trivia follows its separator, up to `text.length`. */
7
7
  end: number;
8
+ /** The separator token that terminates this cell, as doc offsets (`start` inclusive, `end`
9
+ * exclusive): the `;`, or the `GO` word itself (not its line). Absent when the cell has no
10
+ * separator (an unterminated final statement, a separator-free document, the whole-document
11
+ * fallback). The statement's own text ends where this starts, before any trailing trivia. */
12
+ separator?: {
13
+ start: number;
14
+ end: number;
15
+ };
8
16
  }
9
17
  /**
10
18
  * Split `text` into top-level statement cells using `tokenize(text, dialect)`.
11
19
  * Total: never throws. Splits at channel-0 `;` at compound depth 0 (BEGIN/CASE
12
20
  * increment, END decrements, floor 0; a T-SQL `BEGIN TRAN`/`TRANSACTION`/
13
21
  * `DISTRIBUTED` does not open a depth level) plus, for T-SQL, a `GO` batch
14
- * separator alone on its line. Returns the whole doc as one cell when
22
+ * separator alone on its line; text ending inside an open level splits at every
23
+ * separator from the unclosed opener on (see `findSplitEnds`). Each cell carries
24
+ * the separator token that ends it. Returns the whole doc as one cell when
15
25
  * splitting is unsafe (the tiling invariant fails) or pointless (no separators).
16
26
  */
17
27
  export declare function splitStatements(text: string, dialect: Dialect): StatementCellSpan[];
@@ -26,14 +26,43 @@ const NON_OPENER_END_SUFFIXES = new Set(["IF", "WHILE", "FOR", "LOOP", "REPEAT"]
26
26
  function wholeDoc(text) {
27
27
  return [{ start: 0, end: text.length }];
28
28
  }
29
- /** Every offset in `text` where a top-level separator ends (exclusive), in ascending order. A
30
- * separator that no channel-0 token follows (only whitespace, comments, the final newline) is not
31
- * a split end: the trivia after it belongs to the cell it terminates, so a single terminated
32
- * statement is one cell rather than a statement plus a token-less tail cell. */
29
+ /** The split point a `;` or a T-SQL `GO` at `channel0[i]` makes, ignoring depth, or undefined when
30
+ * the token is neither. A GO batch separator must sit alone on its line among channel-0 tokens
31
+ * (otherwise it is an identifier/alias use of the word); its cell end is the end of that line. */
32
+ function separatorAt(text, channel0, i, dialect) {
33
+ const t = channel0[i];
34
+ const separator = { start: t.start, end: t.stop + 1 };
35
+ if (t.text === ";")
36
+ return { end: t.stop + 1, separator };
37
+ if (dialect === "tsql" && t.text.toUpperCase() === "GO") {
38
+ const prev = channel0[i - 1];
39
+ const next = channel0[i + 1];
40
+ const alone = (!prev || prev.line !== t.line) && (!next || next.line !== t.line);
41
+ if (!alone)
42
+ return undefined;
43
+ const nl = text.indexOf("\n", t.stop + 1);
44
+ return { end: nl === -1 ? text.length : nl + 1, separator };
45
+ }
46
+ return undefined;
47
+ }
48
+ /** Every top-level split point in `text`, in ascending order, plus `tail`: the separator of a
49
+ * terminated final statement that nothing real follows (only whitespace, comments, the final
50
+ * newline). That separator is not a split end, the trivia after it belongs to the cell it
51
+ * terminates, so a single terminated statement is one cell rather than a statement plus a
52
+ * token-less tail cell; `tail` lets that cell still carry its separator.
53
+ *
54
+ * Depth: `BEGIN`/`CASE` open a level, `END` closes one, and only a separator at depth 0 splits.
55
+ * When the text ends INSIDE an open level (an unclosed CASE mid-typing, jinja arms that leave
56
+ * the placeholder with more openers than closers), the walk cannot know where that block ends,
57
+ * and one cell silently spanning several statements is the worse failure (a "run statement at
58
+ * cursor" would run them all): the split points before the outermost unclosed opener stand, and
59
+ * from that opener on every separator splits regardless of depth. Balanced text is unaffected. */
33
60
  function findSplitEnds(text, tokens, dialect) {
34
61
  const channel0 = tokens.filter((t) => t.channel === 0);
35
- const ends = [];
62
+ let ends = [];
36
63
  let depth = 0;
64
+ /** The outermost currently-open level: where it opened and how many split points preceded it. */
65
+ let opener;
37
66
  for (let i = 0; i < channel0.length; i++) {
38
67
  const t = channel0[i];
39
68
  const upper = t.text.toUpperCase();
@@ -41,10 +70,15 @@ function findSplitEnds(text, tokens, dialect) {
41
70
  // `BEGIN TRAN`/`TRANSACTION`/`DISTRIBUTED` (T-SQL) starts a transaction, not a
42
71
  // scripting compound — it has no matching END, so it must not open a depth level.
43
72
  const next = channel0[i + 1];
44
- if (!next || !TRAN_WORDS.has(next.text.toUpperCase()))
73
+ if (!next || !TRAN_WORDS.has(next.text.toUpperCase())) {
74
+ if (depth === 0)
75
+ opener = { index: i, endsBefore: ends.length };
45
76
  depth++;
77
+ }
46
78
  }
47
79
  else if (upper === "CASE") {
80
+ if (depth === 0)
81
+ opener = { index: i, endsBefore: ends.length };
48
82
  depth++;
49
83
  }
50
84
  else if (upper === "END") {
@@ -66,42 +100,46 @@ function findSplitEnds(text, tokens, dialect) {
66
100
  else {
67
101
  depth = Math.max(0, depth - 1);
68
102
  }
69
- }
70
- else if (t.text === ";") {
71
103
  if (depth === 0)
72
- ends.push(t.stop + 1);
104
+ opener = undefined;
73
105
  }
74
- else if (dialect === "tsql" && upper === "GO" && depth === 0) {
75
- // A GO batch separator must sit alone on its line among channel-0 tokens —
76
- // otherwise it's an identifier/alias use of the word `GO`, not a separator.
77
- const prev = channel0[i - 1];
78
- const next = channel0[i + 1];
79
- const alone = (!prev || prev.line !== t.line) && (!next || next.line !== t.line);
80
- if (alone) {
81
- const nl = text.indexOf("\n", t.stop + 1);
82
- ends.push(nl === -1 ? text.length : nl + 1);
83
- }
106
+ else if (depth === 0) {
107
+ const sep = separatorAt(text, channel0, i, dialect);
108
+ if (sep)
109
+ ends.push(sep);
110
+ }
111
+ }
112
+ if (depth > 0 && opener) {
113
+ // Unclosed level: keep the split points before it, then split at every separator from it on.
114
+ ends = ends.slice(0, opener.endsBefore);
115
+ for (let i = opener.index; i < channel0.length; i++) {
116
+ const sep = separatorAt(text, channel0, i, dialect);
117
+ if (sep)
118
+ ends.push(sep);
84
119
  }
85
120
  }
86
121
  // Tokens are in source order, so the last channel-0 token decides whether anything real follows
87
122
  // the last separator.
88
123
  const lastReal = channel0[channel0.length - 1];
89
- if (ends.length > 0 && (lastReal === undefined || lastReal.start < ends[ends.length - 1]))
124
+ const last = ends[ends.length - 1];
125
+ if (last && (lastReal === undefined || lastReal.start < last.end)) {
90
126
  ends.pop();
91
- return ends;
127
+ return { ends, tail: last.separator };
128
+ }
129
+ return { ends };
92
130
  }
93
- /** Turn ascending split-end offsets into contiguous cells tiling `[0, text.length)`. A doc
94
- * with no separators is one cell; trailing text after the last separator is its own cell
95
- * but when the last separator already reaches `length` there is no trailing cell to add. */
96
- function buildCells(splitEnds, length) {
131
+ /** Turn ascending split points into contiguous cells tiling `[0, text.length)`. A doc with no
132
+ * split points is one cell; text after the last split point is the final cell, carrying `tail`
133
+ * (its own separator, when it is a terminated statement whose trailing trivia was folded in). */
134
+ function buildCells(splitEnds, tail, length) {
97
135
  const spans = [];
98
136
  let start = 0;
99
- for (const end of splitEnds) {
100
- spans.push({ start, end });
101
- start = end;
137
+ for (const e of splitEnds) {
138
+ spans.push({ start, end: e.end, separator: e.separator });
139
+ start = e.end;
102
140
  }
103
141
  if (start < length || spans.length === 0)
104
- spans.push({ start, end: length });
142
+ spans.push(tail ? { start, end: length, separator: tail } : { start, end: length });
105
143
  return spans;
106
144
  }
107
145
  /** The tiling invariant: contiguous, starts at 0, ends at `length`, in order. */
@@ -123,14 +161,16 @@ function tiles(spans, length) {
123
161
  * Total: never throws. Splits at channel-0 `;` at compound depth 0 (BEGIN/CASE
124
162
  * increment, END decrements, floor 0; a T-SQL `BEGIN TRAN`/`TRANSACTION`/
125
163
  * `DISTRIBUTED` does not open a depth level) plus, for T-SQL, a `GO` batch
126
- * separator alone on its line. Returns the whole doc as one cell when
164
+ * separator alone on its line; text ending inside an open level splits at every
165
+ * separator from the unclosed opener on (see `findSplitEnds`). Each cell carries
166
+ * the separator token that ends it. Returns the whole doc as one cell when
127
167
  * splitting is unsafe (the tiling invariant fails) or pointless (no separators).
128
168
  */
129
169
  export function splitStatements(text, dialect) {
130
170
  try {
131
171
  const tokens = tokenize(text, dialect);
132
- const splitEnds = findSplitEnds(text, tokens, dialect);
133
- const spans = buildCells(splitEnds, text.length);
172
+ const { ends, tail } = findSplitEnds(text, tokens, dialect);
173
+ const spans = buildCells(ends, tail, text.length);
134
174
  return tiles(spans, text.length) ? spans : wholeDoc(text);
135
175
  }
136
176
  catch (e) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, type Nullability, Lineage, originsOfExpr, lineageAt, lineageOf, type LineageHop, type ViaStep, tokenize, SqlDocument, LineIndex, complete, completeAt, type Completion, type CompletionResult, type ReplaceRange, type CompleteOptions, type CandidateIdentity, type CandidateDecoration, type DecorateCandidate, jinjaSlotAt, type JinjaSlot, signatureAt, SIGNATURES, lookupSignature, hasSignature, renderSignature, FN_DOCS, lookupFnDoc, referencesAt, type Occurrence, type Occurrences, frameAt, type Frame, clausesOf, type ClauseInfo, type ClauseKind, setOpArmsOf, type SetOpArm, type SetOpArms, dialectSymbols, type DialectSymbols, dialectVocabulary, type DialectVocabulary, reservedKeywords, type KeywordEntry, type KeywordReservation, CallbackSchema, type SchemaProvider, type TableResolver, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, type IdentKind, type SignatureHelpInfo, type SignatureLabel, type FnSignature, type ParamSig, type RenderSignatureOptions, type FnDoc, type Dialect, type DialectOpts, type ParseResultIR, type Analysis, type Token, type TokenRole, type DocumentAnalysis, type StatementCell, type StatementCellSpan, type DocumentVariant, type UnionCte, } from "./api.js";
1
+ export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, type Nullability, Lineage, originsOfExpr, lineageAt, lineageOf, type LineageHop, type ViaStep, tokenize, SqlDocument, LineIndex, complete, completeAt, type Completion, type CompletionResult, type ReplaceRange, type CompleteOptions, type CandidateIdentity, type CandidateDecoration, type DecorateCandidate, jinjaSlotAt, type JinjaSlot, signatureAt, SIGNATURES, lookupSignature, hasSignature, renderSignature, FN_DOCS, lookupFnDoc, referencesAt, type Occurrence, type Occurrences, frameAt, type Frame, clausesOf, type ClauseInfo, type ClauseKind, setOpArmsOf, type SetOpArm, type SetOpArms, dialectSymbols, type DialectSymbols, dialectVocabulary, type DialectVocabulary, reservedKeywords, type KeywordEntry, type KeywordReservation, CallbackSchema, type SchemaProvider, type TableResolver, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, type IdentKind, type SignatureHelpInfo, type SignatureLabel, type FnSignature, type ParamSig, type RenderSignatureOptions, type FnDoc, type Dialect, type DialectOpts, type ParseResultIR, type Analysis, type Token, type TokenRole, type DocumentAnalysis, type StatementCell, type StatementCellSpan, statementSpans, type DocumentVariant, type UnionCte, } from "./api.js";
2
2
  export { SqlSession, type SessionOptions } from "./session.js";
3
3
  export { parseDatabricks } from "./databricks/parse.js";
4
4
  export { parseTSql } from "./tsql/parse.js";
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  // - Building blocks: the per-dialect parse*/lower and the raw shared passes, for callers who
11
11
  // want a specific tier or the raw CST escape hatch.
12
12
  // --- Uniform entry, lift helpers, typed wrappers, composable passes (src/api.ts) ---
13
- export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, Lineage, originsOfExpr, lineageAt, lineageOf, tokenize, SqlDocument, LineIndex, complete, completeAt, jinjaSlotAt, signatureAt, SIGNATURES, lookupSignature, hasSignature, renderSignature, FN_DOCS, lookupFnDoc, referencesAt, frameAt, clausesOf, setOpArmsOf, dialectSymbols, dialectVocabulary, reservedKeywords, CallbackSchema, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, } from "./api.js";
13
+ export { parse, analyze, toAst, toScopes, qualify, lineage, deriveSymbols, TypeInfo, Lineage, originsOfExpr, lineageAt, lineageOf, tokenize, SqlDocument, LineIndex, complete, completeAt, jinjaSlotAt, signatureAt, SIGNATURES, lookupSignature, hasSignature, renderSignature, FN_DOCS, lookupFnDoc, referencesAt, frameAt, clausesOf, setOpArmsOf, dialectSymbols, dialectVocabulary, reservedKeywords, CallbackSchema, DERIVED_DIALECTS, resolveDialect, foldIdentifier, displayName, statementSpans, } from "./api.js";
14
14
  // SqlSession — the verb-shaped facade over one SqlDocument (offset in, answer out; pure delegation).
15
15
  export { SqlSession } from "./session.js";
16
16
  // --- Per-dialect building blocks: parse* (CST + errors) and lower* (CST → IR), kept as one
@@ -1,4 +1,4 @@
1
- import { parseTemplated, parseTemplatedCell } from "./parse.js";
1
+ import { parseTemplated, parseTemplatedCell, placeholderOf } from "./parse.js";
2
2
  import { templateVariants } from "./variants.js";
3
3
  /** The minijinja template engine (the Rust engine dbt Fusion uses — the grammar
4
4
  * oracle for what we accept). The shipped, and only, TemplateEngine. */
@@ -7,6 +7,7 @@ export function minijinja() {
7
7
  name: "minijinja",
8
8
  parse: (text, dialect, opts) => parseTemplated(text, dialect, opts),
9
9
  variants: (text, dialect) => templateVariants(text, dialect),
10
+ placeholder: (text, _dialect, opts) => placeholderOf(text, opts),
10
11
  parseCell: (whole, span, text, dialect, opts) => parseTemplatedCell(whole, span, text, dialect, opts),
11
12
  };
12
13
  }
@@ -43,3 +43,7 @@ export declare function parseTemplatedCell(whole: TemplatedParseResult, span: {
43
43
  start: number;
44
44
  end: number;
45
45
  }, text: string, dialect: Dialect, opts?: TemplatedParseOptions): TemplatedCellResult;
46
+ /** The placeholder `parseTemplated` would parse for `text` (`TemplateEngine.placeholder`): the
47
+ * segmenter alone, no SQL parse. Total: the text itself when segmentation gives up, the same
48
+ * floor `parseTemplated`'s degrade path reports as its placeholder. */
49
+ export declare function placeholderOf(text: string, opts?: TemplatedParseOptions): string;
@@ -675,6 +675,18 @@ export function parseTemplatedCell(whole, span, text, dialect, opts) {
675
675
  })),
676
676
  };
677
677
  }
678
+ /** The placeholder `parseTemplated` would parse for `text` (`TemplateEngine.placeholder`): the
679
+ * segmenter alone, no SQL parse. Total: the text itself when segmentation gives up, the same
680
+ * floor `parseTemplated`'s degrade path reports as its placeholder. */
681
+ export function placeholderOf(text, opts) {
682
+ try {
683
+ return segment(text, opts?.provider ?? OPEN_PROVIDER).placeholder;
684
+ }
685
+ catch (e) {
686
+ debugRethrow(e);
687
+ return text;
688
+ }
689
+ }
678
690
  /** The cell start's 0-based line / column / char offset in `text` (`\n` is the line break, the
679
691
  * convention every span in the pipeline follows; a `\r` is an ordinary column). */
680
692
  function cellBaseOf(text, offset) {
@@ -122,6 +122,10 @@ export interface TemplateEngine {
122
122
  parse(text: string, dialect: Dialect, opts?: TemplatedParseOptions): TemplatedParseResult;
123
123
  /** Optional: coherent per-branch variant enumeration, for engines with control-flow arms. */
124
124
  variants?(text: string, dialect: Dialect): TemplateVariant[];
125
+ /** Optional: the placeholder-filled SQL text `parse` would see for `text` (see
126
+ * `TemplatedParseResult.placeholder`), without running the SQL parse. Total: on any internal
127
+ * surprise answer `text` itself. Backs `statementSpans`, which only needs the split. */
128
+ placeholder?(text: string, dialect: Dialect, opts?: TemplatedParseOptions): string;
125
129
  /** Optional: the products of ONE statement cell of a templated document, the plain parse of
126
130
  * `whole.placeholder`'s slice `[span.start, span.end)` (cell-relative) with `whole`'s tags
127
131
  * correlated onto it. `whole` is this engine's own `parse` result for the full `text`, `span`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqllens",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "description": "A TypeScript SQL parser and static analyzer: parse, resolve names, infer types, and trace column lineage across many SQL dialects (Databricks, T-SQL, Snowflake, BigQuery, Redshift, PostgreSQL, DuckDB, Trino, SQLite, MySQL).",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",