/** * OverlayService — drizzle-bound entry point for the catalog overlay store. * * Wraps the pure `resolveOverlay` logic (in `../overlay/resolver.ts`) with * the DB queries verticals actually need: fetch active overlays for an * entity, write a new overlay row, soft-delete an overlay, list by origin, * and the all-in-one `resolveEntityView` helper that fetches + resolves in * one call. * * Functions take an `AnyDrizzleDb` as their first parameter to match the * existing voyant convention (see `packages/products/src/service.ts`). Pure * resolver logic stays separate and remains unit-testable without a DB. * * See `docs/architecture/catalog-architecture.md` §5.2 for the design. */ import type { AnyDrizzleDb } from "@voyantjs/db"; import type { FieldPolicyRegistry, Visibility } from "../contract.js"; import { type OverlayLookup, type ResolvedView, type ResolverOverlay, type ResolverScope } from "../overlay/resolver.js"; import { OVERLAY_DEFAULT_SCOPE, type OverlayOrigin, type SelectCatalogOverlay } from "../overlay/schema.js"; /** * Fetch all active (not soft-deleted) overlays for an entity in one query. * The resolver expects this exact shape; downstream callers pass the result * straight into `resolveOverlay`. */ export declare function fetchOverlaysForEntity(db: AnyDrizzleDb, entityModule: string, entityId: string): Promise; /** * Batched form of `fetchOverlaysForEntity`: fetch all active overlays for * many entities of one module in a single query, grouped by entity id. * * Every requested id is present in the returned map (entities without * overlays map to an empty array), so callers can index without null * checks. Pass the per-entity array straight into * `resolveEntityViewWithOverlays` — the result is identical to calling * `resolveEntityView` once per entity, minus the N-1 round trips. */ export declare function fetchOverlaysForEntities(db: AnyDrizzleDb, entityModule: string, entityIds: ReadonlyArray): Promise>; /** * Resolve an entity's view in one call: fetch overlays, run the resolver, * return the merged view filtered by the actor's visibility. * * The caller supplies the source projection (typically gathered from the * vertical's own service layer) and the requesting scope. Verticals call * this in their `getEntity` / `listEntities` paths. */ export declare function resolveEntityView(db: AnyDrizzleDb, registry: FieldPolicyRegistry, entityModule: string, entityId: string, sourceProjection: ReadonlyMap, scope: ResolverScope): Promise; /** * Lower-level helper for callers that have already fetched overlays (e.g. * batch read-paths that pre-fetch overlays for many entities in one query). */ export declare function resolveEntityViewWithOverlays(registry: FieldPolicyRegistry, sourceProjection: ReadonlyMap, overlays: OverlayLookup, scope: ResolverScope): ResolvedView; /** * List overlay rows by their origin discriminator. Used by revert / re-sync * workflows ("show me everything Sanity wrote in the last week", "revert * all AI-generated overlays on this entity"). */ export interface OverlayOriginFilter { kind: OverlayOrigin["kind"]; /** Kind-specific narrowing — e.g. `provider: "sanity"` for `kind: "cms"`. */ match?: Partial; } export declare function listOverlaysByOrigin(db: AnyDrizzleDb, filter: OverlayOriginFilter, options?: { includeDeleted?: boolean; limit?: number; }): Promise; /** * Input for writing a single overlay row. Variant axes default to * `OVERLAY_DEFAULT_SCOPE`. */ export interface WriteOverlayInput { entity_module: string; entity_id: string; field_path: string; locale?: string; audience?: Visibility | typeof OVERLAY_DEFAULT_SCOPE; market?: string; value: unknown; origin: OverlayOrigin; } /** * Write or replace an overlay row for the given variant tuple. * * If a row already exists for `(entity_module, entity_id, field_path, * locale, audience, market)` and is not soft-deleted, this updates its * value, origin, and `updated_at`. The partial unique index on the active * rows guarantees idempotency. * * Last-write-wins is the default conflict-resolution policy (see * architecture §5.2.3); per-field canonical-writer config is deferred. * * Note: this function does not validate that the field policy permits an * overlay write (e.g. that `merge` is not `source-only` or that the actor's * `editRole` matches). Callers are responsible for policy validation; the * service-layer caller typically wraps this with a check against the * vertical's `FieldPolicyRegistry`. */ export declare function writeOverlay(db: AnyDrizzleDb, input: WriteOverlayInput): Promise; /** * Soft-delete an overlay row by setting `deleted_at`. The row is preserved * for retention / restore but no longer participates in resolver merges. */ export declare function softDeleteOverlay(db: AnyDrizzleDb, id: string): Promise; /** * Restore a soft-deleted overlay by clearing `deleted_at`. Used by source * reconnection (§5.10.5) when an entity comes back within the retention * window. */ export declare function restoreOverlay(db: AnyDrizzleDb, id: string): Promise; //# sourceMappingURL=overlay-service.d.ts.map