import type { ZodType } from "zod"; import type { BatchResult, FinishResult, Json, JsonObject, ReverseEtlContext, ReverseEtlStream, ReverseEtlWriter, WriteBatch, } from "./reverse-etl"; export interface ReverseIdentity { identity: Json; upsert: JsonObject; remove: JsonObject; } export type ReverseProjection = (action: "upsert" | "remove", row: unknown) => ReverseIdentity[]; export interface ReverseRuntimeRecovery { attachWriter(context: ReverseEtlContext): Promise>; reconcileBatch?( batch: WriteBatch, action: "upsert" | "remove", saved: BatchResult | undefined, context: ReverseEtlContext ): Promise; reconcileFinish?(saved: FinishResult | undefined, context: ReverseEtlContext): Promise; reconcileInit?(context: ReverseEtlContext): Promise<"absent" | "cleaned-up">; reconcileAbort?(context: ReverseEtlContext): Promise; } export interface ReverseRuntimeAdapter { insertOnly?: boolean; options?: JsonObject; stream: ReverseEtlStream; credentials: JsonObject; targetIdentity: string; project: ReverseProjection; mirror?: { stream: ReverseEtlStream; projection: { rowType: ZodType; project(row: JsonObject): ReverseIdentity[] }; batchDelivery: "accepted" | "asynchronous"; refreshAfterMs?: number; }; verifyMirrorBaseline?(signal: AbortSignal): Promise<"new-empty" | "tracked" | "replace">; recovery?(providerState: JsonObject): ReverseRuntimeRecovery; } export interface ReverseDestinationConfig { id: string; workspaceId: string; toId: string; destination: Record; model: { cursor?: unknown; deleteColumn?: unknown; primaryKey?: string[] }; options: { stream: string; mode: "upsert" | "mirror"; streamOptions: Record }; } /** Host-bound sync scope, not a provider-accessible database. Expected values are opaque JSON snapshots. */ export interface ScopedTargetState { read(): Promise; /** Creating initial state must atomically reject an existing delivery baseline. */ create(value: JsonObject): Promise; compareAndSet(expected: JsonObject, value: JsonObject): Promise; } export interface DestinationServices { /** Host stages/validates the source before a first target creation; never available in delivery context. */ validateSource?( validation: Pick, "stream" | "projection"> ): Promise; targetState?(key: string): ScopedTargetState; getAccessToken(signal: AbortSignal): Promise; fetch: typeof fetch; signal: AbortSignal; log(message: string): Promise; /** Deployment-owned defaults; never read process.env inside a provider adapter. */ developerToken?: string; }