/** * BidirectionalSync — Manages two-way sync between Figma and code. * * Tracks per-entity state (hash + timestamp + source), detects conflicts, * and drives sync in both directions through the bridge and registry. */ import { EventEmitter } from "events"; import type { MemoireEngine } from "./core.js"; import type { DesignSystem, DesignToken } from "./registry.js"; import { type TokenDiff, type SyncEntity, type SyncConflict } from "./token-differ.js"; export type SyncDirection = "figma-to-code" | "code-to-figma" | "bidirectional"; export interface SyncConfig { direction: SyncDirection; conflictWindowMs: number; autoResolve: "last-write-wins" | "figma-wins" | "code-wins" | "manual"; persistState: boolean; } export interface SyncState { figma: Map; code: Map; conflicts: SyncConflict[]; lastSyncAt: string | null; } export interface SyncResult { direction: SyncDirection; diff: TokenDiff; conflicts: SyncConflict[]; applied: number; skipped: number; pushed: number; elapsedMs: number; } export declare class BidirectionalSync extends EventEmitter { private engine; private config; private state; private syncing; private syncGuard; private stateDir; constructor(engine: MemoireEngine, config?: Partial); /** Load persisted sync state from disk. */ loadState(): Promise; /** Persist sync state to disk. */ saveState(): Promise; /** Enable sync guard — prevents echo loops during push operations. */ enableGuard(): void; /** Disable sync guard. */ disableGuard(): void; /** Check if sync guard is active (for orchestrator to check). */ get isGuarded(): boolean; /** Get current conflicts. */ getConflicts(): SyncConflict[]; /** Resolve a conflict by name. */ resolveConflict(name: string, resolution: "figma-wins" | "code-wins" | "manual"): boolean; /** * Run a full sync cycle: snapshot both sides, diff, detect conflicts, apply changes. */ sync(snapshot?: DesignSystem): Promise; /** * Handle a variable-changed event from Figma (granular update). */ onVariableChanged(data: { name: string; collection: string; values: Record; updatedAt: number; }): void; /** * Handle a code-side token change (from code-watcher or manual edit). */ onCodeTokenChanged(token: DesignToken): void; /** Build a minimal DesignSystem from tracked state for diffing. */ private buildDesignSystemFromState; /** Update entity tracking for one side. Prunes stale entries not in current DS. */ private updateEntityTracking; /** Get tokens that changed on the code side since last sync. */ private getCodeSideChanges; }