/**
 * Runtime support for the `relationship` field type.
 *
 * Two responsibilities:
 *
 *   1. **Validation** — confirm the IDs a caller writes actually point at
 *      live (non-deleted) documents in the declared target collection(s).
 *      Without this an integrator can accidentally store stale or fabricated
 *      IDs and the bug surfaces only on render.
 *
 *   2. **Population (depth=1)** — opt-in expansion of stored IDs into full
 *      reference summaries (`{ id, title, slug, status, collection }`) so
 *      frontend consumers don't need to round-trip per relation.
 *
 * Both helpers walk the field schema, support `hasMany`, and tolerate the
 * `relationTo: string | string[]` polymorphism that `RelationshipField`
 * permits. We deliberately cap the population depth at 1 — recursive
 * expansion would let a single read pull half the database when authors,
 * related posts, and case studies all link to one another.
 */
import type { FieldDefinition } from '../config/types.js';
export interface RelationLookup {
    /**
     * Fetch documents by id, returning a map keyed by id. Implementations
     * should filter by `deletedAt: null` and restrict to the requested
     * collection(s). Missing ids are simply omitted from the returned map.
     */
    fetchByIds: (collections: string[], ids: string[]) => Promise<Map<string, RelationSummary>>;
}
export interface RelationSummary {
    id: string;
    collection: string;
    title?: string | null;
    slug?: string | null;
    status?: string | null;
    /** Whatever subset of the document data the lookup wants to expose. */
    data?: Record<string, unknown> | null;
}
/**
 * Walk a field schema and collect every relation reference present in the
 * document data. Returns `{ collection -> Set<id> }` and an inventory of
 * which field paths hold which ids — used by both validation and populate.
 */
export declare function collectRelationRefs(fields: Record<string, FieldDefinition>, data: Record<string, unknown>): {
    byCollection: Map<string, Set<string>>;
    refsByPath: Array<{
        path: string;
        field: FieldDefinition;
        ids: string[];
    }>;
};
/**
 * Validate that every relation reference in `data` points at a live
 * document. Throws on the first broken reference with a precise error
 * (path + missing id + target collection) so admins can fix the input
 * instead of guessing.
 */
export declare function validateRelations(fields: Record<string, FieldDefinition>, data: Record<string, unknown>, lookup: RelationLookup): Promise<void>;
export interface PopulateOptions {
    /**
     * Whitelist of field paths to populate. `['*']` expands all relations.
     * Otherwise: top-level field names (matches the most common case where
     * a frontend only wants e.g. `author` populated, not every reference).
     *
     * Nested paths (e.g. `relatedPosts.author`) are intentionally not
     * supported — depth=1 only.
     */
    paths?: string[] | '*';
}
/**
 * Replace stored IDs with `{ id, title, slug, status, collection }` summaries
 * for every relation field in the document. The original IDs remain
 * accessible via the summary's `id` field, so callers that wrote raw IDs
 * still see them after a populated read.
 *
 * Returns a *new* document object; the input is not mutated.
 */
export declare function populateRelations(fields: Record<string, FieldDefinition>, data: Record<string, unknown>, lookup: RelationLookup, options?: PopulateOptions): Promise<Record<string, unknown>>;
/**
 * Parse the `?populate=` query param into an options object.
 *   - `?populate=*`          → expand all relations
 *   - `?populate=true`       → expand all relations (alias)
 *   - `?populate=a,b`        → expand only `a` and `b`
 *   - missing / `false`      → no expansion
 */
export declare function parsePopulateParam(raw: string | null | undefined): PopulateOptions | null;
//# sourceMappingURL=relations.d.ts.map