/**
 * Invite database queries.
 *
 * CRUD operations for the invite table — creating invites,
 * finding unclaimed matches, claiming, and cleanup.
 *
 * @module
 */
import type { QueryDeps } from '../db/query_deps.js';
import type { Invite, CreateInviteInput, InviteWithUsernamesJson } from './invite_schema.js';
/**
 * Create a new invite.
 *
 * @param deps - query dependencies
 * @param input - the invite fields
 * @returns the created invite
 * @mutates `invite` table - inserts the new row
 */
export declare const query_create_invite: (deps: QueryDeps, input: CreateInviteInput) => Promise<Invite>;
/**
 * Find an unclaimed invite by email (case-insensitive).
 */
export declare const query_invite_find_unclaimed_by_email: (deps: QueryDeps, email: string) => Promise<Invite | undefined>;
/**
 * Find an unclaimed invite by username (case-insensitive).
 */
export declare const query_invite_find_unclaimed_by_username: (deps: QueryDeps, username: string) => Promise<Invite | undefined>;
/**
 * Find an unclaimed invite matching email and/or username, taking a
 * row-level write lock on the matched row.
 *
 * Three scoping modes:
 *
 * - **Email-only invite** (email set, username NULL) → matches only if signup provides matching email.
 * - **Username-only invite** (username set, email NULL) → matches only if signup provides matching username.
 * - **Both-field invite** (both set) → requires BOTH email and username to match.
 *
 * Must run inside the same transaction as `query_invite_claim_unscoped`:
 * `FOR UPDATE` makes find + claim atomic, so a concurrent signup that
 * matched the same invite blocks on the lock until this transaction
 * commits/rolls back. After commit, the loser's `find_for_update`
 * returns no row (the winner flipped `claimed_at`) and falls through to
 * `ERROR_NO_MATCHING_INVITE` — no race window between find and claim.
 *
 * @param deps - query dependencies — `deps.db` MUST be a transaction
 * @param email - email to match (or null if signup provides none)
 * @param username - username to match
 * @returns the matching invite (locked), or `undefined`
 */
export declare const query_invite_find_unclaimed_match_for_update: (deps: QueryDeps, email: string | null, username: string) => Promise<Invite | undefined>;
/**
 * Claim an invite by setting the claimed_by and claimed_at fields.
 *
 * The `_unscoped` suffix is the safety signal — the SQL only checks the
 * row state (`claimed_at IS NULL`), not whether the claiming account's
 * email or username matches the invite. Callers must scope the lookup
 * upstream via one of the `_find_unclaimed_match*` siblings (production
 * uses `_for_update` to make find + claim atomic). Skipping the find
 * step lets a caller claim any unclaimed invite by id.
 *
 * Mirrors the `query_session_revoke_by_hash_unscoped` precedent — there
 * is no scoped sibling because the scoping is provided by a separate
 * find query, not by an alternate variant of this query.
 *
 * @param deps - query dependencies
 * @param invite_id - the invite to claim
 * @param account_id - the account claiming the invite
 * @returns true if the invite was claimed, false if already claimed or not found
 * @mutates `invite` row - sets `claimed_by` and `claimed_at` when still unclaimed
 */
export declare const query_invite_claim_unscoped: (deps: QueryDeps, invite_id: string, account_id: string) => Promise<boolean>;
/**
 * List all invites, newest first.
 */
export declare const query_invite_list_all: (deps: QueryDeps) => Promise<Array<Invite>>;
/**
 * List all invites with resolved creator/claimer usernames, newest first.
 *
 * @param deps - query dependencies
 * @returns invites with `created_by_username` and `claimed_by_username`
 */
export declare const query_invite_list_all_with_usernames: (deps: QueryDeps) => Promise<Array<InviteWithUsernamesJson>>;
/**
 * Delete an unclaimed invite.
 *
 * @param deps - query dependencies
 * @param id - the invite id
 * @returns true if deleted, false if not found or already claimed
 * @mutates `invite` table - deletes the row when still unclaimed
 */
export declare const query_invite_delete_unclaimed: (deps: QueryDeps, id: string) => Promise<boolean>;
//# sourceMappingURL=invite_queries.d.ts.map