import type { H3Event } from 'h3'; export interface PageRow { id: number; route: string; route_key: string; title: string; description: string; markdown: string; headings: string; keywords: string; content_hash: string | null; updated_at: string; indexed_at: number; is_error: number; indexed: number; source: 'prerender' | 'runtime'; last_seen_at: number | null; indexnow_synced_at: number | null; locale: string | null; } export interface PageEntry { route: string; title: string; description: string; headings: Array>; keywords: string[]; updatedAt: string; isError: boolean; locale: string; } export interface PageData extends PageEntry { markdown: string; } export interface SearchResult { route: string; title: string; description: string; score: number; } export interface QueryPagesOptions { route?: string; includeMarkdown?: boolean; where?: { pending?: boolean; hasError?: boolean; source?: 'prerender' | 'runtime'; }; limit?: number; offset?: number; } /** * Get lastmod (updatedAt) for all indexed pages * Returns a Map for O(1) lookup when enriching sitemaps */ export declare function getPageLastmods(event: H3Event | undefined): Promise>; /** * Unified page query function * @param event - H3Event (optional, used for db context) * @param options - Query options */ export declare function queryPages(event?: H3Event, options?: QueryPagesOptions): Promise; export declare function queryPages(event: H3Event | undefined, options: QueryPagesOptions & { route: string; }): Promise; export declare function queryPages(event: H3Event | undefined, options: QueryPagesOptions & { route: string; includeMarkdown: true; }): Promise; export declare function queryPages(event: H3Event | undefined, options: QueryPagesOptions & { includeMarkdown: true; }): Promise; export interface StreamPagesOptions { batchSize?: number; } /** * Stream pages using cursor-based pagination * Yields pages one batch at a time to avoid loading all into memory */ export declare function streamPages(event?: H3Event, options?: StreamPagesOptions): AsyncGenerator; export interface CountPagesOptions { where?: { pending?: boolean; hasError?: boolean; source?: 'prerender' | 'runtime'; }; } /** * Count pages matching criteria */ export declare function countPages(event?: H3Event, options?: CountPagesOptions): Promise; export interface SearchPagesOptions { limit?: number; } /** * Full-text search using FTS5 * Note: FTS is only available at runtime, not during prerender */ export declare function searchPages(event: H3Event | undefined, query: string, options?: SearchPagesOptions): Promise; export interface UpsertPageInput { route: string; title: string; description: string; markdown: string; headings: string; keywords: string[]; contentHash?: string; updatedAt: string; isError?: boolean; source?: 'prerender' | 'runtime'; locale?: string; } /** * Insert or update a page */ export declare function upsertPage(event: H3Event | undefined, page: UpsertPageInput): Promise; /** * Check if a page is fresh (within TTL) */ export declare function isPageFresh(event: H3Event | undefined, route: string, ttlSeconds: number): Promise; /** * Get existing content hash for a page (for change detection) * @internal */ export declare function getPageHash(event: H3Event | undefined, route: string): Promise; /** * Seed routes from sitemap (insert with indexed=0 if not exists) */ export declare function seedRoutes(event: H3Event | undefined, routes: Array): Promise; /** * Get sitemap seeded timestamp from _ai_ready_info */ export declare function getSitemapSeededAt(event: H3Event | undefined): Promise; /** * Set sitemap seeded timestamp */ export declare function setSitemapSeededAt(event: H3Event | undefined, timestamp: number): Promise; /** * Prune routes not seen in sitemap for longer than threshold * Only prunes routes with source='runtime' (never prerendered pages) */ export declare function pruneStaleRoutes(event: H3Event | undefined, staleThresholdSeconds: number): Promise; /** * Get stale routes that would be pruned (for preview) */ export declare function getStaleRoutes(event: H3Event | undefined, staleThresholdSeconds: number): Promise; /** * Get pages needing IndexNow sync (content changed since last sync) */ export declare function getPagesNeedingIndexNowSync(event: H3Event | undefined, limit?: number): Promise<{ route: string; }[]>; /** * Count pages needing IndexNow sync */ export declare function countPagesNeedingIndexNowSync(event: H3Event | undefined): Promise; /** * Mark pages as synced to IndexNow */ export declare function markIndexNowSynced(event: H3Event | undefined, routes: string[]): Promise; /** * Update IndexNow stats after submission * Uses atomic SQL to handle concurrent updates safely */ export declare function updateIndexNowStats(event: H3Event | undefined, submitted: number, error?: string): Promise; /** * Batch update for IndexNow: mark pages synced + update stats * Runs all queries in parallel for speed */ export declare function batchIndexNowUpdate(event: H3Event | undefined, routes: string[], submitted: number): Promise; export interface IndexNowStats { totalSubmitted: number; lastSubmittedAt: number | null; lastError: string | null; } /** * Get IndexNow stats */ export declare function getIndexNowStats(event: H3Event | undefined): Promise; export interface IndexNowBackoffStatus { active: boolean; until: number | null; remainingMs: number | null; attempt: number | null; } /** * Get IndexNow backoff status for status endpoint */ export declare function getIndexNowBackoff(event: H3Event | undefined): Promise; export interface IndexNowLogEntry { id: number; submittedAt: number; urlCount: number; success: boolean; error: string | null; } /** * Log an IndexNow submission attempt (for debug mode) */ export declare function logIndexNowSubmission(event: H3Event | undefined, urlCount: number, success: boolean, error?: string): Promise; /** * Get recent IndexNow submission log entries */ export declare function getIndexNowLog(event: H3Event | undefined, limit?: number): Promise; export interface CronRunRow { id: number; started_at: number; finished_at: number | null; duration_ms: number | null; pages_indexed: number; pages_remaining: number; indexnow_submitted: number; indexnow_remaining: number; errors: string; status: 'running' | 'success' | 'partial' | 'error'; } export interface CronRun { id: number; startedAt: number; finishedAt: number | null; durationMs: number | null; pagesIndexed: number; pagesRemaining: number; indexNowSubmitted: number; indexNowRemaining: number; errors: string[]; status: 'running' | 'success' | 'partial' | 'error'; } /** * Start a cron run and return its ID */ export declare function startCronRun(event: H3Event | undefined): Promise; /** * Complete a cron run with results */ export declare function completeCronRun(event: H3Event | undefined, runId: number, result: { pagesIndexed: number; pagesRemaining: number; indexNowSubmitted: number; indexNowRemaining: number; errors: string[]; }): Promise; /** * Get recent cron runs */ export declare function getRecentCronRuns(event: H3Event | undefined, limit?: number): Promise; /** * Clean up old cron runs (keep last N) */ export declare function cleanupOldCronRuns(event: H3Event | undefined, keepCount?: number): Promise; /** * Clean up cron runs older than specified age */ export declare function pruneCronRunsByAge(event: H3Event | undefined, maxAgeMs?: number): Promise; export interface CronFastPathStatus { totalPages: number; pendingPages: number; indexNowPending: number; lastStaleCheck: number | null; buildId: string | null; indexNowBackoff: { until: number; attempt: number; } | null; sitemapsNeedCrawl: number; } /** * Get all cron status in a single query for fast-path checking * Reduces 6+ sequential DB calls to 1 */ export declare function getCronFastPathStatus(event: H3Event | undefined, sitemapIntervalMinutes?: number): Promise; /** * Try to acquire cron lock. Returns true if acquired, false if another run is active. * Uses atomic INSERT OR REPLACE with conditional check to prevent race conditions. */ export declare function tryAcquireCronLock(event: H3Event | undefined): Promise; /** * Release cron lock */ export declare function releaseCronLock(event: H3Event | undefined): Promise; export interface CronLockStatus { held: boolean; since: number | null; elapsedMs: number | null; stale: boolean; } /** * Get cron lock status for status endpoint */ export declare function getCronLockStatus(event: H3Event | undefined): Promise; export interface SitemapEntry { name: string; route: string; lastCrawledAt: number | null; urlCount: number; errorCount: number; lastError: string | null; } /** * Sync sitemap list from config to DB * Inserts new sitemaps, removes stale ones */ export declare function syncSitemaps(event: H3Event | undefined, sitemaps: Array<{ name: string; route: string; }>): Promise<{ added: number; removed: number; }>; /** * Get next sitemap to crawl * Prioritizes: sitemaps with errors (for retry), then oldest crawled * Skips sitemaps crawled within minIntervalMinutes (default 5 min) */ export declare function getNextSitemapToCrawl(event: H3Event | undefined, minIntervalMinutes?: number): Promise; /** * Get the last crawl timestamp for a single sitemap. Used to throttle runtime * re-seeding (the sitemap:resolved hook fires on every sitemap request). * Returns null when the sitemap row doesn't exist yet. */ export declare function getSitemapLastCrawledAt(event: H3Event | undefined, name: string): Promise; /** * Mark sitemap as successfully crawled */ export declare function markSitemapCrawled(event: H3Event | undefined, name: string, urlCount: number): Promise; /** * Mark sitemap crawl as failed */ export declare function markSitemapError(event: H3Event | undefined, name: string, error: string): Promise; /** * Reset all sitemap errors (called on build_id change) */ export declare function resetSitemapErrors(event: H3Event | undefined): Promise; /** * Get all sitemaps with their status */ export declare function getSitemapStatus(event: H3Event | undefined): Promise; export interface RecentPageActivity { route: string; title: string; indexedAt: number; } /** * Get recently indexed pages */ export declare function getRecentlyIndexedPages(event: H3Event | undefined, limit?: number): Promise; /** * Count pages indexed in a time window */ export declare function countRecentlyIndexed(event: H3Event | undefined, sinceMs: number): Promise;