import type { AuthSection, ExtensionInfo, Manifest } from "./manifest.js"; import { afterCommit, type GrantsToRestore } from "./restore-engine.js"; /** * 恢复后要清掉的待处理认证状态,和 GoTrue 的 ClearAllPendingTokens 对齐:备份时发出去的找回密码、邮箱确认、 * 改邮箱改手机的链接和验证码,在新项目上一律作废。RECOVERY.md 的手工步骤用同一句 */ export declare const CLEAR_PENDING_AUTH_SQL: string; /** auth.dump 里恢复要用的东西:两段数据的目录行、要补建的触发器、数据段的列 */ export interface AuthArchive { path: string; usersData: string; identitiesData: string; triggers: Array<{ name: string; entry: string; }>; /** 数据段里的列和类型(建表语句的列减去生成列,pg_dump 不导出生成列) */ columns: Record<"users" | "identities", Array<{ name: string; type: string; }>>; } /** 读 auth.dump 的目录和两张表的建表语句。不碰目标 */ export declare function readAuthArchive(path: string, manifest: Manifest, workDir: string): Promise; /** * 只读预检(dry-run 和正式执行共用):目标得是一个新项目的 Auth——两张表在、没有用户、没有用户自己的触发器和策略, * 列能装下备份的数据。返回拦下的原因,空数组 = 能恢复 */ export declare function authRestorePreflight(targetUrl: string, archive: AuthArchive): Promise; /** * 主 dump 里的大对象。pg_restore 输出 SQL 时会在它们前后自己写 BEGIN; / COMMIT;,混进这个事务就会提前提交。 * 有的话这条路不能走,由调用方拦下。备份端的主 dump 总带 --schema,pg_dump 这时默认不导出大对象, * 所以正常的快照里不会有:这是兜底,防的是别处来的归档 */ export declare function largeObjectEntries(dumpPath: string): Promise; export declare function emitsRestrict([major, minor]: [number, number]): boolean; /** * psql 要能安全地执行 pg_restore 写出来的 SQL:pg_restore 得是带 \restrict 的版本,psql 和它同一个客户端包、 * 不比它旧(旧 psql 不认识 \restrict)。返回拦下的原因,null = 可以 */ export declare function psqlProblem(): Promise; /** * pg_restore -f - 的输出开头:第一条不是注释、不是空行的行必须是 `\restrict <密钥>`。还没读到完整的那一行时 * 返回 "more"。不是它就不交给 psql:没有受限模式,归档内容里的元命令会被执行 */ export declare function restrictHeader(text: string): "ok" | "missing" | "more"; /** * 等 stdin 能再写(drain)或者 psql 已经退出。监听用完就摘掉:大库恢复要等几十万次, * 挂在一个直到最后才结束的 Promise 上的回调会一直攒着 */ export declare function drainOrExit(stdin: NodeJS.WritableStream, child: NodeJS.EventEmitter): Promise; /** psql 默认格式的第一条错误:主消息 + DETAIL/HINT。不带 CONTEXT(COPY 出错时那里是整行数据) */ export declare function firstPsqlError(stderr: string): string; /** * 写过 COMMIT、却没看到 psql 确认时,用事务号问目标:提交了、回滚了,还是说不清。 * 还在进行中(原会话还没收尾)就等一会儿再问;等不到、连不上、事务号查不了,都是"说不清",不猜 */ export declare function transactionOutcome(connString: string, xid: string, opts?: { waitMs?: number; pollMs?: number; graceMs?: number; identity?: TargetIdentity; }): Promise<"committed" | "rolled_back" | "unknown">; export interface AuthRestoreRun { /** committed:快照里的东西都在目标上了;rolled_back:目标上什么都没留下;unknown:查不清 */ transaction: "committed" | "rolled_back" | "unknown"; /** 没提交(或查不清)的原因;提交后的步骤出错写在 afterCommit 里 */ failure?: string; xid?: string; afterCommit?: Awaited>; /** 补建了的触发器 */ triggers: string[]; } /** * 目标是哪个库:库的 OID,读得到时再加集群的 system identifier。事务号只在同一个集群里有意义, * 拿事务号问结果之前先核对:目标被换掉、连接改指了别处,就不能拿那边同号的事务当答案 */ export interface TargetIdentity { databaseOid: string; systemIdentifier: string | null; } export declare function targetIdentity(client: { query: (text: string) => Promise<{ rows: Array>; }>; }): Promise; /** 两个 Auth 表名在 tableKey 里的写法:指向它们的外键和备份里的外键一样,提交后再加 */ export declare const AUTH_TABLE_KEYS: string[]; export declare function restoreWithAuth(opts: { dumpPath: string; archive: AuthArchive; connString: string; auth: AuthSection; schemas: string[]; grants: GrantsToRestore; listDir: string; /** * manifest 记着的扩展:装在这个事务里(锁内重查之后),恢复失败时随事务一起回滚,重跑时目标是干净的。 * 调用方事先在一个回滚掉的事务里确认过它们装得上 */ extensions?: ExtensionInfo[]; /** 拿到事务号之后、写 COMMIT 之前调用:调用方据此记下"这次恢复对应哪个事务" */ onTransactionId?: (xid: string, identity: TargetIdentity) => Promise | void; /** 事务结果确定之后、提交后的步骤之前调用 */ onOutcome?: (transaction: AuthRestoreRun["transaction"]) => Promise | void; /** 提交后补完授权时调用 */ onGrantsApplied?: () => Promise | void; }): Promise; /** * 没提交(或查不清)时给用户的那句话。结果只由事务本身说了算(没写 COMMIT,或 pg_xact_status 的回答), * 不去数目标里有什么来推断:查不清就如实说查不清,并给出能查清的那条语句 */ export declare function authRestoreFailureMessage(run: AuthRestoreRun): string; /** * 恢复报告里关于 Auth 的说明(和 RECOVERY.md 同一套说法):哪些用户恢复后登录会受影响、哪些东西要手工补 */ export declare function authRestoreNotes(auth: AuthSection, schemas: string[]): { notes: string[]; manual: string[]; };