import { FileResolutionResponse } from "./file-resolution.mjs"; import { AccountNextAction, AccountStatus, PartnerLifecycleAccount, PartnerLifecycleResponse, PartnerLifecycleSite } from "./onboarding.mjs"; type TableName = 'pages' | 'queries' | 'countries' | 'page_queries' | 'dates' | 'search_appearance' | 'search_appearance_pages' | 'search_appearance_queries' | 'search_appearance_page_queries' | 'hourly_pages'; /** * Temporal granularity axis. Daily callers (`'day'`, default) read/write rows * keyed by `date`; hourly callers (`'hour'`) read/write rows that additionally * carry a `hour` field. Composes with `searchType` — hourly is only meaningful * for Discover at the moment but the engine is generic. */ type Grain = 'day' | 'hour'; type Row = Record; type ColumnType = 'DATE' | 'VARCHAR' | 'INTEGER' | 'BIGINT' | 'DOUBLE'; interface ColumnDef { name: string; type: ColumnType; nullable: boolean; } interface TableSchema { name: TableName; columns: ColumnDef[]; sortKey: string[]; version: number; } interface TenantCtx { userId: string; siteId?: string; } type Dimension = 'page' | 'query' | 'queryCanonical' | 'country' | 'device' | 'date' | 'searchAppearance' | 'hour'; type Metric = 'clicks' | 'impressions' | 'ctr' | 'position'; type GscSearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews'; type Filter = unknown; interface BuilderStateWire { dimensions: Dimension[]; metrics?: Metric[]; filter?: Filter; orderBy?: { column: Metric | 'date'; dir: 'asc' | 'desc'; }; rowLimit?: number; startRow?: number; searchType?: GscSearchType; } interface GscApiRange { start: string; end: string; } interface CountryRow { country: string; clicks: number; impressions: number; sum_position: number; } interface CountriesResponse { rows: CountryRow[]; range: GscApiRange; generatedAt: string; source: 'gsc-api' | 'engine'; } interface SearchAppearanceRow { searchAppearance: string; clicks: number; impressions: number; sum_position: number; } interface SearchAppearanceResponse { rows: SearchAppearanceRow[]; range: GscApiRange; generatedAt: string; source: 'gsc-api' | 'engine'; } interface SiteListItem { id: string; label: string; hostname: string; propertyType: 'domain' | 'url-prefix'; readBackend?: 'd1' | 'r2'; } interface ScheduleState { nextAt: number; consecutiveUnchanged: number; policyVersion: number; } /** * Wire-format extension carried under `InspectionHistoryRecord.raw`. * * Source of truth: D1 `url_indexing_status` (per the 2026-05-19 redesign). * Most fields are JSON-encoded TEXT in D1 and surface here unchanged as * `string | null`; consumers parse on read. * * Additional keys are tolerated (`[key: string]: unknown`) for * forward-compatibility — new fields can ship without a contract bump. */ interface InspectionRecordRaw { /** Adaptive recheck schedule owned by `inspectionPolicy.observe`. */ schedule?: ScheduleState; /** Unix seconds. Mirrors the `next_check_after` column. */ nextCheckAfter?: number; /** Mirrors the `next_check_priority` column. */ priority?: 'high' | 'medium' | 'low'; /** JSON-encoded `string[]` of sitemap URLs containing this URL. */ sitemaps?: string | null; /** JSON-encoded `string[]` of referring URLs Google reported. */ referringUrls?: string | null; /** Crawler that fetched the URL (`Googlebot smartphone` etc.). */ crawlingUserAgent?: string | null; /** JSON-encoded mobile-usability issues. */ mobileIssues?: string | null; /** JSON-encoded rich-results items array. */ richResultsItems?: string | null; /** Deep link into the GSC URL Inspection tool. */ inspectionResultLink?: string | null; [key: string]: unknown; } interface InspectionHistoryRecord { url: string; inspectedAt: string; indexStatus?: string; lastCrawlTime?: string; googleCanonical?: string; userCanonical?: string; coverageState?: string; robotsTxtState?: string; indexingState?: string; pageFetchState?: string; mobileUsabilityVerdict?: string; richResultsVerdict?: string; raw?: InspectionRecordRaw; } interface InspectionHistoryResponse { url: string | null; records: InspectionHistoryRecord[]; } interface InspectionIndex { version: 1; records: Record; } interface RollupEnvelope { version: 1; id: string; builtAt: number; windowDays: number | null; payload: T; } interface GscRowQueryMeta { sourceName: string; sourceKind: 'row' | 'sql'; queryMs: number; } interface GscRowQueryResponse> { rows: T[]; meta: GscRowQueryMeta; } type IndexingUrlStatus = 'indexed' | 'not_indexed' | 'pending'; interface IndexingUrlRow { url: string; issueType?: string | null; verdict: string | null; coverageState: string | null; indexingState: string | null; robotsTxtState: string | null; pageFetchState: string | null; lastCrawlTime: string | null; crawlingUserAgent: string | null; userCanonical: string | null; googleCanonical: string | null; sitemaps: string[] | null; referringUrls: string[] | null; mobileVerdict: string | null; mobileIssues: unknown[] | null; richResultsVerdict: string | null; richResultsItems: unknown[] | null; inspectionResultLink: string | null; firstCheckedAt: string; lastCheckedAt: string; checkCount: number; } interface IndexingUrlsResponse { urls: IndexingUrlRow[]; pagination: { total: number; limit: number; offset: number; hasMore: boolean; }; meta: { siteUrl: string; status: string; issue: string | null; }; } type IndexingIssueSeverity = 'error' | 'warning' | 'info'; interface IndexingIssue { type: string; label: string; severity: IndexingIssueSeverity; count: number; description: string; fix: string; } interface IndexingDiagnostics { summary: { totalUrls: number; indexed: number; indexedPercent: number; }; issues: IndexingIssue[]; samples?: Record; meta: { siteUrl: string; indexingStatus?: 'pending' | 'partial' | 'complete'; indexingProgress?: number; sitemapTotal?: number; inspectedCount?: number; rollupBuiltAt?: number; }; } interface IndexingDiagnosticsParams { sampleIssues?: string[] | string; sampleLimit?: number; } interface IndexingInspectRequest { urls: string[]; } interface IndexingInspectResult { url: string; verdict: string | null; coverageState: string | null; indexingState: string | null; robotsTxtState: string | null; pageFetchState: string | null; lastCrawlTime: string | null; crawlingUserAgent: string | null; userCanonical: string | null; googleCanonical: string | null; sitemaps: string | null; referringUrls: string | null; mobileVerdict: string | null; mobileIssues: string | null; richResultsVerdict: string | null; richResultsItems: string | null; inspectionResultLink: string | null; } interface IndexingInspectRateLimit { reserved: number; remaining: number; limit: number; } interface IndexingInspectResponse { siteId: string; rateLimit: IndexingInspectRateLimit; results: IndexingInspectResult[]; errors: Array<{ url: string; error: string; }>; skipped: Array<{ url: string; reason: string; }>; } interface IndexingInspectRateLimited { error: 'rate_limited'; message: string; rateLimit: { reserved: 0; remaining: 0; limit: number; }; retryAfterSeconds: number; } interface SitemapAddedRow { url: string; sitemap: string; firstSeenAt: number; } interface SitemapRemovedRow { url: string; sitemap: string; removedAt: number; } type SitemapChangesCompleteness = { _tag: 'complete'; scannedUrls: number; } | { _tag: 'truncated'; scannedUrls: number; reasons: Array<'scan_limit' | 'added_limit' | 'removed_limit' | 'updated_limit' | 'history_unavailable'>; historyAvailableFrom?: number; limits: { scannedUrls: number; added: number; removed: number; updated: number; }; }; interface SitemapChangesResponse { added: SitemapAddedRow[]; removed: SitemapRemovedRow[]; summary: { totalAdded: number; totalRemoved: number; totalUpdated: number; period: { days: number; }; }; completeness: SitemapChangesCompleteness; } type AnalysisSourcesResponse = GscdumpAnalysisSourcesResponse; interface SourceInfoResponse { name: string; kind: 'row' | 'sql'; capabilities: { attachedTables?: boolean; [k: string]: unknown; }; supportedAnalyzerIds: string[]; browserAttachEligible: boolean; identityAttrs?: Record | null; } interface WhoamiResponse { userId?: string | null; plan?: string | null; attrs?: Record; } interface BackfillRange { startDate: string; endDate: string; } interface BackfillResponse { ok?: boolean; queued?: boolean; [key: string]: unknown; } type GscComparisonFilter = 'new' | 'lost' | 'improving' | 'declining'; interface GscdumpDataRow { page?: string; query?: string; queryCanonical?: string; country?: string; device?: string; date?: string; clicks: number; impressions: number; ctr: number; position: number; prevClicks?: number; prevImpressions?: number; prevCtr?: number; prevPosition?: number; topKeyword?: string; topPage?: string; variantCount?: number; variants?: Array<{ query: string; clicks: number; impressions: number; position: number; }>; difficulty?: number; searchVolume?: number; cpc?: number; firstDate?: string; lastDate?: string; } interface GscdumpMeta { siteUrl: string; syncStatus: string; newestDateSynced: string | null; oldestDateSynced: string | null; dataDelay?: string; dataEndDate?: string | null; warnings?: string[]; enrichment?: { lastEnriched: number; isDue: boolean; }; backfill?: { percent: number; daysRemaining?: number; }; } interface GscdumpTotals { clicks: number; impressions: number; ctr: number; position: number; } interface GscdumpDataResponse { rows: GscdumpDataRow[]; totalCount: number; totals: GscdumpTotals; meta: GscdumpMeta; } interface GscdumpDataDetailResponse { daily: Array<{ date: string; clicks: number; impressions: number; ctr: number; position: number; }>; previousDaily?: Array<{ date: string; clicks: number; impressions: number; ctr: number; position: number; }>; totals: GscdumpTotals; previousTotals?: GscdumpTotals; meta: GscdumpMeta; } interface GscdumpUserRegistration { userId: string; apiKey?: string; isNew?: boolean; status?: 'provisioning' | 'ready'; } interface GscdumpUserStatus { userId: string; status: 'provisioning' | 'ready' | 'reauth_required'; databaseReady?: boolean; needsReauth?: boolean; reauthRequired?: boolean; reauthReason?: string | null; authFailureCount?: number; nextAction?: 'reconnect_google' | 'none'; grantedScopes?: string | null; } interface GscdumpUserTokenUpdate { userId: string; updated: boolean; sites: GscdumpAvailableSite[]; } interface GscdumpAvailableSite { siteUrl: string; permissionLevel: string; registered: boolean; siteId?: string; /** Integer alias (`user_sites.int_id`) — the int JOIN key partners denormalize into their own catalog namespaces. Present on registered sites. */ intId?: number | null; syncStatus?: 'pending' | 'syncing' | 'synced' | 'error' | null; syncProgress?: { completed: number; failed?: number; total: number; percent: number; }; lastSyncAt?: number | null; newestDateSynced?: string | null; oldestDateSynced?: string | null; } interface GscdumpSiteIntIdCrosswalkEntry { siteId: string; intId: number; siteUrl: string; } interface GscdumpSiteIntIdCrosswalkResponse { crosswalk: Record; sites: GscdumpSiteIntIdCrosswalkEntry[]; } interface GscdumpSiteRegistration { siteId: string; /** Integer alias (`user_sites.int_id`) — the int JOIN key partners denormalize into their own catalog namespaces. */ intId?: number | null; /** Team-scoped catalog identifier (`user_sites.catalog_site_id`). Echoes caller input or defaults to `intId`. */ catalogSiteId?: number | null; status: 'idle' | 'pending' | 'syncing' | 'synced' | 'error'; message?: string; existing?: boolean; indexingEligible?: boolean; indexingIneligibleReason?: 'free_plan' | 'missing_gsc_read_scope' | 'insufficient_gsc_permission'; indexingPermissionLevel?: string | null; grantedScopes?: string[]; site?: PartnerLifecycleSite | null; } type GscVerificationMethod = 'META' | 'FILE' | 'DNS_TXT' | 'DNS_CNAME' | 'ANALYTICS' | 'TAG_MANAGER'; interface GscVerificationSite { type: 'SITE' | 'INET_DOMAIN'; identifier: string; } interface GscVerificationDnsRecord { type: 'TXT' | 'CNAME'; host: string; value: string; } interface GscVerificationRequest { userId?: string; siteUrl: string; method?: GscVerificationMethod; } interface GscVerificationTokenResponse { siteUrl: string; site: GscVerificationSite; method: GscVerificationMethod; token: string; metaContent: string | null; dnsRecord: GscVerificationDnsRecord | null; } interface GscAddAndVerifyResponse { siteUrl: string; site: GscVerificationSite; method: GscVerificationMethod; verified: true; owners: string[]; } interface GscdumpUserSite { siteId: string; siteUrl: string; analyticsSyncStatus?: 'idle' | 'pending' | 'syncing' | 'synced' | 'error'; analyticsSyncProgress?: { completed: number; failed?: number; total: number; percent: number; }; syncStatus: 'idle' | 'pending' | 'syncing' | 'synced' | 'error'; syncProgress?: { completed: number; failed?: number; total: number; percent: number; }; indexingEligible?: boolean; indexingIneligibleReason?: 'free_plan' | 'missing_gsc_read_scope' | 'insufficient_gsc_permission'; indexingPermissionLevel?: string | null; grantedScopes?: string[]; indexingStatus?: 'not_started' | 'indexing' | 'complete'; indexingProgress?: { completed: number; failed?: number; total: number; percent: number; }; indexingUrl?: string; lastSyncAt: number | null; newestDateSynced: string | null; oldestDateSynced: string | null; } interface GscdumpSyncStatusResponse { siteUrl: string; syncStatus: 'pending' | 'syncing' | 'synced' | 'error'; oldestDateAvailable: string | null; oldestDateSynced: string | null; newestDateSynced: string | null; lastSyncAt: number | null; lastError: string | null; jobs: { queued: number; processing: number; completed: number; failed: number; }; progress: number; jobProgress: number; daysSynced: number; daysAvailable: number; isSyncing: boolean; hasData: boolean; isComplete: boolean; tables: Record; days?: Record; }>; failedJobs?: Array<{ date: string; tableName: string; error: string; retryCount: number; }>; } interface GscdumpSitemap { path: string; errors: number; warnings: number; urlCount: number; isIndex: boolean; contentHash: string | null; lastDownloaded: string | null; lastError: string | null; isPending: boolean; fetchedAt: number; } interface GscdumpSitemapHistory { date: string; errors: number; warnings: number; urlCount: number; urlDelta: number; } interface GscdumpPerSitemapHistoryEntry { date: string; urlCount: number; changed: boolean; urlDelta: number; } interface GscdumpSitemapsResponse { sitemaps: GscdumpSitemap[]; history: GscdumpSitemapHistory[]; perSitemapHistory: Record; meta: { siteUrl: string; gscPropertyUrl?: string; syncStatus: string | null; sitemapScope: { excludedCount: number; duplicateCount: number; }; }; generation: GscdumpSitemapGeneration | null; } interface GscdumpSitemapChangesResponse { added: { url: string; sitemap: string; firstSeenAt: number; }[]; removed: { url: string; sitemap: string; removedAt: number; }[]; updated: { url: string; sitemap: string; previousLastmod: string | null; lastmod: string | null; observedAt: number; }[]; summary?: { totalAdded: number; totalRemoved: number; totalUpdated: number; period: { days: number; }; }; completeness: SitemapChangesCompleteness; generation: GscdumpSitemapGeneration | null; } interface GscdumpSitemapGeneration { id: string; observedAt: number; publishedAt: number; completeness: { _tag: 'complete'; }; membershipHistoryAvailableFrom: number | null; legacyImport: { _tag: 'none'; } | { _tag: 'metadata_only'; importedAt: number; recordCount: number; source: 'gsc_sitemaps'; }; } type PartnerSitemapAction = { action: 'submit' | 'delete'; sitemapUrl: string; } | { action: 'refresh' | 'auto-discover'; }; type PartnerSitemapActionResponse = { success: boolean; action: 'submitted' | 'deleted'; sitemapUrl: string; sitemapCount: number; } | { success: true; action: 'refreshed'; sitemapCount: number; changed: boolean; deltas?: unknown; } | { success: boolean; action: 'auto-discover'; discovered: string | null; submitError?: string | null; sitemapCount: number; }; interface GscdumpSitemapMembershipParams { urls: string[]; generationId?: string; } type GscdumpSitemapMembershipEvidence = { _tag: 'present'; url: string; feedpath: string; lastmod: string | null; firstSeenAt: number; lastSeenAt: number; } | { _tag: 'absent'; url: string; observedAt: number; } | { _tag: 'unknown'; url: string; reason: 'no_generation' | 'generation_not_found' | 'generation_incomplete' | 'history_pruned' | 'invalid_url'; }; interface GscdumpSitemapMembershipResponse { generation: GscdumpSitemapGeneration | null; evidence: GscdumpSitemapMembershipEvidence[]; meta: { requested: number; checked: number; matched: number; }; } interface GscdumpSitemapUrlsResponse { generation: GscdumpSitemapGeneration; items: Array<{ url: string; feedpath: string; lastmod: string | null; firstSeenAt: number; lastSeenAt: number; }>; page: { nextCursor: string | null; limit: number; }; } interface GscdumpSitemapExportResponse { generation: GscdumpSitemapGeneration; export: { _tag: 'url'; url: string; expiresAt: number; contentType: 'application/x-ndjson'; contentEncoding: 'identity' | 'gzip'; } | { _tag: 'unavailable'; reason: 'generation_not_found' | 'export_unavailable'; }; } interface GscdumpIndexingTrendPoint { date: string; totalUrls: number; indexedCount: number | null; notIndexedCount: number | null; errorCount: number | null; indexedPercent: number; issues: { blockedByRobots: number | null; noindexDetected: number | null; soft404: number | null; redirect: number | null; notFound: number | null; serverError: number | null; }; coverage: { submittedIndexed: number | null; crawledNotIndexed: number | null; discoveredNotCrawled: number | null; }; signals: { mobilePass: number; mobileFail: number; richResultsPass: number; richResultsFail: number; }; } interface GscdumpIndexingResponse { trend: GscdumpIndexingTrendPoint[]; summary: { totalUrls: number; indexed: number; notIndexed: number; pending: number; indexedPercent: number; oldestCheck: string | null; newestCheck: string | null; change7d: number | null; change28d: number | null; signals: { mobilePass: number; mobileFail: number; mobileUnspecified: number; richResultsPass: number; richResultsFail: number; richResultTypes: Array<{ type: string; count: number; }>; crawlingMobile: number; crawlingDesktop: number; }; }; meta: { siteUrl: string; syncStatus: string | null; indexingStatus: 'pending' | 'partial' | 'complete'; indexingProgress: number; sitemapTotal: number; inspectedCount: number; noSitemapsSubmitted: boolean; sitemapsPending: boolean; rollupBuiltAt?: number; }; } type GscdumpIndexingUrlStatus = 'indexed' | 'not_indexed' | 'pending'; type GscdumpIndexingIssueSeverity = 'error' | 'warning' | 'info'; type GscdumpCanonicalDifferenceKind = 'none' | 'formatting' | 'path' | 'cross_domain'; interface GscdumpRichResultItem { richResultType: string; items?: unknown[]; } interface GscdumpIndexingUrl { url: string; issueType?: string | null; verdict: string | null; coverageState: string | null; indexingState: string | null; robotsTxtState?: string | null; pageFetchState?: string | null; lastCrawlTime: string | null; crawlingUserAgent?: string | null; userCanonical?: string | null; googleCanonical?: string | null; canonicalMismatchKind: GscdumpCanonicalDifferenceKind; sitemaps?: string[] | null; referringUrls?: string[] | null; mobileVerdict?: string | null; mobileIssues?: string[] | null; richResultsVerdict?: string | null; richResultsItems?: GscdumpRichResultItem[] | null; inspectionResultLink?: string | null; firstCheckedAt: string; lastCheckedAt: string; checkCount?: number; } interface GscdumpIndexingUrlsResponse { urls: GscdumpIndexingUrl[]; pagination: { total: number; limit: number; offset: number; hasMore: boolean; }; meta: { siteUrl: string; gscPropertyUrl?: string; status: string; issue: string | null; }; } interface GscdumpIndexingDiagnosticsResponse { summary: { totalUrls: number; indexed: number; indexedPercent: number; }; issues: Array<{ type: string; label: string; severity: GscdumpIndexingIssueSeverity; count: number; description: string; fix: string; }>; samples?: Record; meta: { siteUrl: string; indexingStatus?: 'pending' | 'partial' | 'complete'; indexingProgress?: number; sitemapTotal?: number; inspectedCount?: number; rollupBuiltAt?: number; }; } type GscdumpIndexingInspectRequest = IndexingInspectRequest; type GscdumpIndexingInspectResult = IndexingInspectResult; type GscdumpIndexingInspectResponse = IndexingInspectResponse; type GscdumpIndexingInspectRateLimited = IndexingInspectRateLimited; type GscdumpAnalysisPreset = 'striking-distance' | 'opportunity' | 'decay' | 'zero-click' | 'non-brand' | 'brand-only' | 'movers-rising' | 'movers-declining'; interface GscdumpAnalysisParams { preset: GscdumpAnalysisPreset; startDate: string; endDate: string; prevStartDate?: string; prevEndDate?: string; brandTerms?: string; limit?: number; offset?: number; search?: string; minImpressions?: number; minPosition?: number; maxPosition?: number; maxCtr?: number; searchType?: GscSearchType; } interface GscdumpAnalysisResponse { preset: GscdumpAnalysisPreset; keywords: Array>; totalCount: number; summary?: Record | null; meta: { siteUrl: string; params: { brandTerms?: string[]; startDate?: string; endDate?: string; prevStartDate?: string; prevEndDate?: string; }; presetDescription?: string; }; } interface GscdumpAnalysisBundleParams extends Omit { presets: GscdumpAnalysisPreset[]; } interface GscdumpAnalysisBundleResponse { bundle: Record>; totalCount: number; summary?: Record | null; presetDescription: string; }>; meta: GscdumpAnalysisResponse['meta']; } interface RegisterPartnerUserParams { userGoogleId: string; userEmail: string; userName?: string; accessToken: string; refreshToken: string; tokenExpiresAt?: number; } interface UpdatePartnerUserTokensParams { accessToken: string; refreshToken: string; tokenExpiresAt?: number; } interface RegisterPartnerSiteParams { userId: string; siteUrl: string; requestedUrl?: string; gscPropertyUrl?: string; externalSiteId?: string; externalSiteUrl?: string; webhookUrl?: string; webhookEvents?: WebhookEventType[]; teamId?: string; enabledSearchTypes?: GscSearchType[]; catalogSiteId?: number; } interface BulkRegisterPartnerSitesParams { userId?: string; siteUrls?: string[]; sites?: Array<{ siteUrl?: string; requestedUrl?: string; gscPropertyUrl?: string; externalSiteId?: string; externalSiteUrl?: string; webhookUrl?: string; webhookEvents?: WebhookEventType[]; enabledSearchTypes?: GscSearchType[]; }>; } interface BulkRegisterPartnerSiteResult { siteUrl: string; siteId?: string; status: 'registered' | 'already_exists' | 'not_found' | 'error'; error?: string; site?: PartnerLifecycleSite | null; indexingEligible?: boolean; indexingIneligibleReason?: 'free_plan' | 'missing_gsc_read_scope' | 'insufficient_gsc_permission'; indexingPermissionLevel?: string | null; grantedScopes?: string[]; } interface BulkRegisterPartnerSitesResponse { results: BulkRegisterPartnerSiteResult[]; summary: { registered: number; alreadyExists: number; notFound: number; errors: number; }; } interface DeletePartnerUserResponse { ok: true; queued: true; userId: number; publicId: string; } type GscdumpAnalysisSourcesResponse = FileResolutionResponse; interface SearchTypeOptions { searchType?: GscSearchType; } interface SourceInfoOptions extends SearchTypeOptions { start?: string; end?: string; startDate?: string; endDate?: string; } interface AnalysisSourcesOptions extends SearchTypeOptions { tables?: string[] | string; start?: string; end?: string; startDate?: string; endDate?: string; /** Client-derived browser attachment byte ceiling. */ maxBytes?: number; /** Client-derived browser attachment row ceiling. */ maxRows?: number; /** Client-derived per-table parquet file-count ceiling. */ maxFiles?: number; } interface DataQueryOptions { comparison?: BuilderStateWire; filter?: GscComparisonFilter; searchType?: GscSearchType; } interface DataDetailOptions { comparison?: BuilderStateWire; searchType?: GscSearchType; } interface IndexingUrlsParams { limit?: number; offset?: number; status?: GscdumpIndexingUrlStatus; issue?: string; search?: string; /** * Pass `0`/`false` to skip the total COUNT(*) — a second full scan of the * joined url_indexing_status/sitemap_urls set. Sample callers that read only * `urls` (e.g. the assess page-issue collector) should opt out; paginated UI * reads that show an exact total leave it unset. */ count?: 0 | false; } interface GscdumpUserSettings { browserAnalyzerEnabled: boolean; } interface GscdumpPermissionRecovery { success: boolean; permissionLevel: string | null; jobsQueued: number; message: string; } interface GscdumpTopAssociationParams { type: 'topPage' | 'topKeyword'; identifier: string; startDate: string; endDate: string; } interface GscdumpTopAssociationResponse { value: string | null; } interface GscdumpKeywordSparklinesParams { keywords: string[]; startDate: string; endDate: string; searchType?: GscSearchType; } interface GscdumpKeywordSparklinesResponse { sparklines: Record; } interface GscdumpQueryTrendParams { startDate: string; endDate: string; prevStartDate?: string; prevEndDate?: string; searchType?: GscSearchType; } interface GscdumpQueryTrendResponse { daily: Array<{ date: string; queryCount: number; }>; total: number; previousTotal?: number; meta: { siteUrl: string; syncStatus: string | null; }; } interface GscdumpPageTrendParams { startDate: string; endDate: string; prevStartDate?: string; prevEndDate?: string; searchType?: GscSearchType; } interface GscdumpPageTrendResponse { daily: Array<{ date: string; pageCount: number; }>; total: number; previousTotal?: number; meta: { siteUrl: string; syncStatus: string | null; }; } interface GscdumpCanonicalMismatchRow { url: string; userCanonical: string; googleCanonical: string; verdict: string | null; coverageState: string | null; lastCrawlTime: string | null; lastCheckedAt: string | null; kind: Extract; } interface GscdumpCanonicalMismatchesResponse { mismatches: GscdumpCanonicalMismatchRow[]; totalCount: number; consolidationTargets: Array<{ google_canonical: string; count: number; }>; trend: Array<{ date: string; count: number; }>; meta: { siteUrl: string; syncStatus: string | null; }; } interface GscdumpIndexPercentTrendPoint { date: string; percent: number; total: number; visible: number; added: number | null; removed: number | null; } interface GscdumpInvisibleUrlRow { url: string; firstSeen?: string; lastmod: string | null; } interface GscdumpOrphanPageRow { url: string; impressions: number | null; clicks: number | null; } interface GscdumpIndexPercentSitemap { path: string; urlCount: number; isIndex: boolean; } interface GscdumpIndexPercentResponse { trend: GscdumpIndexPercentTrendPoint[]; invisibleUrls: GscdumpInvisibleUrlRow[]; invisibleCount: number; orphanPages: GscdumpOrphanPageRow[]; orphanCount: number; sitemaps: GscdumpIndexPercentSitemap[]; summary: { currentPercent: number; totalSitemapUrls: number; visibleUrls: number; change7d: number | null; change28d: number | null; dataDate: string; }; meta: { siteUrl: string; syncStatus: string | null; newestDateSynced: string | null; }; } interface GscdumpUserMeResponse { id: string; name?: string; email: string; picture?: string; setupComplete: boolean; databaseReady: boolean; plan: string; accountStatus: AccountStatus; accountNextAction: AccountNextAction; missingScopes: string[]; browserAnalyzerEnabled: boolean; stats: { activeSessions: number; totalApiCalls: number; lastUsed: number | null; } | null; } interface GscdumpHealthResponse { timestamp: number; jobs: { byStatus: Record; byQueue: Record; stuck: number; oldCompleted: number; }; failures: { lastHour: number; }; users: { needsReauth: number; }; throughput: { completedLastHour: number; }; totals: { users: number; sites: number; byPlan: Record; }; } interface GscdumpSyncProgressDateStatus { date: string; status: 'completed' | 'queued' | 'processing' | 'failed'; } interface GscdumpSyncProgressPhaseCounts { total: number; done: number; pending: number; stuck: number; failed: number; percent: number; rows: number; } interface GscdumpSyncProgressSite { id: string; userId: number; partnerId: string | null; siteUrl: string; syncStatus: string | null; lastError: string | null; createdAt: number; oldestDateSynced: string | null; newestDateSynced: string | null; oldestDateAvailable: string | null; userEmail: string | null; partnerName: string | null; needsReauth: boolean; authFailureCount: number; currentPhase: 'initial' | 'backfill' | 'complete'; isStalled: boolean; stallDays: number; needsContinuation: boolean; missingDays: number; initial: GscdumpSyncProgressPhaseCounts; backfill: GscdumpSyncProgressPhaseCounts & { processing: number; daysTarget: number; daysQueued: number; }; tables: Record; overallPercent: number; totalRows: number; dateStatuses: GscdumpSyncProgressDateStatus[]; } interface GscdumpSyncProgressResponse { summary: { total: number; inInitial: number; inBackfill: number; complete: number; stalled: number; authBlocked: number; totalRows: number; avgInitialPercent: number; avgBackfillPercent: number; }; sites: GscdumpSyncProgressSite[]; pagination: { total: number; limit: number; offset: number; hasMore: boolean; }; hasD1Stats: boolean; } type GscdumpSyncJobStatus = 'queued' | 'processing' | 'completed' | 'failed' | 'scheduled'; interface GscdumpSyncJobItem { id: number; userSiteId: string | null; tableName?: string; tableTier?: string; date?: string; priority?: string; status: GscdumpSyncJobStatus; siteUrl: string | null; userEmail?: string | null; rowsFetched: number | null; rowsInserted: number | null; error: string | null; retryCount: number; queuedAt: number; startedAt: number | null; completedAt: number | null; } interface GscdumpSyncJobsQueueCounts { queued: number; processing: number; } interface GscdumpSyncJobsResponse { jobs: GscdumpSyncJobItem[]; summary: { queued: number; processing: number; completed: number; failed: number; }; queues: Record; tiers?: { critical: GscdumpSyncJobsQueueCounts | undefined; standard: GscdumpSyncJobsQueueCounts | undefined; extended: GscdumpSyncJobsQueueCounts | undefined; }; } interface GscdumpSiteReportResponse { status: 'done' | 'error'; cached: boolean; result?: TResult; error?: string; } interface GscdumpTeamRow { id: string; ownerId: number; name: string; personalTeam: boolean; createdAt: number; updatedAt: number; } interface GscdumpTeamMemberRow { userId: number; publicId: string; name: string | null; email: string; picture: string | null; role: 'admin' | 'editor' | 'viewer'; joinedAt: number; } interface CreatePartnerTeamParams { ownerUserId: string; name: string; personalTeam?: boolean; } interface AddPartnerTeamMemberParams { userId: string; role: GscdumpTeamMemberRow['role']; } interface BindPartnerSiteTeamParams { teamId: string | null; } interface GscdumpTeamCatalogRef { teamId: string; catalogUri: string | null; warehouse: string | null; bucket: string | null; namespace: string | null; provisioningState: string | null; keyEncoding: string | null; catalogTablesReady: boolean; readsEnabled: boolean; } interface BindPartnerTeamCatalogParams { catalogUri: string; warehouse: string; namespace?: string; bucket?: string; } interface BindPartnerTeamCatalogResponse { teamId: string; status: 'ready'; catalogUri: string; warehouse: string; bucket: string; namespace: string; } type CanonicalWebhookEventType = 'user.lifecycle.changed' | 'site.lifecycle.changed' | 'site.analytics.ready' | 'site.indexing.ready' | 'site.auth.failed' | 'job.failed'; type WebhookEventType = CanonicalWebhookEventType; interface WebhookEnvelope = Record> { contractVersion: string; deliveryId: string; event: CanonicalWebhookEventType; partnerId: string; userId: string | null; siteId?: string; externalUserId?: string | null; externalSiteId?: string | null; lifecycleRevision: number; occurredAt: string; data: TData; } type PartnerWebhookData = Record; interface CreateWebhookEnvelopeOptions = Record> { event: CanonicalWebhookEventType; partnerId: string; userId: string | null; siteId?: string; externalUserId?: string | null; externalSiteId?: string | null; lifecycleRevision: number; data: TData; deliveryId?: string; occurredAt?: string | Date; contractVersion?: string; } interface PartnerWebhookHeaders { event?: string | null; delivery?: string | null; contractVersion?: string | null; timestamp?: string | null; signature?: string | null; } export { AddPartnerTeamMemberParams, AnalysisSourcesOptions, AnalysisSourcesResponse, BackfillRange, BackfillResponse, BindPartnerSiteTeamParams, BindPartnerTeamCatalogParams, BindPartnerTeamCatalogResponse, BuilderStateWire, BulkRegisterPartnerSiteResult, BulkRegisterPartnerSitesParams, BulkRegisterPartnerSitesResponse, CanonicalWebhookEventType, ColumnDef, ColumnType, CountriesResponse, CountryRow, CreatePartnerTeamParams, CreateWebhookEnvelopeOptions, DataDetailOptions, DataQueryOptions, DeletePartnerUserResponse, Dimension, Filter, Grain, GscAddAndVerifyResponse, GscApiRange, GscComparisonFilter, GscRowQueryMeta, GscRowQueryResponse, GscSearchType, GscVerificationDnsRecord, GscVerificationMethod, GscVerificationRequest, GscVerificationSite, GscVerificationTokenResponse, GscdumpAnalysisBundleParams, GscdumpAnalysisBundleResponse, GscdumpAnalysisParams, GscdumpAnalysisPreset, GscdumpAnalysisResponse, GscdumpAnalysisSourcesResponse, GscdumpAvailableSite, GscdumpCanonicalDifferenceKind, GscdumpCanonicalMismatchRow, GscdumpCanonicalMismatchesResponse, GscdumpDataDetailResponse, GscdumpDataResponse, GscdumpDataRow, GscdumpHealthResponse, GscdumpIndexPercentResponse, GscdumpIndexPercentSitemap, GscdumpIndexPercentTrendPoint, GscdumpIndexingDiagnosticsResponse, GscdumpIndexingInspectRateLimited, GscdumpIndexingInspectRequest, GscdumpIndexingInspectResponse, GscdumpIndexingInspectResult, GscdumpIndexingIssueSeverity, GscdumpIndexingResponse, GscdumpIndexingTrendPoint, GscdumpIndexingUrl, GscdumpIndexingUrlStatus, GscdumpIndexingUrlsResponse, GscdumpInvisibleUrlRow, GscdumpKeywordSparklinesParams, GscdumpKeywordSparklinesResponse, GscdumpMeta, GscdumpOrphanPageRow, GscdumpPageTrendParams, GscdumpPageTrendResponse, GscdumpPerSitemapHistoryEntry, GscdumpPermissionRecovery, GscdumpQueryTrendParams, GscdumpQueryTrendResponse, GscdumpRichResultItem, GscdumpSiteIntIdCrosswalkEntry, GscdumpSiteIntIdCrosswalkResponse, GscdumpSiteRegistration, GscdumpSiteReportResponse, GscdumpSitemap, GscdumpSitemapChangesResponse, GscdumpSitemapExportResponse, GscdumpSitemapGeneration, GscdumpSitemapHistory, GscdumpSitemapMembershipEvidence, GscdumpSitemapMembershipParams, GscdumpSitemapMembershipResponse, GscdumpSitemapUrlsResponse, GscdumpSitemapsResponse, GscdumpSyncJobItem, GscdumpSyncJobStatus, GscdumpSyncJobsQueueCounts, GscdumpSyncJobsResponse, GscdumpSyncProgressDateStatus, GscdumpSyncProgressPhaseCounts, GscdumpSyncProgressResponse, GscdumpSyncProgressSite, GscdumpSyncStatusResponse, GscdumpTeamCatalogRef, GscdumpTeamMemberRow, GscdumpTeamRow, GscdumpTopAssociationParams, GscdumpTopAssociationResponse, GscdumpTotals, GscdumpUserMeResponse, GscdumpUserRegistration, GscdumpUserSettings, GscdumpUserSite, GscdumpUserStatus, GscdumpUserTokenUpdate, IndexingDiagnostics, IndexingDiagnosticsParams, IndexingInspectRateLimit, IndexingInspectRateLimited, IndexingInspectRequest, IndexingInspectResponse, IndexingInspectResult, IndexingIssue, IndexingIssueSeverity, IndexingUrlRow, IndexingUrlStatus, IndexingUrlsParams, IndexingUrlsResponse, InspectionHistoryRecord, InspectionHistoryResponse, InspectionIndex, InspectionRecordRaw, Metric, type PartnerLifecycleAccount, type PartnerLifecycleResponse, type PartnerLifecycleSite, PartnerSitemapAction, PartnerSitemapActionResponse, PartnerWebhookData, PartnerWebhookHeaders, RegisterPartnerSiteParams, RegisterPartnerUserParams, RollupEnvelope, Row, ScheduleState, SearchAppearanceResponse, SearchAppearanceRow, SearchTypeOptions, SiteListItem, SitemapAddedRow, SitemapChangesCompleteness, SitemapChangesResponse, SitemapRemovedRow, SourceInfoOptions, SourceInfoResponse, TableName, TableSchema, TenantCtx, UpdatePartnerUserTokensParams, WebhookEnvelope, WebhookEventType, WhoamiResponse };