{"version":3,"sources":["/Users/grichardson/Documents/dev/supabase/pg-parser/packages/pg-parser/dist/index.cjs","../src/errors.ts","../src/constants.ts","../src/util.ts","../src/pg-parser.ts"],"names":[],"mappings":"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","file":"/Users/grichardson/Documents/dev/supabase/pg-parser/packages/pg-parser/dist/index.cjs","sourcesContent":[null,"export type ParseErrorType = 'syntax' | 'semantic' | 'unknown';\n\nexport type ParseErrorDetails = {\n  type: ParseErrorType;\n  position: number;\n};\n\nexport class ParseError extends Error {\n  override readonly name = 'ParseError';\n\n  /**\n   * The type of parse error. Possible values are:\n   *\n   * - `syntax`: A lexical or syntactic error, such as mismatched parentheses,\n   *   unterminated quotes, invalid tokens, or incorrect SQL statement structure.\n   *   Most SQL errors will fall into this category.\n   *\n   * - `semantic`: These are rare, but can occur during specific validations like\n   *   numeric range checking (e.g., column numbers must be between 1 and 32767\n   *   in ALTER INDEX statements).\n   *\n   * - `unknown`: An unknown error type, typically representing an internal parser error.\n   *\n   * Note: The vast majority of semantic validation (type checking, schema validation,\n   * constraint validation, etc.) happens after parsing and is not represented in these error types.\n   */\n  type: ParseErrorType;\n\n  /**\n   * The position of the error in the SQL string.\n   * This is a zero-based index, so the first character is at position 0.\n   * Points to the character where the error was detected.\n   */\n  position: number;\n\n  constructor(message: string, { type, position }: ParseErrorDetails) {\n    super(message);\n    this.type = type;\n    this.position = position;\n  }\n}\n\n/**\n * Get the type of parse error based on the internal file name\n * returned from libpg_query.\n */\nexport function getParseErrorType(fileName: string): ParseErrorType {\n  switch (fileName) {\n    case 'scan.l':\n      return 'syntax';\n    case 'gram.y':\n      return 'semantic';\n    default:\n      return 'unknown';\n  }\n}\n","export const SUPPORTED_VERSIONS = [15, 16, 17] as const;\n","import { SUPPORTED_VERSIONS } from './constants.js';\nimport type {\n  Node,\n  ParseResult,\n  SupportedVersion,\n  WrappedParseResult,\n} from './types/index.js';\n\n/**\n * Extracts keys from a union type.\n */\ntype ExtractKeys<T> = T extends T ? keyof T : never;\n\n/**\n * Unwraps a Node to get its underlying value based on\n * the specified type of the node.\n */\nexport type NodeValue<T extends Node, U extends ExtractKeys<T>> =\n  T extends Record<U, infer V> ? V : never;\n\n/**\n * Unwraps a Node into its type and value.\n */\nexport type UnwrappedNode<T extends Node> =\n  T extends Record<infer K, infer V> ? { type: K; node: V } : never;\n\n/**\n * Unwraps a `WrappedParseResult` by throwing an error if the result\n * contains an `error`, or otherwise returning the parsed `tree`.\n *\n * Supports both synchronous and asynchronous results.\n */\nexport async function unwrapParseResult<Version extends SupportedVersion>(\n  result: WrappedParseResult<Version> | Promise<WrappedParseResult<Version>>\n) {\n  const resolved = await result;\n  if (resolved.error) {\n    throw resolved.error;\n  }\n  return resolved.tree;\n}\n\n/**\n * Gets a list of supported Postgres versions.\n */\nexport function getSupportedVersions() {\n  return SUPPORTED_VERSIONS;\n}\n\n/**\n * Type guard to check if the major Postgres version is supported.\n */\nexport function isSupportedVersion(\n  version: number\n): version is SupportedVersion {\n  return SUPPORTED_VERSIONS.includes(version as SupportedVersion);\n}\n\n/**\n * Type guard to check if the `ParseResult` is of a specific version.\n */\nexport function isParseResultVersion<Version extends SupportedVersion>(\n  result: ParseResult,\n  version: Version\n): result is ParseResult<Version> {\n  if (!result.version) {\n    return false;\n  }\n\n  // `result.version` looks like 170004\n  const versionString = result.version.toString();\n\n  try {\n    // Strip away the last 4 digits\n    const majorVersion = parseInt(versionString.slice(0, -4), 10);\n\n    // Compare the major version with the provided version\n    return majorVersion === version;\n  } catch (error) {\n    return false;\n  }\n}\n\n/**\n * Asserts that a value is defined.\n *\n * Useful for type narrowing.\n */\nexport function assertDefined<T>(\n  value: T | undefined,\n  errorMessage: string\n): asserts value is T {\n  if (value === undefined) {\n    throw new Error(errorMessage);\n  }\n}\n\n/**\n * Unwraps a `Node` to get its type and underlying value.\n *\n * Unwrapping makes it easier to work with nodes\n * by allowing you to narrow them based on their type.\n *\n * @example\n * const tree = await unwrapParseResult(parser.parse('SELECT 1'));\n * const firstStmt = tree.stmts.[0].stmt;\n * const { type, node } = unwrapNode(firstStmt);\n *\n * switch (type) {\n *  case 'SelectStmt':\n *    // Now `node` is narrowed to `SelectStmt`\n *    break;\n * }\n */\nexport function unwrapNode<T extends Node>(wrappedNode: T) {\n  const keys = Object.keys(wrappedNode) as ExtractKeys<T>[];\n\n  if (keys.length === 0) {\n    throw new Error('node has no keys, expected a single key');\n  }\n\n  if (keys.length > 1) {\n    throw new Error(\n      `node has multiple keys, expected a single key: ${keys.join(', ')}`\n    );\n  }\n\n  const [type] = keys;\n\n  if (!type) {\n    throw new Error('node has no keys, expected a single key');\n  }\n\n  const node = wrappedNode[type];\n\n  return { type, node } as UnwrappedNode<T>;\n}\n\n/**\n * Asserts that a `Node` is a specific type and\n * unwraps its underlying value.\n *\n * @returns The unwrapped `Node` value.\n * @throws If `node` is not of type `type`.\n */\nexport function assertAndUnwrapNode<T extends Node, U extends ExtractKeys<T>>(\n  wrappedNode: T,\n  expectedType: U,\n  errorMessage?: string\n): NodeValue<T, U> {\n  const { type, node } = unwrapNode(wrappedNode);\n\n  if (type !== expectedType) {\n    throw new Error(\n      errorMessage ?? `expected node of type ${expectedType}, got ${type}`\n    );\n  }\n\n  return node as NodeValue<T, U>;\n}\n","import {\n  getParseErrorType,\n  ParseError,\n  type ParseErrorType,\n} from './errors.js';\nimport type {\n  MainModule,\n  PgParserModule,\n  SupportedVersion,\n  WrappedParseResult,\n} from './types/index.js';\nimport { isSupportedVersion } from './util.js';\n\nexport type PgParserOptions<Version extends SupportedVersion> = {\n  version?: Version | number;\n};\n\nexport class PgParser<Version extends SupportedVersion = 17> {\n  readonly ready: Promise<void>;\n  readonly version: Version;\n\n  #module: Promise<MainModule<Version>>;\n\n  /**\n   * Creates a new PgParser instance with the given options.\n   */\n  constructor({ version = 17 }: PgParserOptions<Version> = {}) {\n    if (!isSupportedVersion(version)) {\n      throw new Error(`unsupported version: ${version}`);\n    }\n\n    this.#module = this.#init(version);\n    this.ready = this.#module.then();\n    this.version = version as Version;\n  }\n\n  /**\n   * Initializes the WASM module.\n   */\n  async #init(version: SupportedVersion) {\n    const createModule = await this.#loadFactory(version);\n    return await createModule();\n  }\n\n  /**\n   * Loads the WASM module factory for the given version.\n   *\n   * Note we intentionally don't use template strings on a single import\n   * statement to avoid bundling issues that occur during static analysis.\n   */\n  async #loadFactory(version: SupportedVersion) {\n    switch (version) {\n      case 15:\n        return await import('../wasm/15/pg-parser.js').then<\n          PgParserModule<Version>\n        >((module) => module.default);\n      case 16:\n        return await import('../wasm/16/pg-parser.js').then<\n          PgParserModule<Version>\n        >((module) => module.default);\n      case 17:\n        return await import('../wasm/17/pg-parser.js').then<\n          PgParserModule<Version>\n        >((module) => module.default);\n      default:\n        throw new Error(`unsupported version: ${version}`);\n    }\n  }\n\n  /**\n   * Parses the given SQL string to a Postgres AST.\n   */\n  async parse(sql: string) {\n    const module = await this.#module;\n\n    const sqlPtr = module._malloc(sql.length + 1); // +1 for null terminator\n    module.stringToUTF8(sql, sqlPtr, sql.length + 1);\n\n    const resultPtr = module._parse_sql(sqlPtr);\n    module._free(sqlPtr);\n\n    const parseResult = await this.#parsePgQueryParseResult(resultPtr);\n    module._free_parse_result(resultPtr);\n\n    return parseResult;\n  }\n\n  /**\n   * Parses a PgQueryParseResult struct from a pointer\n   */\n  async #parsePgQueryParseResult(\n    resultPtr: number\n  ): Promise<WrappedParseResult<Version>> {\n    const module = await this.#module;\n\n    const parseTreePtr = module.getValue(resultPtr, 'i32');\n    const stderrBufferPtr = module.getValue(resultPtr + 4, 'i32');\n    const errorPtr = module.getValue(resultPtr + 8, 'i32');\n\n    const tree = parseTreePtr\n      ? JSON.parse(module.UTF8ToString(parseTreePtr))\n      : undefined;\n\n    // TODO: add debug mode + print this to stdout/stderr\n    const stderrBuffer = stderrBufferPtr\n      ? module.UTF8ToString(stderrBufferPtr)\n      : undefined;\n\n    const error = errorPtr\n      ? await this.#parsePgQueryError(errorPtr)\n      : undefined;\n\n    if (error) {\n      return {\n        tree: undefined,\n        error,\n      };\n    }\n\n    if (!tree) {\n      throw new Error('both parse tree and error are undefined');\n    }\n\n    return {\n      tree,\n      error: undefined,\n    };\n  }\n\n  /**\n   * Parses a PgQueryError struct from a pointer.\n   *\n   * The struct fields are defined in the C code as:\n   * ```c\n   * typedef struct {\n   *   char *message;\n   *   char *funcname;\n   *   char *filename;\n   *   int lineno;\n   *   int cursorpos;\n   *   char *context;\n   * } PgQueryError;\n   * ```\n   *\n   * We only care about the message and cursorpos fields, along with\n   * filename to determine the error type (syntax vs semantic).\n   */\n  async #parsePgQueryError(errorPtr: number) {\n    const module = await this.#module;\n\n    const messagePtr = module.getValue(errorPtr, 'i32');\n    const fileNamePtr = module.getValue(errorPtr + 8, 'i32');\n    const position = module.getValue(errorPtr + 16, 'i32') - 1; // Convert to zero-based index\n\n    const message = messagePtr\n      ? module.UTF8ToString(messagePtr)\n      : 'unknown error';\n    const type: ParseErrorType = fileNamePtr\n      ? getParseErrorType(module.UTF8ToString(fileNamePtr))\n      : 'unknown';\n\n    const error = new ParseError(message, {\n      type,\n      position,\n    });\n\n    return error;\n  }\n}\n"]}