import { type TypedLexMap } from '@atproto/lex-data'; import { type AtUriString, type DidString, type NsidString } from '@atproto/lex-schema'; import type { DataPlaneClient } from '../data-plane/client/index.js'; import { type ExternalHydrationRoot, type ExternalHydrationWork, type HydrationXrpcEndpoint } from '../telemetry/events.js'; import { type SiteStandardDocumentRecord, type SiteStandardPublicationRecord } from '../views/types.js'; import type { Actors } from './actor.js'; import type { Posts } from './feed.js'; import type { Labels } from './label.js'; import { HydrationMap, type ItemRef, type RecordInfo } from './util.js'; /** Generic record bodies are decoded, but not validated against a Lexicon. */ export type ExternalRecord = RecordInfo; export type ExternalRecords = HydrationMap; /** Keyed by `genericRecordKey({ uri, cid })` to retain versions of a URI. */ export type ExternalRecordsByRef = HydrationMap; export type ExternalRecordBacklinks = HydrationMap; /** Viewer subscription outcomes per publication; null means unknown. */ export type ExternalPublicationSubscriptions = HydrationMap; export type AtmosphereActivityItem = { uri: AtUriString; sortedAt: Date; }; export type AtmosphereTimeline = { items: AtmosphereActivityItem[]; cursor?: string; }; export type AtmosphereBacklinks = { backlinks: AtmosphereActivityItem[]; cursor?: string; }; export type ExternalRecordBacklinkCounts = HydrationMap>>; export type AtmosphereBacklinksByActor = { backlinks: HydrationMap; truncated: boolean; }; declare const exactRecordKeySymbol: unique symbol; /** * A version-exact `${uri}@${cid}` key, only produced by `genericRecordKey` for * a ref with a CID, so it can be parsed back by `parseGenericRecordKey`. */ export type ExactRecordKey = string & { [exactRecordKeySymbol]: true; }; export type SiteStandardDocument = RecordInfo; export type SiteStandardPublication = RecordInfo; export type ExternalHydrationLevel = 'basic' | 'detailed'; /** * Options for external hydration traversals. `hydration` picks one level for * the whole traversal (default `'detailed'`): `'basic'` hydrates renderable * content, moderation and aggregate backlink counts; `'detailed'` also samples * social-preview backlinks and hydrates their records and participants. * `publicationSubscriptions` opts an authenticated viewer into request-cached * subscription discovery. The remaining fields are shared traversal state. */ export type ExternalHydrationOptions = { hydration?: ExternalHydrationLevel; seenRecordKeys?: Set; hydrationPass?: number; hydrationMetrics?: ExternalHydrationTracker; publicationSubscriptions?: ExternalPublicationSubscriptions; }; /** * Per-collection sample limits. Basic hydration skips social previews, * but keeps gallery items. Direct publication/photo references are singular. */ export declare const EXTERNAL_HYDRATION_LIMITS: { readonly "site.standard.document": { readonly recommendationPreviews: 3; }; readonly "site.standard.publication": { readonly subscriberPreviews: 3; }; readonly "social.grain.gallery": { readonly items: 10; readonly favoritePreviews: 3; }; }; /** Maximum in-flight backlink sample RPCs, not a dependency-count limit. */ export declare const MAX_CONCURRENT_BACKLINK_REQUESTS = 8; /** Maximum logical batches per traversal, counting the root as pass 1. */ export declare const MAX_EXTERNAL_HYDRATION_PASSES = 8; export declare class ExternalHydrator { dataplane: DataPlaneClient; /** * Entries per generic record RPC. The dataplane rejects larger URI lookups; * exact-ref lookups use the same bound defensively. */ static readonly MAX_RECORDS_PER_REQUEST = 100; /** * Target URIs per backlink-count RPC. The dataplane requires between 1 and * 100; this is a separate limit from `MAX_RECORDS_PER_REQUEST`. */ static readonly MAX_BACKLINK_COUNT_TARGETS_PER_REQUEST = 100; /** Target URIs per actor-backlink RPC, bounded by the dataplane. */ static readonly MAX_BACKLINK_ACTOR_TARGETS_PER_REQUEST = 100; constructor(dataplane: DataPlaneClient); /** * Fetch exact record versions; unavailable records are represented by null. * Large inputs are fetched in sequential bounded requests; any failed request * rejects the whole call. */ getRecordsByRef(refs: Required[], includeTakedowns?: boolean): Promise; /** * Fetch the latest indexed versions without collection-specific validation. * Large inputs are fetched in sequential bounded requests; any failed request * rejects the whole call. */ getRecordsByURI(uris: AtUriString[], includeTakedowns?: boolean): Promise; /** Fetch a page of activity refs for subsequent generic record hydration. */ getAtmosphereTimeline(viewerDid: DidString, opts?: { limit?: number; cursor?: string; }): Promise; /** * Fetch source-record counts, optionally restricted to one collection. Large * inputs are fetched in sequential bounded requests; any failed request * rejects the whole call. */ getAtmosphereBacklinkCounts(targetUris: AtUriString[], collection?: NsidString): Promise; /** Fetch a page of source records linking to a target. */ getAtmosphereBacklinks(targetUri: AtUriString, collection: NsidString, opts?: { limit?: number; cursor?: string; }): Promise; /** Fetch an actor's links per target, retaining the batch truncation flag. */ getAtmosphereBacklinksByActor(targetUris: AtUriString[], actorDid: DidString, collection: NsidString): Promise; } /** * Composes the lookup key for a ref: the bare URI for a latest-version lookup, * or `${uri}@${cid}` for an exact version. A single hydration batch can pull * several versions of one URI (different posts pinning different cids), so * exact maps need the composite for O(1) version-exact lookups. The two forms * never collide, so latest and exact lookups can share one traversal set. * * Throws on an empty CID rather than treating it as a latest lookup. */ export declare function genericRecordKey(ref: Required): ExactRecordKey; export declare function genericRecordKey(ref: ItemRef): string; /** * Recover the URI and CID from an exact record key, splitting at the last `@`. * Throws if either part is missing. Components are trusted, not revalidated. */ export declare function parseGenericRecordKey(key: ExactRecordKey): Required; /** * Null generic external records (in both the URI-keyed and exact-ref maps, * keeping their keys) that are taken down by an actionable label, unless * takedowns are included, or whose owner is explicitly unavailable. Applies to * each record independently; counts and other records are unaffected. */ export declare function actionExternalRecordTakedowns({ externalRecords, externalRecordsByRef, actors, labels, }: { externalRecords?: ExternalRecords; externalRecordsByRef?: ExternalRecordsByRef; actors?: Actors; labels?: Labels; }, includeTakedowns?: boolean): void; /** * Generic lookup work of one external hydration traversal, shared by reference * through its nested passes. `capped` records hitting the pass limit; `partial` * records a recovered best-effort dependency failure. */ export type ExternalHydrationTracker = ExternalHydrationWork & { capped: boolean; partial: boolean; /** * Internal: set by the traversal's first dependency discovery, whose refs * are its roots. */ rootsCounted: boolean; }; /** * Run `fn` with the caller's tracker, or as the owner of a new traversal when * there is none. Only the owner reports, once, including on failure, with the * context's XRPC endpoint (`'unknown'` if unset) and the traversal's wall time. A * returned traversal is `capped` if it hit the pass limit, else `partial` if * it recovered from a dependency failure. Owners that completed report when * they scheduled a batch or inspected roots (even prehydrated or unavailable * ones); only genuinely empty successful calls are not reported. Other * outcomes always are. */ export declare function trackExternalHydration(root: ExternalHydrationRoot, xrpcEndpoint: HydrationXrpcEndpoint | undefined, hydrationMetrics: ExternalHydrationTracker | undefined, fn: (hydrationMetrics: ExternalHydrationTracker) => Promise): Promise; export type AssociatedSiteStandardRecord = { ref: { uri: AtUriString; cid: string; }; info: T; }; /** * Select one pinned embed root. Legacy publication-first pairs may put their * document second; no other authored refs participate in hydration. */ export declare function getExternalRootRef(refs: readonly Required[] | undefined): Required | undefined; /** Select a pinned Standard.site root and its derived publication, if needed. */ export declare function getSiteStandardRecordsFromRefs(associatedRefs: readonly Required[] | undefined, records: ExternalRecordsByRef | undefined, dependencies?: ExternalRecords): { document: AssociatedSiteStandardRecord | undefined; publication: AssociatedSiteStandardRecord | undefined; }; /** Collect one root per post across all layers, deduped by exact ref. */ export declare const externalAssociatedRefsFromPosts: (...postLayers: Posts[]) => Required[]; export {}; //# sourceMappingURL=external.d.ts.map