import { DurableObject } from "cloudflare:workers";

//#region src/types.d.ts
type ImmutablePrimitive = undefined | null | boolean | string | number;
type Immutable<T> = T extends ImmutablePrimitive
  ? T
  : T extends Array<infer U>
    ? ImmutableArray<U>
    : T extends Map<infer K, infer V>
      ? ImmutableMap<K, V>
      : T extends Set<infer M>
        ? ImmutableSet<M>
        : ImmutableObject<T>;
type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
type ConnectionState<T> = ImmutableObject<T> | null;
type ConnectionSetStateFn<T> = (prevState: ConnectionState<T>) => T;
type ConnectionContext = {
  request: Request;
};
/** A WebSocket connected to the Server */
type Connection<TState = unknown> = WebSocket & {
  /** Connection identifier */ id: string;
  /**
   * The URL of the original WebSocket upgrade request.
   * Persisted in the WebSocket attachment so it survives hibernation.
   */
  uri: string | null;
  /**
   * Arbitrary state associated with this connection.
   * Read-only — use {@link Connection.setState} to update.
   *
   * This property is configurable, meaning it can be redefined via
   * `Object.defineProperty` by downstream consumers (e.g. the Cloudflare
   * Agents SDK) to namespace or wrap internal state storage.
   */
  state: ConnectionState<TState>;
  /**
   * Update the state associated with this connection.
   *
   * Accepts either a new state value or an updater function that receives
   * the previous state and returns the next state.
   *
   * This property is configurable, meaning it can be redefined via
   * `Object.defineProperty` by downstream consumers. If you redefine
   * `state` and `setState`, you are responsible for calling
   * `serializeAttachment` / `deserializeAttachment` yourself if you need
   * the state to survive hibernation.
   */
  setState(
    state: TState | ConnectionSetStateFn<TState> | null
  ): ConnectionState<TState>;
  /**
   * @deprecated use {@link Connection.setState} instead.
   *
   * Low-level method to persist data in the connection's attachment storage.
   * This property is configurable and can be redefined by downstream
   * consumers that need to wrap or namespace the underlying storage.
   */
  serializeAttachment<T = unknown>(attachment: T): void;
  /**
   * @deprecated use {@link Connection.state} instead.
   *
   * Low-level method to read data from the connection's attachment storage.
   * This property is configurable and can be redefined by downstream
   * consumers that need to wrap or namespace the underlying storage.
   */
  deserializeAttachment<T = unknown>(): T | null;
  /**
   * Tags assigned to this connection via {@link Server.getConnectionTags}.
   * Always includes the connection id as the first tag.
   */
  tags: readonly string[];
  /**
   * @deprecated Use `this.name` on the Server instead.
   * The server name. Populated from `Server.name` after initialization.
   */
  server: string;
};
//#endregion
//#region src/index.d.ts
type WSMessage = ArrayBuffer | ArrayBufferView | string;
interface RoutingRetryEvent {
  error: unknown;
  attempt: number;
  maxAttempts: number;
  delayMs: number;
  name: string;
  className?: string;
}
interface RoutingRetryOptions {
  /** Max number of attempts, including the first. Default: 3 */
  maxAttempts?: number;
  /** Base delay in ms for exponential backoff. Default: 100 */
  baseDelayMs?: number;
  /** Max delay cap in ms. Default: 800 */
  maxDelayMs?: number;
  /** Optional callback invoked before each retry delay. */
  onRetry?: (event: RoutingRetryEvent) => void | Promise<void>;
}
/**
 * For a given server namespace, create a server with a name.
 *
 * Makes an RPC that awaits the DO's `onStart()` before returning, so callers
 * can invoke user-defined RPC methods on the returned stub and trust that
 * `onStart()` has completed. (User-defined RPC methods don't
 * otherwise pass through `Server.fetch()`, which is where initialization
 * would normally be triggered.)
 *
 * `this.name` inside the DO is always populated from `ctx.id.name`, so
 * the RPC no longer needs to carry the name for bookkeeping; it exists
 * purely to synchronize `onStart()` and to deliver `props`.
 */
declare function getServerByName<
  Env extends Cloudflare.Env = Cloudflare.Env,
  T extends Server<Env> = Server<Env>,
  Props extends Record<string, unknown> = Record<string, unknown>
>(
  serverNamespace: DurableObjectNamespace<T>,
  name: string,
  options?: {
    jurisdiction?: DurableObjectJurisdiction;
    locationHint?: DurableObjectLocationHint;
    props?: Props;
    routingRetry?: false | RoutingRetryOptions;
  }
): Promise<DurableObjectStub<T>>;
interface Lobby<Env = Cloudflare.Env> {
  /**
   * The kebab-case namespace from the URL path (e.g. `"my-agent"`).
   * @deprecated Use `className` instead, which returns the Durable Object class name.
   * In the next major version, `party` will return the class name instead of the kebab-case namespace.
   */
  party: string;
  /** The Durable Object class name / env binding name (e.g. `"MyAgent"`). */
  className: Extract<keyof Env, string>;
  /** The room / instance name extracted from the URL. */
  name: string;
}
interface PartyServerOptions<
  Env = Cloudflare.Env,
  Props = Record<string, unknown>
> {
  prefix?: string;
  jurisdiction?: DurableObjectJurisdiction;
  locationHint?: DurableObjectLocationHint;
  props?: Props;
  /**
   * Whether to enable CORS for matched routes.
   *
   * When `true`, uses default permissive CORS headers:
   * - Access-Control-Allow-Origin: *
   * - Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS
   * - Access-Control-Allow-Headers: *
   * - Access-Control-Max-Age: 86400
   *
   * For credentialed requests, pass explicit headers with a specific origin:
   * ```ts
   * cors: {
   *   "Access-Control-Allow-Origin": "https://myapp.com",
   *   "Access-Control-Allow-Credentials": "true",
   *   "Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
   *   "Access-Control-Allow-Headers": "Content-Type, Authorization"
   * }
   * ```
   *
   * When set to a `HeadersInit` value, uses those as the CORS headers instead.
   * CORS preflight (OPTIONS) requests are handled automatically for matched routes.
   * Non-WebSocket responses on matched routes will also have the CORS headers appended.
   */
  cors?: boolean | HeadersInit;
  /**
   * Retry transient Durable Object infrastructure errors thrown while routing
   * to the target DO. Enabled by default; pass `false` to disable.
   *
   * Only errors marked `retryable === true` are retried, and overloaded
   * errors (`overloaded === true`) are never retried.
   */
  routingRetry?: false | RoutingRetryOptions;
  onBeforeConnect?: (
    req: Request,
    lobby: Lobby<Env>
  ) => Response | Request | void | Promise<Response | Request | void>;
  onBeforeRequest?: (
    req: Request,
    lobby: Lobby<Env>
  ) =>
    | Response
    | Request
    | void
    | Promise<Response | Request | undefined | void>;
}
declare function routePartykitRequest<
  Env extends Cloudflare.Env = Cloudflare.Env,
  T extends Server<Env> = Server<Env>,
  Props extends Record<string, unknown> = Record<string, unknown>
>(
  req: Request,
  env?: Env,
  options?: PartyServerOptions<Env, Props>
): Promise<Response | null>;
declare class Server<
  Env extends Cloudflare.Env = Cloudflare.Env,
  Props extends Record<string, unknown> = Record<string, unknown>
> extends DurableObject<Env> {
  #private;
  static options: {
    hibernate?: boolean;
  };
  /**
   * Execute SQL queries against the Server's database
   * @template T Type of the returned rows
   * @param strings SQL query template strings
   * @param values Values to be inserted into the query
   * @returns Array of query results
   */
  sql<T = Record<string, string | number | boolean | null>>(
    strings: TemplateStringsArray,
    ...values: (string | number | boolean | null)[]
  ): T[];
  constructor(ctx: DurableObjectState, env: Env);
  /**
   * Handle incoming requests to the server.
   */
  fetch(request: Request): Promise<Response>;
  webSocketMessage(ws: WebSocket, message: WSMessage): Promise<void>;
  webSocketClose(
    ws: WebSocket,
    code: number,
    reason: string,
    wasClean: boolean
  ): Promise<void>;
  webSocketError(ws: WebSocket, error: unknown): Promise<void>;
  /**
   * @internal — Do not use directly. This is an escape hatch for frameworks
   * (like Agents) that receive calls via native DO RPC, bypassing the
   * standard fetch/alarm/webSocket entry points where initialization
   * normally happens. Calling this from application code is unsupported
   * and may break without notice.
   */
  __unsafe_ensureInitialized(): Promise<void>;
  /**
   * The name for this server.
   *
   * Resolves from `this.ctx.id.name` — the native DO id name, populated
   * whenever the stub was created via `idFromName()` or `getByName()`.
   * This is available inside every entry point (including the constructor,
   * alarms, and hibernating websocket handlers).
   *
   * For alarm handlers firing on stale on-disk alarm records from
   * older workerd versions that didn't persist `name` into the alarm
   * record, the name is recovered from a storage fallback record.
   *
   * Throws if neither source is available — typically this means the DO
   * was addressed via `idFromString()` or `newUniqueId()`, which is not
   * supported by PartyServer.
   */
  get name(): string;
  /**
   * Establish this server's name and trigger `onStart()`.
   *
   * Use cases:
   *
   *   1. **Framework-level bootstrap of DOs where `ctx.id.name` is
   *      undefined** — e.g. DOs addressed via `idFromString()` /
   *      `newUniqueId()`. `setName()` stashes the name in memory and
   *      persists it under `__ps_name` so cold-wake invocations
   *      recover it via `#ensureInitialized()`'s legacy fallback.
   *   2. **Delivering initial `props` to `onStart()`** via the
   *      optional second argument.
   *
   * For DOs addressed via `idFromName()` / `getByName()`, calling
   * `setName()` is redundant — `this.name` is available automatically
   * from `ctx.id.name`. The normal initialization path also persists
   * a fallback record so old-compat alarm handlers can recover the name.
   * Throws if `name` does not match `ctx.id.name`.
   *
   * **Not appropriate for facets.** Cloudflare Agents and any other
   * framework using `ctx.facets.get(...)` should pass an explicit
   * `id` in `FacetStartupOptions` so the facet has its own
   * `ctx.id.name`:
   *
   * ```ts
   * const stub = ctx.facets.get(facetKey, () => ({
   *   class: ChildClass,
   *   id: ctx.exports.SomeBoundDOClass.idFromName(facetName),
   * }));
   * ```
   *
   * Without an explicit `id`, the facet inherits the parent DO's
   * `ctx.id` (including `ctx.id.name`), and `setName()` will throw
   * the ctx.id.name-mismatch error because the facet's intended
   * name differs from the parent's. See
   * https://developers.cloudflare.com/dynamic-workers/usage/durable-object-facets/
   * for the `FacetStartupOptions.id` semantics.
   *
   * @deprecated for callers that address DOs via `idFromName()` /
   * `getByName()`. Still the supported API for framework-level
   * bootstrap of header/`newUniqueId`-addressed DOs and for
   * delivering initial `props` to `onStart()`.
   */
  setName(name: string, props?: Props): Promise<void>;
  /**
   * @internal
   * @deprecated Retained for backward compatibility with older callers.
   * `routePartykitRequest` no longer uses this method; it sends props via
   * the `x-partykit-props` header on the underlying `fetch()` request.
   */
  _initAndFetch(
    name: string,
    props: Props | undefined,
    request: Request
  ): Promise<Response>;
  /** Send a message to all connected clients, except connection ids listed in `without` */
  broadcast(
    msg: string | ArrayBuffer | ArrayBufferView,
    without?: string[] | undefined
  ): void;
  /** Get a connection by connection id */
  getConnection<TState = unknown>(id: string): Connection<TState> | undefined;
  /**
   * Get all connections. Optionally, you can provide a tag to filter returned connections.
   * Use `Server#getConnectionTags` to tag the connection on connect.
   */
  getConnections<TState = unknown>(tag?: string): Iterable<Connection<TState>>;
  /**
   * You can tag a connection to filter them in Server#getConnections.
   * Each connection supports up to 9 tags, each tag max length is 256 characters.
   */
  getConnectionTags(
    connection: Connection,
    context: ConnectionContext
  ): string[] | Promise<string[]>;
  /**
   * Called when the server is started for the first time.
   */
  onStart(props?: Props): void | Promise<void>;
  /**
   * Called when a new connection is made to the server.
   */
  onConnect(
    connection: Connection,
    ctx: ConnectionContext
  ): void | Promise<void>;
  /**
   * Called when a message is received from a connection.
   */
  onMessage(connection: Connection, message: WSMessage): void | Promise<void>;
  /**
   * Called when a connection is closed.
   */
  onClose(
    connection: Connection,
    code: number,
    reason: string,
    wasClean: boolean
  ): void | Promise<void>;
  /**
   * Called when an error occurs on a connection.
   */
  onError(connection: Connection, error: unknown): void | Promise<void>;
  /**
   * Called when a request is made to the server.
   */
  onRequest(request: Request): Response | Promise<Response>;
  /**
   * Called when an exception occurs.
   * @param error - The error that occurred.
   */
  onException(error: unknown): void | Promise<void>;
  onAlarm(): void | Promise<void>;
  alarm(): Promise<void>;
}
//#endregion
export {
  Connection,
  ConnectionContext,
  ConnectionSetStateFn,
  ConnectionState,
  Lobby,
  PartyServerOptions,
  RoutingRetryEvent,
  RoutingRetryOptions,
  Server,
  WSMessage,
  getServerByName,
  routePartykitRequest
};
//# sourceMappingURL=index.d.ts.map
