import http, { IncomingMessage } from "node:http";
import { z } from "zod";
import { DisconnectReason, RemoteSocket, Server, Socket } from "socket.io";
import ts from "typescript";

//#region src/async-api/security.d.ts
interface FlowCommons {
  /** @desc The URL to be used for obtaining refresh tokens. */
  refreshUrl?: string;
  /** @desc A map between the scope name and a short description for it. */
  availableScopes: Record<string, string>;
}
interface AuthHavingFlow {
  /** @desc The authorization URL to be used for this flow. */
  authorizationUrl: string;
}
interface TokenHavingFlow {
  /** @desc The token URL to be used for this flow. */
  tokenUrl: string;
}
interface OAuthFlowsObject {
  implicit?: FlowCommons & AuthHavingFlow;
  password?: FlowCommons & TokenHavingFlow;
  clientCredentials?: FlowCommons & TokenHavingFlow;
  authorizationCode?: FlowCommons & AuthHavingFlow & TokenHavingFlow;
}
interface HttpApiKeySecurity {
  type: "httpApiKey";
  /** @desc The name of the header, query or cookie parameter to be used. */
  name: string;
  in: "query" | "header" | "cookie";
}
interface ApiKeySecurity {
  type: "apiKey";
  in: "user" | "password";
}
interface HttpSecurity {
  type: "http";
  /** @link https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml */
  scheme?: string;
  /** @example "Bearer" */
  bearerFormat?: string;
}
interface ScopesHavingSecurity {
  /** @desc List of the needed scope names. An empty array means no scopes are needed. */
  scopes?: string[];
}
interface OAuth2Security extends ScopesHavingSecurity {
  type: "oauth2";
  flows: OAuthFlowsObject;
}
interface OpenIdConnectSecurity extends ScopesHavingSecurity {
  type: "openIdConnect";
  /** @desc OpenId Connect URL to discover OAuth2 configuration values */
  openIdConnectUrl: string;
}
interface OtherSecurity {
  type: "userPassword" | "X509" | "symmetricEncryption" | "asymmetricEncryption" | "plain" | "scramSha256" | "scramSha512" | "gssapi";
}
type SecuritySchemeObject = {
  description?: string;
} & (HttpApiKeySecurity | ApiKeySecurity | HttpSecurity | OAuth2Security | OpenIdConnectSecurity | OtherSecurity);
//#endregion
//#region src/common-helpers.d.ts
type EmptyObject = Record<string, never>;
//#endregion
//#region src/distribution.d.ts
interface Distribution {
  join: (rooms: string | string[]) => Promise<void>;
  leave: (rooms: string | string[]) => Promise<void>;
}
//#endregion
//#region src/remote-client.d.ts
type SomeRemoteSocket = RemoteSocket<Record<string, (...args: any[]) => void>, unknown>;
interface RemoteClient<E extends EmissionMap, D extends z.ZodObject> extends Distribution {
  id: string;
  handshake: SomeRemoteSocket["handshake"];
  rooms: string[];
  getData: () => Readonly<Partial<z.infer<D>>>;
  emit: Emitter<E>;
}
//#endregion
//#region src/emission.d.ts
interface Emission {
  schema: z.ZodTuple;
  ack?: z.ZodTuple;
}
type EmissionMap = Record<string, Emission>;
type TupleOrTrue<T> = T extends z.ZodTuple ? T : z.ZodLiteral<true>;
type TuplesOrTrue<T> = T extends z.ZodTuple ? z.ZodArray<T> : z.ZodLiteral<true>;
type Emitter<E extends EmissionMap> = <K extends keyof E>(evt: K, ...args: z.input<E[K]["schema"]>) => Promise<z.output<TupleOrTrue<E[K]["ack"]>>>;
type Broadcaster<E extends EmissionMap> = <K extends keyof E>(evt: K, ...args: z.input<E[K]["schema"]>) => Promise<z.output<TuplesOrTrue<E[K]["ack"]>>>;
type RoomService<E extends EmissionMap, D extends z.ZodObject> = (rooms: string | string[]) => {
  /**
   * @desc Emits an event to all/others (depending on context) in the specified room(s)
   * @throws z.ZodError on validation
   * @throws Error on ack timeout
   * */
  broadcast: Broadcaster<E>;
  getClients: () => Promise<RemoteClient<E, D>[]>;
};
//#endregion
//#region src/client.d.ts
interface Client<E extends EmissionMap, D extends z.ZodObject> extends Distribution {
  /** @alias Socket.connected */
  isConnected: () => boolean;
  /** @alias Socket.id */
  id: Socket["id"];
  handshake: Socket["handshake"];
  /**
   * @desc When using express-session:
   * @example getRequest<express.Request>().session
   **/
  getRequest: <T extends IncomingMessage = Socket["request"]>() => T;
  /** @desc Returns the list of the rooms the client in */
  getRooms: () => string[];
  /**
   * @desc Sends a new event to the client (this is not acknowledgement)
   * @throws z.ZodError on validation
   * @throws Error on ack timeout
   * */
  emit: Emitter<E>;
  /**
   * @desc Emits to others
   * @throws z.ZodError on validation
   * @throws Error on ack timeout
   * */
  broadcast: Broadcaster<E>;
  /** @desc Returns the client metadata according to the specified type or empty object */
  getData: () => Readonly<Partial<z.infer<D>>>;
  /**
   * @desc Sets the client metadata according to the specified type
   * @throws z.ZodError on validation
   * */
  setData: (value: z.infer<D>) => void;
}
//#endregion
//#region src/logger.d.ts
/**
 * @desc Using module augmentation approach you can set the type of the actual logger used
 * @example declare module "zod-sockets" { interface LoggerOverrides extends winston.Logger {} }
 * @link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
 * */
interface LoggerOverrides {}
/** @desc You can use any logger compatible with this type. */
type AbstractLogger = Record<"info" | "debug" | "warn" | "error", (message: string, meta?: any) => any> & LoggerOverrides;
//#endregion
//#region src/handler.d.ts
interface IndependentContext<E extends EmissionMap, D extends z.ZodObject> {
  logger: AbstractLogger;
  all: {
    /** @desc Returns the list of available rooms */getRooms: () => string[]; /** @desc Returns the list of familiar clients */
    getClients: () => Promise<RemoteClient<E, D>[]>; /** @desc Emits an event to everyone */
    broadcast: Broadcaster<E>;
  };
  /** @desc Provides room(s)-scope methods */
  withRooms: RoomService<E, D>;
}
interface ClientContext<E extends EmissionMap, D extends z.ZodObject> extends IndependentContext<E, D> {
  /** @desc The sender of the incoming event */
  client: Client<E, D>;
}
interface TracingContext<E extends EmissionMap, D extends z.ZodObject> extends ClientContext<E, D> {
  event: string;
  payload: unknown[];
}
interface ErrorContext<E extends EmissionMap, D extends z.ZodObject> extends IndependentContext<E, D>, Partial<Pick<TracingContext<E, D>, "event" | "payload" | "client">> {
  error: Error;
}
interface ActionContext<IN, E extends EmissionMap, D extends z.ZodObject> extends ClientContext<E, D> {
  /** @desc Validated payload */
  input: IN;
}
type Handler<CTX, OUT> = (params: CTX) => Promise<OUT>;
//#endregion
//#region src/hooks.d.ts
interface Hooks<E extends EmissionMap, D extends z.ZodObject> {
  /** @desc The place for emitting events regardless receiving events */
  onConnection: Handler<ClientContext<E, D>, void>;
  /** @desc Called when a client disconnects, with the disconnect reason provided by Socket.IO */
  onDisconnect: Handler<ClientContext<E, D> & {
    reason: DisconnectReason;
  }, void>;
  onAnyIncoming: Handler<TracingContext<E, D>, void>;
  onAnyOutgoing: Handler<TracingContext<E, D>, void>;
  /** @desc The place for emitting events regardless clients activity */
  onStartup: Handler<IndependentContext<E, D>, void>;
  /** @desc The place for handling errors, in particular validation errors of the incoming events */
  onError: Handler<ErrorContext<E, D>, void>;
}
//#endregion
//#region src/namespace.d.ts
declare const rootNS = "/";
type RootNS = typeof rootNS;
interface Namespace<E extends EmissionMap, D extends z.ZodObject> {
  /** @desc The events that the server can emit */
  emission: E;
  /** @desc Handlers for some events in different contexts */
  hooks: Partial<Hooks<E, D>>;
  /** @desc Schema of the client metadata in this namespace */
  metadata: D;
  security: SecuritySchemeObject[];
}
type Namespaces = Record<string, Namespace<EmissionMap, z.ZodObject>>;
//#endregion
//#region src/config.d.ts
interface ConstructorOptions<NS extends Namespaces> {
  /**
   * @desc The acknowledgment awaiting timeout
   * @default 2000
   * */
  timeout?: number;
  /**
   * @desc You can disable the startup logo.
   * @default true
   */
  startupLogo?: boolean;
  /**
   * @desc Define namespaces inline or consider using addNamespace() method
   * @default {}
   * @see Namespace
   * */
  namespaces?: NS;
  security?: SecuritySchemeObject[];
}
/** @todo consider using it for namespaces declaration only */
declare class Config<T extends Namespaces = EmptyObject> {
  constructor({
    timeout,
    startupLogo,
    namespaces,
    security
  }?: ConstructorOptions<T>);
  /** @default { path: "/", emission: {}, metadata: z.object({}), hooks: {}, examples: {}, security: [] } */
  addNamespace<E extends EmissionMap = EmptyObject, D extends z.ZodObject = z.ZodObject<EmptyObject>, K extends string = RootNS>({
    path,
    emission,
    metadata,
    hooks,
    security
  }: Partial<Namespace<E, D>> & {
    path?: K;
  }): Config<Omit<T, K> & Record<K, Namespace<E, D>>>;
}
/** @desc Shorthand for single namespace config (root namespace only) */
declare const createSimpleConfig: <E extends EmissionMap, D extends z.ZodObject>({
  startupLogo,
  timeout,
  security,
  emission,
  hooks,
  metadata
}?: Omit<ConstructorOptions<never>, "namespaces"> & Partial<Namespace<E, D>>) => Config<Omit<EmptyObject, "/"> & Record<"/", Namespace<E, D>>>;
//#endregion
//#region src/actions-factory.d.ts
interface Commons<IN extends z.ZodTuple, NS extends Namespaces, K extends keyof NS> {
  /** @desc The incoming event payload validation schema (without or excluding acknowledgement) */
  input: IN;
  /**
   * @desc The namespace this Action belongs to (optional)
   * @default "/"
   * */
  ns?: K;
  /** @desc The incoming event name */
  event: string;
}
interface ActionNoAckDef<IN extends z.ZodTuple, NS extends Namespaces, K extends keyof NS> extends Commons<IN, NS, K> {
  /** @desc No output schema => no returns => no acknowledgement */
  handler: Handler<ActionContext<z.output<IN>, NS[K]["emission"], NS[K]["metadata"]>, void>;
}
interface ActionWithAckDef<IN extends z.ZodTuple, OUT extends z.ZodTuple, NS extends Namespaces, K extends keyof NS> extends Commons<IN, NS, K> {
  /** @desc The acknowledgement validation schema */
  output: OUT;
  /** @desc The returns become an Acknowledgement */
  handler: Handler<ActionContext<z.output<IN>, NS[K]["emission"], NS[K]["metadata"]>, z.input<OUT>>;
}
declare class ActionsFactory<NS extends Namespaces> {
  protected config: Config<NS>;
  constructor(config: Config<NS>);
  build<IN extends z.ZodTuple, OUT extends z.ZodTuple | undefined = undefined, K extends keyof NS = RootNS>(def: ActionNoAckDef<IN, NS, K> | ActionWithAckDef<IN, NonNullable<OUT>, NS, K>): Action<NS, IN, OUT>;
}
//#endregion
//#region src/action.d.ts
declare abstract class AbstractAction {
  abstract execute(params: {
    params: unknown[];
  } & ClientContext<EmissionMap, z.ZodObject>): Promise<void>;
}
declare class Action<NS extends Namespaces, IN extends z.ZodTuple, OUT extends z.ZodTuple | undefined = undefined> extends AbstractAction {
  constructor(action: ActionWithAckDef<IN, NonNullable<OUT>, NS, keyof NS> | ActionNoAckDef<IN, NS, keyof NS>);
  get event(): string;
  get namespace(): keyof NS;
  get inputSchema(): IN;
  get outputSchema(): OUT;
  execute({
    params,
    logger,
    ...rest
  }: {
    params: unknown[];
  } & ClientContext<EmissionMap, z.ZodObject>): Promise<void>;
}
//#endregion
//#region src/attach.d.ts
declare const attachSockets: <NS extends Namespaces>({
  io,
  actions,
  target,
  config: {
    namespaces,
    timeout,
    startupLogo
  },
  logger: rootLogger
}: {
  /**
   * @desc The Socket.IO server
   * @example new Server()
   * */
  io: Server;
  /**
   * @desc The array of handling rules for the incoming Socket.IO events
   * @example [ onPing ]
   * */
  actions: AbstractAction[];
  /**
   * @desc HTTP or HTTPS server to attach the sockets to
   * @example http.createServer().listen(8090)
   * */
  target: http.Server; /** @desc The configuration describing the emission (outgoing events) */
  config: Config<NS>;
  /**
   * @desc The instance of a logger
   * @default console
   * */
  logger?: AbstractLogger;
}) => Promise<Server>;
//#endregion
//#region src/integration.d.ts
interface IntegrationParams {
  typescript: typeof ts;
  config: Config<Namespaces>;
  actions: AbstractAction[];
  /**
   * @desc When event has both .rest() and an acknowledgement, the "...rest" can not be placed in a middle.
   * @desc In this case, overloads are used to reflect variations on different number of the function arguments.
   * @default 3
   * @example ( (cb) => void ) | ( (rest1, cb) => void ) | ( (rest1, rest2, cb) => void )
   */
  maxOverloads?: number;
}
declare const registryScopes: string[];
declare class Integration {
  protected registry: Record<string, // namespace
  Record<(typeof registryScopes)[number], {
    event: string;
    node: ts.TypeNode;
  }[]>>;
  constructor({
    typescript,
    config: {
      namespaces
    },
    actions,
    maxOverloads
  }: IntegrationParams);
  static create(params: Omit<IntegrationParams, "typescript">): Promise<Integration>;
  print(printerOptions?: ts.PrinterOptions): string;
}
//#endregion
//#region src/async-api/websockets.d.ts
/** @see https://github.com/asyncapi/bindings/tree/master/websockets */
declare namespace WS {
  /** @desc This object MUST NOT contain any properties. Its name is reserved for future use. */
  interface Server {}
  /**
   * @desc When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple
   * @desc virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or,
   * @desc put it another way, there's only one channel and its characteristics are strongly related to the protocol
   * @desc used for the handshake, i.e., HTTP.
   */
  interface Channel {
    /**
     * @desc The HTTP method to use when establishing the connection. Its value MUST be either GET or POST.
     * */
    method: "GET" | "POST";
    /**
     * @desc A Schema object containing the definitions for each query parameter.
     * @desc This schema MUST be of type object and have a properties key.
     */
    query: SchemaObject | ReferenceObject;
    /**
     * @desc A Schema object containing the definitions of the HTTP headers to use when establishing the connection.
     * @desc This schema MUST be of type object and have a properties key.
     */
    headers: SchemaObject | ReferenceObject;
    /**
     * @desc The version of this binding. If omitted, "latest" MUST be assumed.
     */
    bindingVersion: "0.1.0";
  }
  /**
   * @desc This object MUST NOT contain any properties. Its name is reserved for future use.
   * */
  interface Operation {}
  /** @desc This object MUST NOT contain any properties. Its name is reserved for future use. */
  interface Message {}
}
//#endregion
//#region src/async-api/model.d.ts
/**
 * @fileoverview AsyncAPI specification
 * @version 3.0.0
 */
interface Bindings<T> {
  ws?: T;
}
/** @since 3.0.0 detached from OAS; added host, pathname, title, description, tags, externalDocs; changed security */
interface ServerObject {
  host: string;
  protocol: string;
  protocolVersion?: string;
  pathname?: string;
  title?: string;
  description?: string;
  variables?: Record<string, ServerVariableObject>;
  security?: Array<SecuritySchemeObject | ReferenceObject>;
  tags?: TagObject[];
  externalDocs?: ExternalDocumentationObject;
  bindings?: Bindings<WS.Server>;
}
interface ContactObject {
  name?: string;
  url?: string;
  email?: string;
}
interface LicenseObject {
  name: string;
  url?: string;
}
/** @since 3.0.0 contains tags and externalDocs */
interface InfoObject {
  title: string;
  version: string;
  description?: string;
  termsOfService?: string;
  contact?: ContactObject;
  license?: LicenseObject;
  tags?: TagObject[];
  externalDocs?: ExternalDocumentationObject;
}
/** @since 3.0.0 channels are optional, added operations */
interface AsyncApiObject {
  asyncapi: string;
  /** @desc URI or URN format */
  id?: string;
  info: InfoObject;
  servers?: Record<string, ServerObject>;
  channels?: ChannelsObject;
  operations?: OperationsObject;
  components?: ComponentsObject;
  defaultContentType?: string;
}
/**
 * @since 3.0.0 An identifier for the described channel. The channelId value is case-sensitive.
 * */
type ChannelsObject = Record<string, ChannelObject>;
interface ReferenceObject {
  $ref: string;
}
/** @since 3.0.0 renamed; added address, title, summary, messages, servers, tags, externalDocs; removed pubs/subs */
interface ChannelObject {
  /** @desc Typically the "topic name", "routing key", "event type", or "path". */
  address?: string | null;
  title?: string;
  summary?: string;
  description?: string;
  messages?: MessagesObject;
  servers?: ReferenceObject[];
  /** @desc Describes a map of parameters included in a channel name. */
  parameters?: ParametersObject;
  tags?: TagObject[];
  externalDocs?: ExternalDocumentationObject;
  /** @desc Map describing protocol-specific definitions for a channel. */
  bindings?: Bindings<WS.Channel>;
}
interface ServerVariableObject {
  enum?: string[] | boolean[] | number[];
  default: string | boolean | number;
  description?: string;
  examples?: string[];
}
type SchemaObjectType = "integer" | "number" | "string" | "boolean" | "object" | "null" | "array";
/**
 * @desc DRAFT-07
 * @link https://json-schema.org/specification-links#draft-7
 * @link https://json-schema.org/draft-07/draft-handrews-json-schema-validation-01
 * */
interface Draft07 {
  title?: string;
  type?: SchemaObjectType | SchemaObjectType[];
  required?: string[];
  multipleOf?: number;
  maximum?: number;
  exclusiveMaximum?: number;
  minimum?: number;
  exclusiveMinimum?: number;
  maxLength?: number;
  minLength?: number;
  pattern?: string;
  maxItems?: number;
  minItems?: number;
  uniqueItems?: boolean;
  maxProperties?: number;
  minProperties?: number;
  enum?: any[];
  const?: any;
  examples?: any[];
  readOnly?: boolean;
  writeOnly?: boolean;
  properties?: {
    [propertyName: string]: SchemaObject | ReferenceObject;
  };
  patternProperties?: {
    [pattern: string]: SchemaObject | ReferenceObject;
  };
  additionalProperties?: SchemaObject | ReferenceObject | boolean;
  additionalItems?: SchemaObject | ReferenceObject | boolean;
  items?: SchemaObject | ReferenceObject | [SchemaObject | ReferenceObject, ...Array<SchemaObject | ReferenceObject>];
  propertyNames?: SchemaObject | ReferenceObject;
  contains?: SchemaObject;
  allOf?: (SchemaObject | ReferenceObject)[];
  oneOf?: (SchemaObject | ReferenceObject)[];
  anyOf?: (SchemaObject | ReferenceObject)[];
  not?: SchemaObject | ReferenceObject;
  /**
   * @desc JSON Schema compliant Content-Type, optional when specified as a key of ContentObject
   * @example image/png
   */
  contentMediaType?: string;
  /**
   * @desc Specifies the Content-Encoding for the schema, supports all encodings from RFC4648, and "quoted-printable" from RFC2045
   * @override format
   * @see https://datatracker.ietf.org/doc/html/rfc4648
   * @see https://datatracker.ietf.org/doc/html/rfc2045#section-6.7
   * @example base64
   */
  contentEncoding?: string;
}
/** @link https://www.asyncapi.com/docs/reference/specification/v3.0.0#schemaObject */
interface SchemaObject extends Draft07 {
  description?: string;
  format?: "int32" | "int64" | "float" | "double" | "byte" | "binary" | "date" | "date-time" | "password" | string;
  default?: any;
  discriminator?: string;
  externalDocs?: ExternalDocumentationObject | ReferenceObject;
  deprecated?: boolean;
}
/** @since 3.0.0 added replies */
interface ComponentsObject {
  schemas?: Record<string, SchemaObject | ReferenceObject>;
  servers?: Record<string, ServerObject>;
  serverVariables?: Record<string, ServerVariableObject>;
  channels?: Record<string, ChannelObject>;
  messages?: Record<string, MessageObject>;
  securitySchemes?: Record<string, SecuritySchemeObject>;
  parameters?: Record<string, ParameterObject>;
  correlationIds?: Record<string, CorrelationIDObject>;
  operationTraits?: Record<string, OperationTraitObject>;
  messageTraits?: Record<string, MessageTraitObject>;
  replies?: Record<string, OperationReplyObject>;
  serverBindings?: Bindings<WS.Server>;
  channelBindings?: Bindings<WS.Channel>;
  operationBindings?: Bindings<WS.Operation>;
  messageBindings?: Bindings<WS.Message>;
}
/** @since 3.0.0 supports MultiFormatSchemaObject in payload */
interface MessageObject extends MessageTraitObject {
  payload?: SchemaObject | MultiFormatSchemaObject | ReferenceObject;
  traits?: MessageTraitObject | ReferenceObject;
}
/** @desc The key represents the message identifier. The messageId value is case-sensitive. */
type MessagesObject = Record<string, MessageObject | ReferenceObject>;
/** @since 3.0.0 added action, channel, messages, reply */
interface OperationObject extends OperationTraitObject {
  action: "send" | "receive";
  /** @desc A $ref pointer to the definition of the channel in which this operation is performed. */
  channel: ReferenceObject;
  /** @desc A list of $ref pointers pointing to the supported Message Objects that can be processed by this operation */
  messages?: ReferenceObject[];
  reply?: OperationReplyObject | ReferenceObject;
  traits?: Record<string, OperationTraitObject>;
}
/**
 * @desc Describes the reply part that MAY be applied to an Operation Object.
 * @desc If an operation implements the request/reply pattern, the reply object represents the response message.
 * @since 3.0.0 new
 * */
interface OperationReplyObject {
  /** @desc Definition of the address that implementations MUST use for the reply. */
  address?: OperationReplyAddressObject | ReferenceObject;
  /** @desc A $ref pointer to the definition of the channel in which this operation is performed. */
  channel?: ReferenceObject;
  /** @desc A list of pointers to the supported Message Objects that can be processed by this operation as reply */
  messages?: ReferenceObject[];
}
/**
 * @desc An object that specifies where an operation has to send the reply.
 * @since 3.0.0 new
 * */
interface OperationReplyAddressObject {
  /**
   * @desc A runtime expression that specifies the location of the reply address.
   * @example $message.header#/replyTo
   * @example $message.payload#/messageId
   * @link https://www.asyncapi.com/docs/reference/specification/v3.0.0#runtimeExpression
   * */
  location: string;
  description?: string;
}
/**
 * @desc The operation this application MUST implement. The field name (operationId) MUST be a string used to
 * @desc identify the operation in the document where it is defined, and its value is case-sensitive.
 * */
type OperationsObject = Record<string, OperationObject>;
/** @since 3.0.0 operationId moved to OperationsObject; added title, security */
interface OperationTraitObject {
  title?: string;
  summary?: string;
  description?: string;
  security?: Array<SecuritySchemeObject | ReferenceObject>;
  tags?: TagObject[];
  externalDocs?: ExternalDocumentationObject;
  bindings?: Bindings<WS.Operation>;
}
/** @since 3.0.0 messageId moved to MessagesObject, schemaFormat moved to MultiFormatSchemaObject */
interface MessageTraitObject {
  headers?: SchemaObject | MultiFormatSchemaObject;
  correlationId?: CorrelationIDObject;
  contentType?: string;
  name?: string;
  title?: string;
  summary?: string;
  description?: string;
  tags?: TagObject[];
  externalDocs?: ExternalDocumentationObject;
  bindings?: Bindings<WS.Message>;
  examples?: MessageExampleObject[];
}
/**
 * @desc Represents an example of a Message Object and MUST contain either headers and/or payload fields.
 * @since 3.0.0 new
 * */
interface MessageExampleObject {
  name?: string;
  summary?: string;
  headers?: Record<string, any>;
  payload?: any;
}
/** @since 3.0.0 new */
interface MultiFormatSchemaObject {
  /**
   * @desc A string containing the name of the schema format that is used to define the information.
   * @example application/vnd.aai.asyncapi+yaml;version=3.0.0
   * @example application/schema+yaml;version=draft-07
   * @example application/vnd.oai.openapi+yaml;version=3.0.0
   * */
  schemaFormat: string;
  schema: SchemaObject;
}
interface CorrelationIDObject {
  description?: string;
  /**
   * @desc A runtime expression that specifies the location of the correlation ID.
   * @example $message.header#/correlationId
   * @link https://www.asyncapi.com/docs/reference/specification/v3.0.0#runtimeExpression
   * */
  location: string;
}
interface TagObject {
  name: string;
  description?: string;
  externalDocs?: ExternalDocumentationObject;
}
/** @since 3.0.0 partially extends SchemaObject; schema prop removed */
interface ParameterObject extends Pick<SchemaObject, "enum" | "default" | "description" | "examples"> {
  /**
   * @desc A runtime expression that specifies the location of the parameter value.
   * @link https://www.asyncapi.com/docs/reference/specification/v3.0.0#runtimeExpression
   * */
  location?: string;
}
/** @desc Property pattern ^[A-Za-z0-9_\-]+$ */
type ParametersObject = Record<string, ParameterObject>;
interface ExternalDocumentationObject {
  description?: string;
  url: string;
}
//#endregion
//#region src/async-api/builder.d.ts
declare class AsyncApiBuilder {
  protected readonly document: AsyncApiObject;
  constructor(initial: Pick<AsyncApiObject, "info" | "id" | "defaultContentType">);
  addServer(name: string, server: ServerObject): this;
  addChannel(name: string, channel: ChannelObject): this;
  addOperation(name: string, operation: OperationObject): this;
  addSecurityScheme(name: string, schema: SecuritySchemeObject): this;
  addSchema(name: string, schema: SchemaObject | ReferenceObject): this;
  getSpec(): AsyncApiObject;
  getSpecAsJson(replacer?: (key: string, value: unknown) => unknown, space?: string | number): string;
  getSpecAsYaml(): string;
}
//#endregion
//#region src/documentation.d.ts
interface DocumentationParams {
  title: string;
  version: string;
  documentId?: string;
  description?: string;
  contact?: ContactObject;
  license?: LicenseObject;
  servers?: Record<string, {
    url: string;
    description?: string;
  }>;
  actions: AbstractAction[];
  config: Config<Namespaces>;
}
declare class Documentation extends AsyncApiBuilder {
  constructor({
    actions,
    config: {
      namespaces,
      security: globalSecurity
    },
    title,
    version,
    documentId,
    description,
    contact,
    license,
    servers
  }: DocumentationParams);
}
//#endregion
//#region src/errors.d.ts
/** @desc An error related to the input and output schemas declaration */
declare class IOSchemaError extends Error {
  name: string;
}
/** @desc An error of validating the incoming data */
declare class InputValidationError extends IOSchemaError {
  readonly cause: z.ZodError;
  name: string;
  constructor(cause: z.ZodError);
}
/** @desc An error of validating the outgoing data */
declare class OutputValidationError extends IOSchemaError {
  readonly cause: z.ZodError;
  name: string;
  constructor(cause: z.ZodError);
}
//#endregion
export { AbstractAction, type AbstractLogger, ActionsFactory, type ClientContext, Config, Documentation, type EmissionMap, InputValidationError, Integration, type LoggerOverrides, type Namespace, OutputValidationError, attachSockets, createSimpleConfig };