@indiekitai/pg-complete 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/completer.ts","../src/keywords.ts","../src/parser.ts","../src/metadata.ts"],"sourcesContent":["export { PgCompleter } from './completer';\nexport type {\n Completion,\n CompletionType,\n ColumnMetadata,\n ForeignKey,\n FunctionMetadata,\n TableReference,\n SchemaMetadata,\n PgCompleterOptions,\n} from './types';\nexport { suggestType, extractTables } from './parser';\nexport { KEYWORDS, BUILTIN_FUNCTIONS, KEYWORD_TREE } from './keywords';\n","/**\n * Main completion engine — ported from pgcli's pgcompleter.py\n */\n\nimport { Pool } from 'pg';\nimport type { Completion, SchemaMetadata, ColumnMetadata, ForeignKey, PgCompleterOptions, TableReference } from './types';\nimport { KEYWORDS, KEYWORD_TREE, BUILTIN_FUNCTIONS, RESERVED_WORDS } from './keywords';\nimport { suggestType, extractTables, tableRef, type SuggestionContext } from './parser';\nimport { fetchMetadata, fetchSearchPath } from './metadata';\n\nexport class PgCompleter {\n private pool: Pool | null = null;\n private metadata: SchemaMetadata;\n private searchPath: string[];\n private qualifyColumns: 'always' | 'never' | 'if_more_than_one_table';\n private connectionString?: string;\n\n constructor(connectionStringOrOpts?: string | PgCompleterOptions) {\n const opts: PgCompleterOptions = typeof connectionStringOrOpts === 'string'\n ? { connectionString: connectionStringOrOpts }\n : (connectionStringOrOpts || {});\n\n this.connectionString = opts.connectionString;\n this.metadata = opts.metadata || { tables: {}, views: {}, functions: {}, datatypes: {} };\n this.searchPath = opts.searchPath || ['pg_catalog', 'public'];\n this.qualifyColumns = opts.qualifyColumns || 'if_more_than_one_table';\n }\n\n /** Connect to the database and load schema metadata */\n async refresh(): Promise<void> {\n if (!this.connectionString) {\n throw new Error('No connection string provided');\n }\n this.pool = new Pool({ connectionString: this.connectionString, max: 2 });\n try {\n const [meta, sp] = await Promise.all([\n fetchMetadata(this.pool),\n fetchSearchPath(this.pool),\n ]);\n this.metadata = meta;\n this.searchPath = sp;\n } finally {\n await this.pool.end();\n this.pool = null;\n }\n }\n\n /** Close any open connections */\n async close(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n }\n }\n\n /** Set metadata directly (for testing or pre-loaded scenarios) */\n setMetadata(meta: SchemaMetadata, searchPath?: string[]): void {\n this.metadata = meta;\n if (searchPath) this.searchPath = searchPath;\n }\n\n /**\n * Get completions for the given SQL text.\n * @param text - The full SQL text typed so far\n * @param cursorPos - Cursor position (defaults to end of text)\n * @returns Array of completion suggestions\n */\n complete(text: string, cursorPos?: number): Completion[] {\n const pos = cursorPos ?? text.length;\n const textBeforeCursor = text.slice(0, pos);\n const fullText = text;\n\n const suggestions = suggestType(fullText, textBeforeCursor);\n const completions: Completion[] = [];\n\n for (const suggestion of suggestions) {\n switch (suggestion.type) {\n case 'keyword':\n completions.push(...this.getKeywordCompletions(suggestion.lastToken));\n break;\n case 'table':\n completions.push(...this.getTableCompletions(suggestion.schema));\n break;\n case 'view':\n completions.push(...this.getViewCompletions(suggestion.schema));\n break;\n case 'column':\n completions.push(...this.getColumnCompletions(\n suggestion.tableRefs,\n suggestion.qualifiable,\n suggestion.parent,\n ));\n break;\n case 'function':\n completions.push(...this.getFunctionCompletions(suggestion.schema));\n break;\n case 'schema':\n completions.push(...this.getSchemaCompletions());\n break;\n case 'from_clause':\n completions.push(...this.getTableCompletions(suggestion.schema));\n completions.push(...this.getViewCompletions(suggestion.schema));\n completions.push(...this.getFunctionCompletions(suggestion.schema));\n break;\n case 'join':\n completions.push(...this.getJoinCompletions(suggestion.tableRefs, suggestion.schema));\n break;\n case 'join_condition':\n completions.push(...this.getJoinConditionCompletions(suggestion.tableRefs, suggestion.parent));\n break;\n case 'alias':\n completions.push(...suggestion.aliases.map(a => ({\n text: a, type: 'alias' as const,\n })));\n break;\n case 'database':\n // Would need a DB query; skip for now\n break;\n case 'datatype':\n completions.push(...this.getDatatypeCompletions(suggestion.schema));\n break;\n }\n }\n\n // Filter by the word being typed\n const wordMatch = textBeforeCursor.match(/([A-Za-z0-9_.\"$]+)$/);\n const word = wordMatch ? wordMatch[1] : '';\n // Handle dot-qualified: only filter on part after dot\n const dotIdx = word.lastIndexOf('.');\n const filterWord = dotIdx >= 0 ? word.slice(dotIdx + 1) : word;\n\n if (!filterWord) return this.dedup(completions);\n\n const lower = filterWord.toLowerCase().replace(/^\"/, '');\n const filtered = completions.filter(c => {\n const ct = c.text.toLowerCase();\n return ct.startsWith(lower) || fuzzyMatch(lower, ct);\n });\n\n // Sort: exact prefix first, then fuzzy\n filtered.sort((a, b) => {\n const aExact = a.text.toLowerCase().startsWith(lower) ? 0 : 1;\n const bExact = b.text.toLowerCase().startsWith(lower) ? 0 : 1;\n if (aExact !== bExact) return aExact - bExact;\n return a.text.localeCompare(b.text);\n });\n\n return this.dedup(filtered);\n }\n\n private dedup(completions: Completion[]): Completion[] {\n const seen = new Set<string>();\n return completions.filter(c => {\n const key = `${c.type}:${c.text}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n }\n\n private getKeywordCompletions(lastToken?: string): Completion[] {\n let kws: string[];\n if (lastToken && KEYWORD_TREE[lastToken]) {\n kws = KEYWORD_TREE[lastToken];\n if (kws.length === 0) kws = KEYWORDS;\n } else {\n kws = KEYWORDS;\n }\n return kws.map(k => ({ text: k, type: 'keyword' }));\n }\n\n private getSchemaCompletions(): Completion[] {\n const schemas = new Set<string>();\n for (const kind of ['tables', 'views', 'functions', 'datatypes'] as const) {\n for (const s of Object.keys(this.metadata[kind])) {\n if (!s.startsWith('pg_')) schemas.add(s);\n }\n }\n return [...schemas].map(s => ({ text: s, type: 'schema' }));\n }\n\n private getTableCompletions(schema: string | null): Completion[] {\n const results: Completion[] = [];\n const schemas = schema ? [schema] : this.getVisibleSchemas();\n for (const s of schemas) {\n const tables = this.metadata.tables[s];\n if (!tables) continue;\n for (const name of Object.keys(tables)) {\n if (!schema && name.startsWith('pg_')) continue;\n // When schema is explicitly provided, don't prefix (user already typed it)\n const prefix = !schema && !this.searchPath.includes(s) ? `${s}.` : '';\n results.push({ text: prefix + name, type: 'table' });\n }\n }\n return results;\n }\n\n private getViewCompletions(schema: string | null): Completion[] {\n const results: Completion[] = [];\n const schemas = schema ? [schema] : this.getVisibleSchemas();\n for (const s of schemas) {\n const views = this.metadata.views[s];\n if (!views) continue;\n for (const name of Object.keys(views)) {\n if (!schema && name.startsWith('pg_')) continue;\n const prefix = !schema && !this.searchPath.includes(s) ? `${s}.` : '';\n results.push({ text: prefix + name, type: 'view' });\n }\n }\n return results;\n }\n\n private getColumnCompletions(\n tableRefs: TableReference[],\n qualifiable: boolean,\n parent?: string,\n ): Completion[] {\n const results: Completion[] = [];\n const doQualify = qualifiable && {\n always: true,\n never: false,\n if_more_than_one_table: tableRefs.length > 1,\n }[this.qualifyColumns];\n\n for (const tref of tableRefs) {\n const cols = this.findColumns(tref);\n const ref = tableRef(tref);\n for (const col of cols) {\n const text = doQualify ? `${ref}.${col.name}` : col.name;\n results.push({\n text,\n type: 'column',\n meta: col.datatype,\n });\n }\n }\n return results;\n }\n\n private getFunctionCompletions(schema: string | null): Completion[] {\n const results: Completion[] = [];\n const schemas = schema ? [schema] : this.getVisibleSchemas();\n for (const s of schemas) {\n const funcs = this.metadata.functions[s];\n if (!funcs) continue;\n for (const name of Object.keys(funcs)) {\n const prefix = schema || !this.searchPath.includes(s) ? `${s}.` : '';\n results.push({ text: prefix + name, type: 'function' });\n }\n }\n // Also suggest built-in functions\n if (!schema) {\n for (const f of BUILTIN_FUNCTIONS) {\n results.push({ text: f, type: 'function' });\n }\n }\n return results;\n }\n\n private getJoinCompletions(tableRefs: TableReference[], schema: string | null): Completion[] {\n const results: Completion[] = [];\n // For each table already in the query, look at foreign keys to suggest joins\n for (const tref of tableRefs) {\n const cols = this.findColumns(tref);\n for (const col of cols) {\n for (const fk of col.foreignKeys) {\n // Determine which side is the \"other\" table\n const isChild = col.name === fk.childColumn &&\n this.matchesTable(tref, fk.childSchema, fk.childTable);\n const otherSchema = isChild ? fk.parentSchema : fk.childSchema;\n const otherTable = isChild ? fk.parentTable : fk.childTable;\n const otherCol = isChild ? fk.parentColumn : fk.childColumn;\n const thisCol = isChild ? fk.childColumn : fk.parentColumn;\n\n if (schema && otherSchema !== schema) continue;\n\n const ref = tableRef(tref);\n const joinText = `${otherTable} ON ${otherTable}.${otherCol} = ${ref}.${thisCol}`;\n results.push({ text: joinText, type: 'join', meta: 'fk join' });\n }\n }\n }\n return results;\n }\n\n private getJoinConditionCompletions(tableRefs: TableReference[], parent?: string): Completion[] {\n const results: Completion[] = [];\n if (tableRefs.length < 2) return results;\n\n const lastRef = tableRefs[tableRefs.length - 1];\n const lastCols = this.findColumns(lastRef);\n const lastRefName = tableRef(lastRef);\n\n // FK-based conditions\n for (const col of lastCols) {\n for (const fk of col.foreignKeys) {\n for (const otherRef of tableRefs.slice(0, -1)) {\n const otherRefName = tableRef(otherRef);\n const isChild = col.name === fk.childColumn &&\n this.matchesTable(lastRef, fk.childSchema, fk.childTable);\n if (isChild) {\n if (this.matchesTable(otherRef, fk.parentSchema, fk.parentTable)) {\n results.push({\n text: `${lastRefName}.${fk.childColumn} = ${otherRefName}.${fk.parentColumn}`,\n type: 'join',\n meta: 'fk join',\n });\n }\n } else {\n if (this.matchesTable(otherRef, fk.childSchema, fk.childTable)) {\n results.push({\n text: `${lastRefName}.${fk.parentColumn} = ${otherRefName}.${fk.childColumn}`,\n type: 'join',\n meta: 'fk join',\n });\n }\n }\n }\n }\n }\n\n // Name-based conditions (columns with same name)\n for (const col of lastCols) {\n for (const otherRef of tableRefs.slice(0, -1)) {\n const otherCols = this.findColumns(otherRef);\n const match = otherCols.find(c => c.name === col.name);\n if (match) {\n const otherRefName = tableRef(otherRef);\n const text = `${lastRefName}.${col.name} = ${otherRefName}.${col.name}`;\n if (!results.some(r => r.text === text)) {\n results.push({ text, type: 'join', meta: 'name join' });\n }\n }\n }\n }\n\n return results;\n }\n\n private getDatatypeCompletions(schema: string | null): Completion[] {\n const results: Completion[] = [];\n const schemas = schema ? [schema] : this.getVisibleSchemas();\n for (const s of schemas) {\n const types = this.metadata.datatypes[s];\n if (!types) continue;\n for (const name of Object.keys(types)) {\n results.push({ text: name, type: 'datatype' });\n }\n }\n // Built-in types\n if (!schema) {\n for (const t of ['integer', 'bigint', 'smallint', 'serial', 'bigserial',\n 'real', 'double precision', 'numeric', 'decimal',\n 'text', 'varchar', 'char', 'boolean', 'bool',\n 'date', 'time', 'timestamp', 'timestamptz', 'interval',\n 'json', 'jsonb', 'uuid', 'bytea', 'xml']) {\n results.push({ text: t, type: 'datatype' });\n }\n }\n return results;\n }\n\n /** Find columns for a table reference, searching through schemas */\n private findColumns(tref: TableReference): ColumnMetadata[] {\n const schemas = tref.schema ? [tref.schema] : this.searchPath;\n for (const s of schemas) {\n const cols = this.metadata.tables[s]?.[tref.name] || this.metadata.views[s]?.[tref.name];\n if (cols) return cols;\n }\n return [];\n }\n\n private matchesTable(tref: TableReference, schema: string, table: string): boolean {\n if (tref.schema) return tref.schema === schema && tref.name === table;\n return tref.name === table && this.searchPath.includes(schema);\n }\n\n private getVisibleSchemas(): string[] {\n // Return search path schemas plus any other schemas in metadata\n const all = new Set(this.searchPath);\n for (const kind of ['tables', 'views', 'functions', 'datatypes'] as const) {\n for (const s of Object.keys(this.metadata[kind])) {\n all.add(s);\n }\n }\n return [...all];\n }\n}\n\nfunction fuzzyMatch(pattern: string, text: string): boolean {\n let pi = 0;\n for (let ti = 0; ti < text.length && pi < pattern.length; ti++) {\n if (text[ti] === pattern[pi]) pi++;\n }\n return pi === pattern.length;\n}\n","/** SQL keywords organized by category for context-aware completion */\n\nexport const KEYWORDS: string[] = [\n // DML\n 'SELECT', 'FROM', 'WHERE', 'AND', 'OR', 'NOT', 'IN', 'EXISTS',\n 'BETWEEN', 'LIKE', 'ILIKE', 'IS', 'NULL', 'TRUE', 'FALSE',\n 'AS', 'ON', 'USING', 'JOIN', 'INNER', 'LEFT', 'RIGHT', 'FULL',\n 'OUTER', 'CROSS', 'NATURAL', 'ORDER', 'BY', 'ASC', 'DESC',\n 'NULLS', 'FIRST', 'LAST', 'GROUP', 'HAVING', 'LIMIT', 'OFFSET',\n 'UNION', 'ALL', 'INTERSECT', 'EXCEPT', 'DISTINCT',\n 'INSERT', 'INTO', 'VALUES', 'DEFAULT', 'RETURNING',\n 'UPDATE', 'SET',\n 'DELETE',\n 'WITH', 'RECURSIVE',\n 'CASE', 'WHEN', 'THEN', 'ELSE', 'END',\n 'CAST', 'COALESCE', 'NULLIF', 'GREATEST', 'LEAST',\n // DDL\n 'CREATE', 'ALTER', 'DROP', 'TRUNCATE',\n 'TABLE', 'VIEW', 'INDEX', 'SEQUENCE', 'SCHEMA', 'DATABASE',\n 'FUNCTION', 'PROCEDURE', 'TRIGGER', 'TYPE', 'EXTENSION',\n 'MATERIALIZED', 'TEMPORARY', 'TEMP', 'UNLOGGED',\n 'IF', 'CASCADE', 'RESTRICT',\n 'ADD', 'COLUMN', 'RENAME', 'TO',\n 'PRIMARY', 'KEY', 'FOREIGN', 'REFERENCES', 'UNIQUE',\n 'CHECK', 'CONSTRAINT', 'NOT NULL',\n // Data types\n 'INTEGER', 'INT', 'BIGINT', 'SMALLINT', 'SERIAL', 'BIGSERIAL',\n 'REAL', 'DOUBLE', 'PRECISION', 'NUMERIC', 'DECIMAL',\n 'TEXT', 'VARCHAR', 'CHAR', 'CHARACTER', 'VARYING',\n 'BOOLEAN', 'BOOL',\n 'DATE', 'TIME', 'TIMESTAMP', 'TIMESTAMPTZ', 'INTERVAL',\n 'JSON', 'JSONB', 'UUID', 'BYTEA', 'ARRAY',\n // Transaction\n 'BEGIN', 'COMMIT', 'ROLLBACK', 'SAVEPOINT',\n // Other\n 'GRANT', 'REVOKE', 'EXPLAIN', 'ANALYZE', 'VERBOSE',\n 'COPY', 'VACUUM', 'REINDEX', 'CLUSTER',\n 'LATERAL', 'WINDOW', 'OVER', 'PARTITION', 'ROWS', 'RANGE',\n 'FETCH', 'NEXT', 'PRIOR', 'ABSOLUTE', 'RELATIVE',\n 'FOR', 'SHARE', 'NOWAIT', 'SKIP', 'LOCKED',\n 'ANY', 'SOME',\n];\n\n/** Keywords that commonly follow other keywords */\nexport const KEYWORD_TREE: Record<string, string[]> = {\n 'SELECT': ['DISTINCT', 'ALL', '*'],\n 'FROM': [],\n 'WHERE': [],\n 'ORDER': ['BY'],\n 'GROUP': ['BY'],\n 'INSERT': ['INTO'],\n 'UPDATE': ['SET'],\n 'DELETE': ['FROM'],\n 'CREATE': ['TABLE', 'VIEW', 'INDEX', 'SCHEMA', 'DATABASE', 'FUNCTION',\n 'PROCEDURE', 'TRIGGER', 'TYPE', 'EXTENSION', 'MATERIALIZED',\n 'TEMPORARY', 'TEMP', 'UNLOGGED', 'UNIQUE', 'OR'],\n 'ALTER': ['TABLE', 'VIEW', 'INDEX', 'SCHEMA', 'DATABASE', 'FUNCTION',\n 'PROCEDURE', 'TRIGGER', 'TYPE', 'EXTENSION', 'SEQUENCE'],\n 'DROP': ['TABLE', 'VIEW', 'INDEX', 'SCHEMA', 'DATABASE', 'FUNCTION',\n 'PROCEDURE', 'TRIGGER', 'TYPE', 'EXTENSION', 'SEQUENCE',\n 'IF'],\n 'JOIN': [],\n 'INNER': ['JOIN'],\n 'LEFT': ['JOIN', 'OUTER'],\n 'RIGHT': ['JOIN', 'OUTER'],\n 'FULL': ['JOIN', 'OUTER'],\n 'CROSS': ['JOIN'],\n 'NATURAL': ['JOIN', 'LEFT', 'RIGHT', 'FULL', 'INNER'],\n 'OUTER': ['JOIN'],\n 'IF': ['EXISTS', 'NOT'],\n 'NOT': ['NULL', 'EXISTS', 'IN', 'BETWEEN', 'LIKE', 'ILIKE'],\n 'IS': ['NULL', 'NOT', 'TRUE', 'FALSE', 'DISTINCT'],\n 'OR': ['REPLACE'],\n 'UNION': ['ALL'],\n 'LIMIT': [],\n 'OFFSET': [],\n 'SET': [],\n 'VALUES': [],\n 'ON': [],\n 'RETURNING': [],\n 'INTO': [],\n 'GRANT': ['ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'USAGE'],\n 'REVOKE': ['ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'USAGE'],\n 'WITH': ['RECURSIVE'],\n};\n\n/** Reserved words that require quoting when used as identifiers */\nexport const RESERVED_WORDS = new Set([\n 'ALL', 'ANALYSE', 'ANALYZE', 'AND', 'ANY', 'ARRAY', 'AS', 'ASC',\n 'ASYMMETRIC', 'AUTHORIZATION', 'BETWEEN', 'BINARY', 'BOTH', 'CASE',\n 'CAST', 'CHECK', 'COLLATE', 'COLLATION', 'COLUMN', 'CONCURRENTLY',\n 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT_CATALOG', 'CURRENT_DATE',\n 'CURRENT_ROLE', 'CURRENT_SCHEMA', 'CURRENT_TIME', 'CURRENT_TIMESTAMP',\n 'CURRENT_USER', 'DEFAULT', 'DEFERRABLE', 'DESC', 'DISTINCT', 'DO',\n 'ELSE', 'END', 'EXCEPT', 'FALSE', 'FETCH', 'FOR', 'FOREIGN', 'FREEZE',\n 'FROM', 'FULL', 'GRANT', 'GROUP', 'HAVING', 'ILIKE', 'IN', 'INITIALLY',\n 'INNER', 'INTERSECT', 'INTO', 'IS', 'ISNULL', 'JOIN', 'LATERAL',\n 'LEADING', 'LEFT', 'LIKE', 'LIMIT', 'LOCALTIME', 'LOCALTIMESTAMP',\n 'NATURAL', 'NOT', 'NOTNULL', 'NULL', 'OFFSET', 'ON', 'ONLY', 'OR',\n 'ORDER', 'OUTER', 'OVERLAPS', 'PLACING', 'PRIMARY', 'REFERENCES',\n 'RETURNING', 'RIGHT', 'SELECT', 'SESSION_USER', 'SIMILAR', 'SOME',\n 'SYMMETRIC', 'TABLE', 'TABLESAMPLE', 'THEN', 'TO', 'TRAILING', 'TRUE',\n 'UNION', 'UNIQUE', 'USER', 'USING', 'VARIADIC', 'VERBOSE', 'WHEN',\n 'WHERE', 'WINDOW', 'WITH',\n]);\n\n/** Built-in PostgreSQL functions */\nexport const BUILTIN_FUNCTIONS: string[] = [\n // Aggregate\n 'avg', 'count', 'max', 'min', 'sum',\n 'array_agg', 'string_agg', 'bool_and', 'bool_or',\n 'json_agg', 'jsonb_agg', 'json_object_agg', 'jsonb_object_agg',\n // String\n 'length', 'lower', 'upper', 'trim', 'ltrim', 'rtrim',\n 'substring', 'replace', 'concat', 'concat_ws',\n 'left', 'right', 'repeat', 'reverse', 'split_part',\n 'starts_with', 'format', 'regexp_replace', 'regexp_matches',\n // Numeric\n 'abs', 'ceil', 'floor', 'round', 'trunc', 'mod', 'power', 'sqrt',\n 'random', 'generate_series',\n // Date/Time\n 'now', 'current_date', 'current_time', 'current_timestamp',\n 'date_trunc', 'date_part', 'extract', 'age',\n 'to_char', 'to_date', 'to_timestamp', 'to_number',\n 'make_date', 'make_time', 'make_timestamp',\n // JSON\n 'json_build_object', 'jsonb_build_object',\n 'json_build_array', 'jsonb_build_array',\n 'json_extract_path', 'jsonb_extract_path',\n 'json_extract_path_text', 'jsonb_extract_path_text',\n 'json_array_length', 'jsonb_array_length',\n 'json_each', 'jsonb_each', 'json_each_text', 'jsonb_each_text',\n 'json_typeof', 'jsonb_typeof',\n 'row_to_json', 'to_json', 'to_jsonb',\n // Array\n 'array_length', 'array_dims', 'array_lower', 'array_upper',\n 'array_append', 'array_prepend', 'array_cat', 'array_remove',\n 'array_position', 'array_positions', 'unnest',\n // Type casting\n 'cast',\n // Window\n 'row_number', 'rank', 'dense_rank', 'percent_rank', 'cume_dist',\n 'ntile', 'lag', 'lead', 'first_value', 'last_value', 'nth_value',\n // System\n 'current_database', 'current_schema', 'current_user', 'session_user',\n 'pg_typeof', 'version',\n // Conditional\n 'coalesce', 'nullif', 'greatest', 'least',\n];\n","/**\n * Simple SQL statement parser to understand context for completions.\n * This is a lightweight port of pgcli's sqlcompletion.suggest_type logic.\n * Instead of using sqlparse (Python), we do regex + token-based parsing.\n */\n\nimport { TableReference } from './types';\n\n/** Represents the context we've determined from the SQL */\nexport type SuggestionContext =\n | { type: 'keyword'; lastToken?: string }\n | { type: 'table'; schema: string | null }\n | { type: 'view'; schema: string | null }\n | { type: 'column'; tableRefs: TableReference[]; qualifiable: boolean; parent?: string }\n | { type: 'function'; schema: string | null }\n | { type: 'schema' }\n | { type: 'from_clause'; schema: string | null; tableRefs: TableReference[] }\n | { type: 'join'; tableRefs: TableReference[]; schema: string | null }\n | { type: 'join_condition'; tableRefs: TableReference[]; parent?: string }\n | { type: 'alias'; aliases: string[] }\n | { type: 'database' }\n | { type: 'datatype'; schema: string | null };\n\n/**\n * Determine what types of completions to suggest based on SQL text.\n */\nexport function suggestType(fullText: string, textBeforeCursor: string): SuggestionContext[] {\n const trimmed = textBeforeCursor.trimEnd();\n \n // Extract word being typed (non-whitespace at end)\n const wordMatch = textBeforeCursor.match(/([A-Za-z0-9_.\"$]+)$/);\n const wordBeforeCursor = wordMatch ? wordMatch[1] : '';\n \n // Get text without the partial word (for context analysis)\n const textForAnalysis = wordBeforeCursor\n ? textBeforeCursor.slice(0, -wordBeforeCursor.length)\n : textBeforeCursor;\n\n // Check if typing a schema-qualified name (e.g. \"schema.\" or \"table.\")\n const dotMatch = wordBeforeCursor.match(/^([A-Za-z_][A-Za-z0-9_]*)\\.(.*)$/);\n \n // Find tables referenced in the query\n const tableRefs = extractTables(fullText);\n \n // Find the last significant keyword\n const lastKeyword = findLastKeyword(textForAnalysis);\n const lastKw = lastKeyword?.toUpperCase() || '';\n\n // If we have a dot, we're qualifying something\n if (dotMatch) {\n const parent = dotMatch[1];\n // Check if parent matches a table alias or table name\n const matchingTables = tableRefs.filter(t =>\n t.alias === parent || t.name === parent ||\n (t.schema && `${t.schema}.${t.name}` === parent)\n );\n \n // Could be table.column OR schema.table — suggest both\n const suggestions: SuggestionContext[] = [];\n if (matchingTables.length > 0) {\n suggestions.push({ type: 'column', tableRefs: matchingTables, qualifiable: false, parent });\n }\n // Also suggest schema-qualified objects\n suggestions.push(\n { type: 'table', schema: parent },\n { type: 'view', schema: parent },\n { type: 'function', schema: parent },\n );\n return suggestions;\n }\n\n // Context-based suggestions\n if (!lastKw || lastKw === '') {\n return [{ type: 'keyword' }];\n }\n\n if (lastKw === 'SELECT' || lastKw === 'WHERE' || lastKw === 'HAVING' ||\n lastKw === 'ORDER BY' || lastKw === 'DISTINCT') {\n return [\n { type: 'column', tableRefs, qualifiable: tableRefs.length > 1 },\n { type: 'function', schema: null },\n { type: 'keyword', lastToken: lastKw },\n ];\n }\n\n if (lastKw === 'FROM' || lastKw === 'COPY' || lastKw === 'UPDATE' ||\n lastKw === 'INTO' || lastKw === 'INSERT INTO' || lastKw === 'TRUNCATE') {\n const isFrom = lastKw === 'FROM';\n const suggestions: SuggestionContext[] = [{ type: 'schema' }];\n if (isFrom) {\n suggestions.push({ type: 'from_clause', schema: null, tableRefs });\n } else {\n suggestions.push({ type: 'table', schema: null });\n suggestions.push({ type: 'view', schema: null });\n }\n return suggestions;\n }\n\n if (lastKw === 'JOIN' || lastKw.endsWith(' JOIN')) {\n const suggestions: SuggestionContext[] = [\n { type: 'schema' },\n { type: 'from_clause', schema: null, tableRefs },\n ];\n // Also suggest JOIN completions with ON clauses\n if (tableRefs.length > 0) {\n suggestions.push({ type: 'join', tableRefs, schema: null });\n }\n return suggestions;\n }\n\n if (lastKw === 'ON') {\n const aliases = tableRefs.map(t => t.alias || t.name);\n const suggestions: SuggestionContext[] = [\n { type: 'alias', aliases },\n ];\n if (tableRefs.length >= 2) {\n suggestions.push({ type: 'join_condition', tableRefs });\n }\n return suggestions;\n }\n\n if (lastKw === 'SET') {\n return [{ type: 'column', tableRefs, qualifiable: false }];\n }\n\n if (lastKw === 'TABLE' || lastKw === 'VIEW') {\n return [{ type: 'schema' }, { type: lastKw === 'TABLE' ? 'table' : 'view', schema: null }];\n }\n\n if (lastKw === 'FUNCTION') {\n return [{ type: 'schema' }, { type: 'function', schema: null }];\n }\n\n if (lastKw === 'SCHEMA') {\n return [{ type: 'schema' }];\n }\n\n if (lastKw === 'DATABASE') {\n return [{ type: 'database' }];\n }\n\n if (lastKw === 'TYPE' || lastKw === '::') {\n return [\n { type: 'datatype', schema: null },\n { type: 'table', schema: null },\n { type: 'schema' },\n ];\n }\n\n if (['CREATE', 'ALTER', 'DROP'].includes(lastKw)) {\n return [{ type: 'keyword', lastToken: lastKw }];\n }\n\n if (lastKw === 'AND' || lastKw === 'OR' || lastKw === ',' || lastKw === '=') {\n // Go back further to find real context\n const prevKw = findPrevSignificantKeyword(textForAnalysis);\n if (prevKw) {\n return suggestType(fullText, textForAnalysis);\n }\n }\n\n if (lastKw === 'AS') {\n return []; // Don't suggest anything for aliases\n }\n\n if (lastKw === 'COLUMN') {\n return [{ type: 'column', tableRefs, qualifiable: false }];\n }\n\n return [{ type: 'keyword', lastToken: lastKw }];\n}\n\n/**\n * Extract table references from SQL text.\n * Handles: FROM tbl, FROM schema.tbl, FROM tbl alias, FROM tbl AS alias,\n * JOIN tbl, UPDATE tbl, INSERT INTO tbl, etc.\n */\nexport function extractTables(sql: string): TableReference[] {\n const tables: TableReference[] = [];\n // Normalize whitespace\n const normalized = sql.replace(/\\s+/g, ' ').trim();\n \n // Pattern to match table references after FROM, JOIN, UPDATE, INTO, TABLE keywords\n const tableContextRegex = /\\b(?:FROM|JOIN|UPDATE|INTO|TABLE)\\s+/gi;\n let match: RegExpExecArray | null;\n\n while ((match = tableContextRegex.exec(normalized)) !== null) {\n const afterKeyword = normalized.slice(match.index + match[0].length);\n const refs = parseTableList(afterKeyword);\n tables.push(...refs);\n }\n\n return dedup(tables);\n}\n\nfunction parseTableList(text: string): TableReference[] {\n const tables: TableReference[] = [];\n // Split on commas for multi-table references (FROM a, b, c)\n const parts = splitOnCommas(text);\n \n for (const part of parts) {\n const ref = parseOneTableRef(part.trim());\n if (ref) tables.push(ref);\n }\n return tables;\n}\n\nfunction splitOnCommas(text: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let current = '';\n for (const ch of text) {\n if (ch === '(') depth++;\n else if (ch === ')') depth--;\n \n if (ch === ',' && depth === 0) {\n parts.push(current);\n current = '';\n } else if (depth < 0) {\n // End of context\n parts.push(current);\n break;\n } else if (/[;]/.test(ch) && depth === 0) {\n parts.push(current);\n break;\n } else {\n current += ch;\n }\n }\n if (current.trim()) parts.push(current);\n return parts;\n}\n\nfunction parseOneTableRef(text: string): TableReference | null {\n // Stop at keywords that end the table reference context\n const stopKeywords = /\\b(?:WHERE|SET|ORDER|GROUP|HAVING|LIMIT|OFFSET|UNION|INTERSECT|EXCEPT|ON|USING|RETURNING|VALUES|LEFT|RIGHT|INNER|OUTER|FULL|CROSS|NATURAL|JOIN)\\b/i;\n const stopMatch = text.match(stopKeywords);\n if (stopMatch) {\n text = text.slice(0, stopMatch.index!).trim();\n }\n \n if (!text) return null;\n\n // Match: [schema.]table [AS] [alias]\n const m = text.match(\n /^(?:\"([^\"]+)\"|([A-Za-z_][A-Za-z0-9_$]*))(?:\\.(?:\"([^\"]+)\"|([A-Za-z_][A-Za-z0-9_$]*)))?(?:\\s+(?:AS\\s+)?(?:\"([^\"]+)\"|([A-Za-z_][A-Za-z0-9_$]*)))?/i\n );\n \n if (!m) return null;\n\n const part1 = m[1] || m[2]; // first identifier\n const part2 = m[3] || m[4]; // second identifier (after dot)\n const alias = m[5] || m[6]; // alias\n \n // Check alias isn't a keyword\n const aliasUpper = alias?.toUpperCase();\n const keywordAlias = aliasUpper && /^(WHERE|SET|ORDER|GROUP|HAVING|LIMIT|OFFSET|ON|USING|JOIN|LEFT|RIGHT|INNER|OUTER|FULL|CROSS|NATURAL|AS|AND|OR|NOT|RETURNING|VALUES|INTO|FROM|SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)$/.test(aliasUpper);\n\n if (part2) {\n return {\n schema: part1.toLowerCase(),\n name: part2.toLowerCase(),\n alias: keywordAlias ? null : (alias?.toLowerCase() || null),\n isFunction: false,\n };\n }\n \n return {\n schema: null,\n name: part1.toLowerCase(),\n alias: keywordAlias ? null : (alias?.toLowerCase() || null),\n isFunction: false,\n };\n}\n\nfunction dedup(tables: TableReference[]): TableReference[] {\n const seen = new Set<string>();\n return tables.filter(t => {\n const key = `${t.schema || ''}.${t.name}.${t.alias || ''}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Find the last significant SQL keyword before cursor position.\n */\nfunction findLastKeyword(text: string): string | null {\n const trimmed = text.trimEnd();\n \n // Check for compound keywords first\n const compoundMatch = trimmed.match(/\\b(ORDER\\s+BY|GROUP\\s+BY|INSERT\\s+INTO|NOT\\s+IN|LEFT\\s+(?:OUTER\\s+)?JOIN|RIGHT\\s+(?:OUTER\\s+)?JOIN|FULL\\s+(?:OUTER\\s+)?JOIN|INNER\\s+JOIN|CROSS\\s+JOIN|NATURAL\\s+JOIN|DISTINCT\\s+ON)\\s*$/i);\n if (compoundMatch) {\n return compoundMatch[1].replace(/\\s+/g, ' ').toUpperCase();\n }\n\n // Simple keyword at end\n const simpleMatch = trimmed.match(/\\b([A-Za-z]+)\\s*$/);\n if (simpleMatch) {\n const kw = simpleMatch[1].toUpperCase();\n const knownKeywords = new Set([\n 'SELECT', 'FROM', 'WHERE', 'JOIN', 'ON', 'AND', 'OR', 'SET',\n 'INTO', 'UPDATE', 'INSERT', 'DELETE', 'CREATE', 'ALTER', 'DROP',\n 'TABLE', 'VIEW', 'FUNCTION', 'SCHEMA', 'DATABASE', 'AS', 'HAVING',\n 'ORDER', 'GROUP', 'DISTINCT', 'LIMIT', 'OFFSET', 'RETURNING',\n 'TRUNCATE', 'COPY', 'TYPE', 'COLUMN', 'VALUES',\n ]);\n if (knownKeywords.has(kw)) return kw;\n }\n\n // Check for special tokens\n if (trimmed.endsWith(',')) return ',';\n if (trimmed.endsWith('=')) return '=';\n if (trimmed.endsWith('::')) return '::';\n\n return null;\n}\n\nfunction findPrevSignificantKeyword(text: string): string | null {\n // Remove the last token and try again\n const withoutLast = text.replace(/\\S+\\s*$/, '').trim();\n return findLastKeyword(withoutLast);\n}\n\n/**\n * Get the ref name for a table reference (alias if available, else name)\n */\nexport function tableRef(t: TableReference): string {\n return t.alias || t.name;\n}\n","/**\n * Schema metadata fetching from PostgreSQL catalog tables.\n * Ported from pgcli's pgexecute.py\n */\n\nimport { Pool } from 'pg';\nimport type { SchemaMetadata, ColumnMetadata, ForeignKey, FunctionMetadata } from './types';\n\nexport async function fetchMetadata(pool: Pool): Promise<SchemaMetadata> {\n const meta: SchemaMetadata = {\n tables: {},\n views: {},\n functions: {},\n datatypes: {},\n };\n\n const [schemas, tables, views, tableCols, viewCols, functions, fks, datatypes] =\n await Promise.all([\n fetchSchemas(pool),\n fetchTables(pool),\n fetchViews(pool),\n fetchColumns(pool, ['r', 'p', 'f']),\n fetchColumns(pool, ['v', 'm']),\n fetchFunctions(pool),\n fetchForeignKeys(pool),\n fetchDatatypes(pool),\n ]);\n\n // Initialize schema buckets\n for (const schema of schemas) {\n meta.tables[schema] = meta.tables[schema] || {};\n meta.views[schema] = meta.views[schema] || {};\n meta.functions[schema] = meta.functions[schema] || {};\n meta.datatypes[schema] = meta.datatypes[schema] || {};\n }\n\n // Populate tables\n for (const { schema, name } of tables) {\n if (!meta.tables[schema]) meta.tables[schema] = {};\n meta.tables[schema][name] = [];\n }\n\n // Populate views\n for (const { schema, name } of views) {\n if (!meta.views[schema]) meta.views[schema] = {};\n meta.views[schema][name] = [];\n }\n\n // Populate table columns\n for (const col of tableCols) {\n const tbl = meta.tables[col.schema]?.[col.table];\n if (tbl) {\n tbl.push({\n name: col.name,\n datatype: col.datatype,\n hasDefault: col.hasDefault,\n default_: col.default_,\n foreignKeys: [],\n });\n }\n }\n\n // Populate view columns\n for (const col of viewCols) {\n const v = meta.views[col.schema]?.[col.view];\n if (v) {\n v.push({\n name: col.name,\n datatype: col.datatype,\n hasDefault: col.hasDefault,\n default_: col.default_,\n foreignKeys: [],\n });\n }\n }\n\n // Populate functions\n for (const f of functions) {\n if (!meta.functions[f.schemaName]) meta.functions[f.schemaName] = {};\n if (!meta.functions[f.schemaName][f.funcName]) {\n meta.functions[f.schemaName][f.funcName] = [];\n }\n meta.functions[f.schemaName][f.funcName].push(f);\n }\n\n // Populate foreign keys\n for (const fk of fks) {\n // Attach to child column\n const childCols = meta.tables[fk.childSchema]?.[fk.childTable];\n if (childCols) {\n const col = childCols.find(c => c.name === fk.childColumn);\n if (col) col.foreignKeys.push(fk);\n }\n // Attach to parent column\n const parentCols = meta.tables[fk.parentSchema]?.[fk.parentTable];\n if (parentCols) {\n const col = parentCols.find(c => c.name === fk.parentColumn);\n if (col) col.foreignKeys.push(fk);\n }\n }\n\n // Populate datatypes\n for (const dt of datatypes) {\n if (!meta.datatypes[dt.schema]) meta.datatypes[dt.schema] = {};\n meta.datatypes[dt.schema][dt.name] = null;\n }\n\n return meta;\n}\n\nasync function fetchSchemas(pool: Pool): Promise<string[]> {\n const { rows } = await pool.query(\n `SELECT nspname FROM pg_catalog.pg_namespace ORDER BY 1`\n );\n return rows.map(r => r.nspname);\n}\n\nasync function fetchTables(pool: Pool): Promise<{ schema: string; name: string }[]> {\n const { rows } = await pool.query(\n `SELECT n.nspname AS schema, c.relname AS name\n FROM pg_catalog.pg_class c\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n WHERE c.relkind = ANY($1)\n ORDER BY 1, 2`,\n [['r', 'p', 'f']]\n );\n return rows.map(r => ({ schema: r.schema, name: r.name }));\n}\n\nasync function fetchViews(pool: Pool): Promise<{ schema: string; name: string }[]> {\n const { rows } = await pool.query(\n `SELECT n.nspname AS schema, c.relname AS name\n FROM pg_catalog.pg_class c\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n WHERE c.relkind = ANY($1)\n ORDER BY 1, 2`,\n [['v', 'm']]\n );\n return rows.map(r => ({ schema: r.schema, name: r.name }));\n}\n\ninterface RawColumn {\n schema: string;\n table: string;\n view: string;\n name: string;\n datatype: string;\n hasDefault: boolean;\n default_: string | null;\n}\n\nasync function fetchColumns(pool: Pool, kinds: string[]): Promise<RawColumn[]> {\n const { rows } = await pool.query(\n `SELECT nsp.nspname AS schema,\n cls.relname AS table,\n att.attname AS name,\n att.atttypid::regtype::text AS datatype,\n att.atthasdef AS \"hasDefault\",\n pg_catalog.pg_get_expr(def.adbin, def.adrelid, true) AS \"default_\"\n FROM pg_catalog.pg_attribute att\n INNER JOIN pg_catalog.pg_class cls ON att.attrelid = cls.oid\n INNER JOIN pg_catalog.pg_namespace nsp ON cls.relnamespace = nsp.oid\n LEFT OUTER JOIN pg_attrdef def ON def.adrelid = att.attrelid AND def.adnum = att.attnum\n WHERE cls.relkind = ANY($1)\n AND NOT att.attisdropped\n AND att.attnum > 0\n ORDER BY 1, 2, att.attnum`,\n [kinds]\n );\n return rows.map(r => ({\n schema: r.schema,\n table: r.table,\n view: r.table,\n name: r.name,\n datatype: r.datatype,\n hasDefault: r.hasDefault,\n default_: r.default_,\n }));\n}\n\nasync function fetchFunctions(pool: Pool): Promise<FunctionMetadata[]> {\n const { rows } = await pool.query(\n `SELECT n.nspname AS \"schemaName\",\n p.proname AS \"funcName\",\n p.proargnames AS \"argNames\",\n COALESCE(proallargtypes::regtype[], proargtypes::regtype[])::text[] AS \"argTypes\",\n p.proargmodes AS \"argModes\",\n prorettype::regtype::text AS \"returnType\",\n p.prokind = 'a' AS \"isAggregate\",\n p.prokind = 'w' AS \"isWindow\",\n p.proretset AS \"isSetReturning\",\n d.deptype = 'e' AS \"isExtension\"\n FROM pg_catalog.pg_proc p\n INNER JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n LEFT JOIN pg_depend d ON d.objid = p.oid AND d.deptype = 'e'\n WHERE p.prorettype::regtype != 'trigger'::regtype\n ORDER BY 1, 2`\n );\n return rows.map(r => ({\n ...r,\n isPublic: r.schemaName === 'public',\n isExtension: !!r.isExtension,\n }));\n}\n\ninterface RawForeignKey {\n parentSchema: string;\n parentTable: string;\n parentColumn: string;\n childSchema: string;\n childTable: string;\n childColumn: string;\n}\n\nasync function fetchForeignKeys(pool: Pool): Promise<RawForeignKey[]> {\n const { rows } = await pool.query(\n `SELECT s_p.nspname AS \"parentSchema\",\n t_p.relname AS \"parentTable\",\n unnest((\n SELECT array_agg(attname ORDER BY i)\n FROM (SELECT unnest(confkey) AS attnum, generate_subscripts(confkey, 1) AS i) x\n JOIN pg_catalog.pg_attribute c USING(attnum)\n WHERE c.attrelid = fk.confrelid\n )) AS \"parentColumn\",\n s_c.nspname AS \"childSchema\",\n t_c.relname AS \"childTable\",\n unnest((\n SELECT array_agg(attname ORDER BY i)\n FROM (SELECT unnest(conkey) AS attnum, generate_subscripts(conkey, 1) AS i) x\n JOIN pg_catalog.pg_attribute c USING(attnum)\n WHERE c.attrelid = fk.conrelid\n )) AS \"childColumn\"\n FROM pg_catalog.pg_constraint fk\n JOIN pg_catalog.pg_class t_p ON t_p.oid = fk.confrelid\n JOIN pg_catalog.pg_namespace s_p ON s_p.oid = t_p.relnamespace\n JOIN pg_catalog.pg_class t_c ON t_c.oid = fk.conrelid\n JOIN pg_catalog.pg_namespace s_c ON s_c.oid = t_c.relnamespace\n WHERE fk.contype = 'f'`\n );\n return rows;\n}\n\nasync function fetchDatatypes(pool: Pool): Promise<{ schema: string; name: string }[]> {\n const { rows } = await pool.query(\n `SELECT n.nspname AS schema, t.typname AS name\n FROM pg_catalog.pg_type t\n INNER JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid))\n AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n ORDER BY 1, 2`\n );\n return rows;\n}\n\n/** Fetch current search path */\nexport async function fetchSearchPath(pool: Pool): Promise<string[]> {\n const { rows } = await pool.query(\n `SELECT * FROM unnest(current_schemas(true))`\n );\n return rows.map(r => r.unnest);\n}\n"],"mappings":"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","names":[]}