{"version":3,"sources":["../../src/pglite/index.ts"],"sourcesContent":["/**\n * PGLite Transport for postgres.do\n *\n * Provides a local PostgreSQL implementation using PGLite WASM\n * that can be used as a transport layer for the postgres.do client.\n *\n * @example\n * ```typescript\n * import { postgres } from 'postgres.do'\n * import { createPGLiteTransport, PGLite } from 'postgres.do/pglite'\n *\n * // Create a PGLite instance (in-memory)\n * const pglite = new PGLite()\n * await pglite.waitReady\n *\n * // Create a postgres.do client with PGLite transport\n * const sql = postgres({ transport: createPGLiteTransport(pglite) })\n *\n * // Use like normal postgres.do client\n * const users = await sql`SELECT * FROM users`\n * ```\n */\n\nimport type { PGlite } from '@dotdo/pglite'\nimport type { Transport, Row, QueryResult, TransactionOptions } from '../types.js'\n\n// Re-export PGLite for convenience\nexport { PGlite } from '@dotdo/pglite'\n\n/**\n * PGLite transport configuration\n */\nexport interface PGLiteTransportConfig {\n  /**\n   * The PGLite instance to use for queries\n   */\n  pglite: PGlite\n\n  /**\n   * Whether to automatically initialize the PGLite instance\n   * Default: true\n   */\n  autoInit?: boolean\n}\n\n/**\n * PGLite Transport implementation\n *\n * Provides a Transport interface compatible with the postgres.do client\n * that uses PGLite WASM for local PostgreSQL execution.\n */\nexport class PGLiteTransport implements Transport {\n  private pglite: PGlite\n  private autoInit: boolean\n  private initialized = false\n\n  constructor(config: PGLiteTransportConfig) {\n    this.pglite = config.pglite\n    this.autoInit = config.autoInit ?? true\n  }\n\n  /**\n   * Ensure PGLite is ready before executing queries\n   */\n  private async ensureReady(): Promise<void> {\n    if (this.initialized) return\n\n    if (this.autoInit && this.pglite.waitReady) {\n      await this.pglite.waitReady\n    }\n\n    this.initialized = true\n  }\n\n  /**\n   * Execute a SQL query with optional parameters\n   */\n  async query<T extends Row = Row>(\n    sql: string,\n    params?: unknown[]\n  ): Promise<QueryResult<T>> {\n    await this.ensureReady()\n\n    const result = await this.pglite.query<T>(sql, params)\n\n    return {\n      rows: result.rows,\n      rowCount: result.affectedRows ?? result.rows.length,\n      fields: result.fields.map((field: { name: string; dataTypeID: number }) => ({\n        name: field.name,\n        dataTypeID: field.dataTypeID,\n        tableID: 0,\n        columnID: 0,\n        dataTypeSize: -1,\n        dataTypeModifier: -1,\n        format: 0,\n      })),\n      command: this.extractCommand(sql),\n    }\n  }\n\n  /**\n   * Execute multiple queries in a transaction\n   */\n  async transaction<T>(\n    queries: Array<{ sql: string; params?: unknown[] }>,\n    options?: TransactionOptions\n  ): Promise<T> {\n    await this.ensureReady()\n\n    // Build BEGIN statement with options\n    const beginParts = ['BEGIN']\n\n    if (options?.isolationLevel) {\n      // Validate isolation level to prevent SQL injection\n      const validLevels = ['read uncommitted', 'read committed', 'repeatable read', 'serializable']\n      const normalized = options.isolationLevel.toLowerCase()\n      if (!validLevels.includes(normalized)) {\n        throw new Error(`Invalid isolation level: \"${options.isolationLevel}\"`)\n      }\n      beginParts.push(`ISOLATION LEVEL ${normalized.toUpperCase()}`)\n    }\n    if (options?.readOnly) {\n      beginParts.push('READ ONLY')\n    }\n    if (options?.deferrable) {\n      beginParts.push('DEFERRABLE')\n    }\n\n    // Start transaction\n    await this.pglite.query(beginParts.join(' '))\n\n    try {\n      const results: unknown[] = []\n\n      for (const q of queries) {\n        const result = await this.pglite.query(q.sql, q.params)\n        results.push(result.rows)\n      }\n\n      await this.pglite.query('COMMIT')\n      return results as T\n    } catch (error) {\n      await this.pglite.query('ROLLBACK')\n      throw error\n    }\n  }\n\n  /**\n   * Close the PGLite connection\n   */\n  async close(): Promise<void> {\n    if (this.pglite.close) {\n      await this.pglite.close()\n    }\n    this.initialized = false\n  }\n\n  /**\n   * Check if the transport is connected (PGLite is always connected when initialized)\n   */\n  isConnected(): boolean {\n    // PGLite's ready property indicates if it's ready for queries\n    // The 'ready' property is true when PGLite has finished initialization\n    return this.initialized || this.pglite.ready === true\n  }\n\n  /**\n   * Get the underlying PGLite instance\n   */\n  getPGLite(): PGlite {\n    return this.pglite\n  }\n\n  /**\n   * Extract the SQL command type from a query string\n   */\n  private extractCommand(sql: string): string {\n    const trimmed = sql.trim().toUpperCase()\n    const firstWord = trimmed.split(/\\s+/)[0]\n    return firstWord || 'UNKNOWN'\n  }\n}\n\n/**\n * Create a PGLite transport from a PGLite instance\n *\n * @param pglite - The PGLite instance to use\n * @param options - Optional configuration\n * @returns A Transport implementation using PGLite\n *\n * @example\n * ```typescript\n * import { PGlite } from '@dotdo/pglite'\n * import { createPGLiteTransport } from 'postgres.do/pglite'\n *\n * const pglite = new PGlite()\n * const transport = createPGLiteTransport(pglite)\n * ```\n */\nexport function createPGLiteTransport(\n  pglite: PGlite,\n  options?: Omit<PGLiteTransportConfig, 'pglite'>\n): PGLiteTransport {\n  return new PGLiteTransport({\n    pglite,\n    ...options,\n  })\n}\n\n/**\n * Create a postgres.do-compatible SQL function backed by PGLite\n *\n * This provides a convenient way to use PGLite with the postgres.do API\n *\n * @param pgliteOrOptions - PGLite instance or PGLite options\n * @returns A postgres.do SQL tagged template function\n *\n * @example\n * ```typescript\n * import { createPGLiteSql } from 'postgres.do/pglite'\n *\n * // With existing PGLite instance\n * const pglite = new PGlite()\n * const sql = await createPGLiteSql(pglite)\n *\n * // Execute queries using postgres.do API\n * const users = await sql`SELECT * FROM users WHERE id = ${userId}`\n * ```\n */\nexport async function createPGLiteSql(pglite: PGlite): Promise<PGLiteSql> {\n  await pglite.waitReady\n\n  const transport = new PGLiteTransport({ pglite })\n\n  // Create the SQL tagged template function\n  const sql = function <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): Promise<T[]> {\n    // Build parameterized query\n    const parts: string[] = []\n    for (let i = 0; i < strings.length; i++) {\n      const str = strings[i]\n      if (str !== undefined) {\n        parts.push(str)\n      }\n      if (i < values.length) {\n        parts.push(`$${i + 1}`)\n      }\n    }\n    const query = parts.join('')\n\n    return transport.query<T>(query, values).then((result) => result.rows)\n  } as PGLiteSql\n\n  // Add unsafe method for raw queries\n  sql.unsafe = async <T extends Row = Row>(\n    query: string,\n    params?: unknown[]\n  ): Promise<T[]> => {\n    const result = await transport.query<T>(query, params)\n    return result.rows\n  }\n\n  // Add transaction support\n  sql.begin = async <T>(\n    fn: (sql: PGLiteTransactionSql) => Promise<T>,\n    options?: TransactionOptions\n  ): Promise<T> => {\n    await pglite.waitReady\n\n    // Build BEGIN statement with options\n    const beginParts = ['BEGIN']\n    if (options?.isolationLevel) {\n      // Validate isolation level to prevent SQL injection\n      const validLevels = ['read uncommitted', 'read committed', 'repeatable read', 'serializable']\n      const normalized = options.isolationLevel.toLowerCase()\n      if (!validLevels.includes(normalized)) {\n        throw new Error(`Invalid isolation level: \"${options.isolationLevel}\"`)\n      }\n      beginParts.push(`ISOLATION LEVEL ${normalized.toUpperCase()}`)\n    }\n    if (options?.readOnly) {\n      beginParts.push('READ ONLY')\n    }\n    if (options?.deferrable) {\n      beginParts.push('DEFERRABLE')\n    }\n\n    await pglite.query(beginParts.join(' '))\n\n    const txSql = createTransactionSql(pglite)\n\n    try {\n      const result = await fn(txSql)\n      await pglite.query('COMMIT')\n      return result\n    } catch (error) {\n      await pglite.query('ROLLBACK')\n      throw error\n    }\n  }\n\n  // Add savepoint (throws since it's only valid in transactions)\n  sql.savepoint = async <T>(): Promise<T> => {\n    throw new Error('savepoint() can only be called within a transaction')\n  }\n\n  // Add end method\n  sql.end = async (): Promise<void> => {\n    await transport.close()\n  }\n\n  // Add options for Drizzle compatibility\n  sql.options = {\n    parsers: {},\n    serializers: {},\n  }\n\n  // Add reserve method (creates a new client)\n  sql.reserve = async (): Promise<PGLiteReservedSql> => {\n    const reserved = await createPGLiteSql(pglite)\n    ;(reserved as PGLiteReservedSql).release = async () => {\n      // No-op for PGLite since connections are not pooled\n    }\n    return reserved as PGLiteReservedSql\n  }\n\n  // Add transport for direct access\n  sql.transport = transport\n\n  // Add pglite for direct access\n  sql.pglite = pglite\n\n  return sql\n}\n\n/**\n * Create a transaction-scoped SQL function\n */\nfunction createTransactionSql(pglite: PGlite): PGLiteTransactionSql {\n  let savepointCounter = 0\n\n  const txSql = function <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): Promise<T[]> {\n    const parts: string[] = []\n    for (let i = 0; i < strings.length; i++) {\n      const str = strings[i]\n      if (str !== undefined) {\n        parts.push(str)\n      }\n      if (i < values.length) {\n        parts.push(`$${i + 1}`)\n      }\n    }\n    const query = parts.join('')\n\n    return pglite.query<T>(query, values).then((result: { rows: T[] }) => result.rows)\n  } as PGLiteTransactionSql\n\n  txSql.unsafe = async <T extends Row = Row>(\n    query: string,\n    params?: unknown[]\n  ): Promise<T[]> => {\n    const result = await pglite.query<T>(query, params)\n    return result.rows\n  }\n\n  txSql.savepoint = async <T>(\n    fn: (sql: PGLiteTransactionSql) => Promise<T>\n  ): Promise<T> => {\n    const savepointName = `sp_${++savepointCounter}`\n    await pglite.query(`SAVEPOINT ${savepointName}`)\n\n    try {\n      const result = await fn(txSql)\n      await pglite.query(`RELEASE SAVEPOINT ${savepointName}`)\n      return result\n    } catch (error) {\n      await pglite.query(`ROLLBACK TO SAVEPOINT ${savepointName}`)\n      throw error\n    }\n  }\n\n  txSql.options = {\n    parsers: {},\n    serializers: {},\n  }\n\n  return txSql\n}\n\n/**\n * PGLite-backed SQL interface\n */\nexport interface PGLiteSql {\n  /**\n   * Execute a SQL query using tagged template literal\n   */\n  <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): Promise<T[]>\n\n  /**\n   * Execute raw SQL\n   */\n  unsafe<T extends Row = Row>(query: string, params?: unknown[]): Promise<T[]>\n\n  /**\n   * Begin a transaction\n   */\n  begin<T>(\n    fn: (sql: PGLiteTransactionSql) => Promise<T>,\n    options?: TransactionOptions\n  ): Promise<T>\n\n  /**\n   * Create a savepoint (only valid in transactions)\n   */\n  savepoint<T>(fn: (sql: PGLiteTransactionSql) => Promise<T>): Promise<T>\n\n  /**\n   * End the connection\n   */\n  end(): Promise<void>\n\n  /**\n   * Reserve a connection\n   */\n  reserve(): Promise<PGLiteReservedSql>\n\n  /**\n   * Options for Drizzle compatibility\n   */\n  options: {\n    parsers: Record<number, (value: string) => unknown>\n    serializers: Record<number, (value: unknown) => string>\n  }\n\n  /**\n   * The underlying transport\n   */\n  transport: PGLiteTransport\n\n  /**\n   * The underlying PGLite instance\n   */\n  pglite: PGlite\n}\n\n/**\n * Transaction-scoped SQL interface\n */\nexport interface PGLiteTransactionSql {\n  /**\n   * Execute a SQL query using tagged template literal\n   */\n  <T extends Row = Row>(\n    strings: TemplateStringsArray,\n    ...values: unknown[]\n  ): Promise<T[]>\n\n  /**\n   * Execute raw SQL\n   */\n  unsafe<T extends Row = Row>(query: string, params?: unknown[]): Promise<T[]>\n\n  /**\n   * Create a savepoint within the transaction\n   */\n  savepoint<T>(fn: (sql: PGLiteTransactionSql) => Promise<T>): Promise<T>\n\n  /**\n   * Options for Drizzle compatibility\n   */\n  options: {\n    parsers: Record<number, (value: string) => unknown>\n    serializers: Record<number, (value: unknown) => string>\n  }\n}\n\n/**\n * Reserved connection SQL interface\n */\nexport interface PGLiteReservedSql extends PGLiteSql {\n  /**\n   * Release the reserved connection\n   */\n  release(): Promise<void>\n}\n"],"mappings":"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","names":[]}