//#region src/server/types.d.ts
/**
* Server-side types for the Yjs Durable Streams Protocol.
*
* These types define the wire format and internal structures used by the
* Yjs server layer that sits between clients and the durable streams server.
*/
/**
* Configuration options for the Yjs server.
*/
interface YjsServerOptions {
  /** Port to listen on (0 for random available port) */
  port?: number;
  /** Host to bind to */
  host?: string;
  /** URL of the underlying durable streams server */
  dsServerUrl: string;
  /**
  * Threshold in bytes for triggering compaction.
  * When cumulative update size exceeds this, a new snapshot is created.
  * @default 1048576 (1MB)
  */
  compactionThreshold?: number;
  /**
  * Optional headers to send to the durable streams server.
  */
  dsServerHeaders?: Record<string, string>;
}
/**
* Internal state for tracking document metadata.
*/
interface YjsDocumentState {
  /**
  * Current snapshot offset, or null if no snapshot exists yet.
  * When set, the snapshot is available at ?offset={snapshotOffset}_snapshot
  */
  snapshotOffset: string | null;
  /** Cumulative size of updates since last compaction (bytes) */
  updatesSizeBytes: number;
  /** Whether compaction is currently in progress */
  compacting: boolean;
}
/**
* Result from a compaction operation.
*/
interface CompactionResult {
  /** The offset at which the snapshot was taken */
  snapshotOffset: string;
  /** Size of the new snapshot in bytes */
  snapshotSizeBytes: number;
  /** Previous snapshot offset (to be deleted), or null if first compaction */
  oldSnapshotOffset: string | null;
}
/**
* Index entry stored in the internal index stream.
* Each compaction appends a new entry with the current snapshot offset.
*/
interface YjsIndexEntry extends Record<string, unknown> {
  /** The snapshot offset (used to construct the snapshot key) */
  snapshotOffset: string;
  /** Timestamp when the snapshot was created */
  createdAt: number;
}
/**
* Internal representation of a Yjs document on the server.
*/
interface YjsDocument {
  /** Service identifier */
  service: string;
  /** Document path (can include forward slashes) */
  docPath: string;
  /** Current document state */
  state: YjsDocumentState;
}
/**
* Headers used by the Yjs protocol layer (lowercase per protocol spec).
*/
declare const YJS_HEADERS: {
  /** Content offset for the next read */
  readonly STREAM_NEXT_OFFSET: "stream-next-offset";
  /** Whether the client is caught up */
  readonly STREAM_UP_TO_DATE: "stream-up-to-date";
  /** Cursor for CDN collapsing */
  readonly STREAM_CURSOR: "stream-cursor";
};
/**
* Stream path builders for consistent path generation.
* All operations use the same document URL with query parameters.
*
* Internal streams use `.` prefixed segments (e.g., `.updates`, `.index`, `.snapshots`)
* which are safe from user collisions since document paths reject `.` characters.
*/
declare const YjsStreamPaths: {
  /**
  * Get the base path for a document.
  * docPath can include forward slashes (e.g., "project/chapter-1").
  */
  readonly doc: (service: string, docPath: string) => string;
  /**
  * Get the underlying DS stream path for document updates.
  * Uses `.updates` suffix to avoid collisions with user document paths.
  */
  readonly dsStream: (service: string, docPath: string) => string;
  /**
  * Get the internal index stream path for a document.
  * This stream stores snapshot offsets and is used internally by the server.
  * Uses `.index` suffix to avoid collisions with user document paths.
  */
  readonly indexStream: (service: string, docPath: string) => string;
  /**
  * Get the snapshot stream path for a given offset.
  * Uses `.snapshots` prefix to avoid collisions with user document paths.
  */
  readonly snapshotStream: (service: string, docPath: string, snapshotKey: string) => string;
  /**
  * Get the awareness stream path for a given name.
  * Uses `.awareness` prefix to avoid collisions with user document paths.
  */
  readonly awarenessStream: (service: string, docPath: string, name: string) => string;
  /**
  * Get the awareness index stream path for a document.
  * This append-only stream tracks which named awareness streams have been created,
  * enabling discovery during cascade delete.
  */
  readonly awarenessIndexStream: (service: string, docPath: string) => string;
  /**
  * Get the snapshot storage key for a given offset.
  */
  readonly snapshotKey: (offset: string) => string;
  /**
  * Parse a snapshot offset from a snapshot key (e.g., "4782_snapshot" -> "4782").
  * Returns null if not a valid snapshot key.
  */
  readonly parseSnapshotOffset: (key: string) => string | null;
}; //#endregion
//#region src/server/yjs-server.d.ts

/**
* Error codes for Yjs protocol errors.
*/
/**
* HTTP server implementing the Yjs Durable Streams Protocol.
*/
declare class YjsServer {
  private readonly dsServerUrl;
  private readonly dsServerHeaders;
  private readonly compactionThreshold;
  private readonly port;
  private readonly host;
  private readonly compactor;
  private readonly documentStates;
  private stateKey;
  private server;
  private _url;
  constructor(options: YjsServerOptions);
  start(): Promise<string>;
  stop(): Promise<void>;
  get url(): string;
  private handleRequest;
  /**
  * Proxy requests that don't match Yjs routes to the underlying DS server.
  * This allows clients to use a single endpoint for both Yjs and raw DS operations.
  */
  private proxyToDsServer;
  /**
  * POST with auto-create on 404: try POST, if stream doesn't exist
  * create it via PUT and retry. Handles awareness streams that may
  * have expired due to TTL.
  */
  private postWithAutoCreate;
  private handleSnapshotDiscovery;
  /**
  * Load the latest snapshot offset from the internal index stream.
  * Returns null if no index exists or it's empty.
  */
  private loadSnapshotOffsetFromIndex;
  private handleSnapshotRead;
  /**
  * Increment an offset string for the next read position.
  * Offsets are formatted as "{timestamp}_{sequence}" padded strings.
  * Increments the sequence portion by 1 so the client reads from the
  * position after the snapshot, not from the snapshot offset itself.
  */
  private incrementOffset;
  /**
  * GET - Proxy to read from .updates stream.
  */
  private handleUpdatesRead;
  /**
  * HEAD - Proxy to check .updates stream existence.
  */
  private handleDocumentHead;
  /**
  * PUT - Create document: creates both .updates and .awareness.default streams.
  */
  private handleDocumentCreate;
  /**
  * POST - Streaming proxy to write to .updates stream.
  * Client sends lib0-framed updates; we pass through directly.
  * Returns 404 if the document does not exist.
  */
  private handleUpdateWrite;
  /**
  * DELETE - Delete document and cascade to associated streams.
  */
  private handleDocumentDelete;
  /**
  * Best-effort cascade delete of snapshot and awareness streams.
  * Errors are logged but do not propagate.
  */
  private cascadeDeleteStreams;
  /**
  * Load entries from an index stream, extracting a value from each entry.
  * Returns deduplicated values. Returns empty array if index doesn't exist.
  */
  private loadIndexEntries;
  private handleAwareness;
  /**
  * Forward a fetch Response to the client ServerResponse.
  */
  private forwardResponse;
  /**
  * Proxy with SSE-specific handling: flush after each chunk for immediate delivery.
  */
  private proxyWithSseFlush;
  /**
  * Try to create a stream at the given DS path.
  * Returns true if the stream was created, false if it already existed.
  */
  private tryCreateStream;
  /**
  * Append a JSON entry to an index stream, creating the stream if needed.
  */
  appendToIndexStream(dsPath: string, entry: Record<string, unknown>): Promise<void>;
  private getOrCreateDocumentState;
  shouldTriggerCompaction(state: YjsDocumentState): boolean;
  getDocumentState(service: string, docPath: string): YjsDocumentState | undefined;
  /**
  * Atomically check if compaction can start and set compacting=true if so.
  * Returns true if compaction was started, false if already compacting or state not found.
  */
  tryStartCompaction(service: string, docPath: string): boolean;
  setCompacting(service: string, docPath: string, compacting: boolean): void;
  resetUpdateCounters(service: string, docPath: string): void;
  updateSnapshotOffset(service: string, docPath: string, offset: string): void;
  getDsServerUrl(): string;
  getDsServerHeaders(): Record<string, string>;
  private readBody;
} //#endregion
//#region src/server/compaction.d.ts
/**
* Interface for the server that the Compactor works with.
*/
interface CompactorServer {
  getDsServerUrl: () => string;
  getDsServerHeaders: () => Record<string, string>;
  getDocumentState: (service: string, docPath: string) => YjsDocumentState | undefined;
  /** Atomically check if compaction can start and set compacting=true if so */
  tryStartCompaction: (service: string, docPath: string) => boolean;
  setCompacting: (service: string, docPath: string, compacting: boolean) => void;
  resetUpdateCounters: (service: string, docPath: string) => void;
  updateSnapshotOffset: (service: string, docPath: string, offset: string) => void;
  /** Append a JSON entry to an index stream, creating the stream if needed */
  appendToIndexStream: (dsPath: string, entry: Record<string, unknown>) => Promise<void>;
}
/**
* Handles document compaction.
*/
declare class Compactor {
  private readonly server;
  constructor(server: CompactorServer);
  /**
  * Trigger compaction for a document.
  * Uses atomic check-and-set to prevent concurrent compactions.
  */
  triggerCompaction(service: string, docPath: string): Promise<void>;
  /**
  * Perform the actual compaction.
  */
  private performCompaction;
  /**
  * Write a new entry to the internal index stream.
  * This persists the snapshot offset so it survives server restarts.
  */
  private writeIndexEntry;
  /**
  * Delete old snapshot.
  */
  private deleteOldSnapshot;
}

//#endregion
/**
* Frame a Yjs update with lib0 encoding for storage.
*/

export { CompactionResult, Compactor, YJS_HEADERS, YjsDocument, YjsDocumentState, YjsIndexEntry, YjsServer, YjsServerOptions, YjsStreamPaths };