import pg from "pg"; import { type Queryable } from "../db/connect.js"; /** * A connection that cannot write, and can be shown not to. * * `crossline verify` is the one command a founder is invited to point at a * production database, so "we only issue reads" being *true* is not enough — * it has to be checkable without reading the code. Three independent guards, * each of which alone would be sufficient, because the cost of one of them * quietly rotting is the whole feature: * * 1. **The statement allowlist.** Every string that reaches Postgres through * this class must begin with `select` or `with` once comments are stripped. * Anything else throws before it is sent. Not a sanitiser — the SQL here is * all our own — but a tripwire on the next person who adds a query. * 2. **A read-only transaction.** The session opens `begin` then * `set transaction read only`, so the *server* refuses any write, including * one that got past the allowlist. This is not a rolled-back write: nothing * is attempted and nothing needs excusing. The transaction is committed, * not rolled back, because it never did anything to undo. * 3. **The type.** It exposes {@link Queryable} and nothing else, so it cannot * be handed to seeding or probing, which need `inRollback`. * * `set transaction read only` rather than the `default_transaction_read_only` * startup parameter: pgbouncer rejects startup parameters it does not know, and * the pooled connection string is the one Supabase's dashboard offers first. * A guarantee that breaks on the most commonly pasted URL is not a guarantee. */ export declare class CatalogReader implements Queryable { private readonly db; private readonly client; private constructor(); /** Statements this class will send. Anything else is a bug, loudly. */ private static readonly ALLOWED; static open(connectionString: string): Promise; query(sql: string, params?: unknown[]): Promise>; close(): Promise; }