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

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);

type EmptyObject = Record<string, never>;

interface Distribution {
    join: (rooms: string | string[]) => Promise<void>;
    leave: (rooms: string | string[]) => Promise<void>;
}

type SomeRemoteSocket = RemoteSocket<Record<string, (...args: any[]) => void>, unknown>;
interface RemoteClient<E extends EmissionMap, D extends z.SomeZodObject> extends Distribution {
    id: string;
    handshake: SomeRemoteSocket["handshake"];
    rooms: string[];
    getData: () => Readonly<Partial<z.infer<D>>>;
    emit: Emitter<E>;
}

interface Emission {
    schema: z.AnyZodTuple;
    ack?: z.AnyZodTuple;
}
type EmissionMap = Record<string, Emission>;
type TupleOrTrue<T> = T extends z.AnyZodTuple ? T : z.ZodLiteral<true>;
type TuplesOrTrue<T> = T extends z.AnyZodTuple ? 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.SomeZodObject> = (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>[]>;
};

interface Client<E extends EmissionMap, D extends z.SomeZodObject> 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;
}

/**
 * @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;

interface IndependentContext<E extends EmissionMap, D extends z.SomeZodObject> {
    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.SomeZodObject> extends IndependentContext<E, D> {
    /** @desc The sender of the incoming event */
    client: Client<E, D>;
}
interface TracingContext<E extends EmissionMap, D extends z.SomeZodObject> extends ClientContext<E, D> {
    event: string;
    payload: unknown[];
}
interface ErrorContext<E extends EmissionMap, D extends z.SomeZodObject> extends IndependentContext<E, D>, Partial<Pick<TracingContext<E, D>, "event" | "payload" | "client">> {
    error: Error;
}
interface ActionContext<IN, E extends EmissionMap, D extends z.SomeZodObject> extends ClientContext<E, D> {
    /** @desc Validated payload */
    input: IN;
}
type Handler<CTX, OUT> = (params: CTX) => Promise<OUT>;

interface Hooks<E extends EmissionMap, D extends z.SomeZodObject> {
    /** @desc The place for emitting events regardless receiving events */
    onConnection: Handler<ClientContext<E, D>, void>;
    onDisconnect: Handler<ClientContext<E, D>, 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>;
}

declare const rootNS = "/";
type RootNS = typeof rootNS;
interface Example<T extends Emission> {
    payload?: z.output<T["schema"]>;
    ack?: T["ack"] extends z.AnyZodTuple ? z.input<T["ack"]> : never;
}
interface Namespace<E extends EmissionMap, D extends z.SomeZodObject> {
    /** @desc The events that the server can emit */
    emission: E;
    /** @desc Examples for the emission per event */
    examples: {
        [K in keyof E]?: Example<E[K]> | Example<E[K]>[];
    };
    /** @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.SomeZodObject>>;

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> {
    readonly timeout: number;
    readonly startupLogo: boolean;
    readonly security: SecuritySchemeObject[];
    readonly namespaces: T;
    constructor({ timeout, startupLogo, namespaces, security, }?: ConstructorOptions<T>);
    /** @default { path: "/", emission: {}, metadata: z.object({}), hooks: {}, examples: {}, security: [] } */
    addNamespace<E extends EmissionMap = EmptyObject, D extends z.SomeZodObject = z.ZodObject<EmptyObject>, K extends string = RootNS>({ path, emission, metadata, hooks, examples, 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.SomeZodObject>({ startupLogo, timeout, security, emission, examples, hooks, metadata, }?: Omit<ConstructorOptions<never>, "namespaces"> & Partial<Namespace<E, D>>) => Config<Omit<EmptyObject, "/"> & Record<"/", Namespace<E, D>>>;

interface Commons<IN extends z.AnyZodTuple, 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.AnyZodTuple, 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.AnyZodTuple, OUT extends z.AnyZodTuple, 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.AnyZodTuple, OUT extends z.AnyZodTuple | undefined = undefined, K extends keyof NS = RootNS>(def: ActionNoAckDef<IN, NS, K> | ActionWithAckDef<IN, NonNullable<OUT>, NS, K>): Action<NS, IN, OUT>;
}

declare abstract class AbstractAction {
    abstract getEvent(): string;
    abstract getNamespace(): PropertyKey;
    abstract execute(params: {
        params: unknown[];
    } & ClientContext<EmissionMap, z.SomeZodObject>): Promise<void>;
    abstract getSchema(variant: "input"): z.AnyZodTuple;
    abstract getSchema(variant: "output"): z.AnyZodTuple | undefined;
    abstract example(variant: "input" | "output", payload: z.infer<z.AnyZodTuple>): this;
    abstract getExamples(variant: "input" | "output"): z.infer<z.AnyZodTuple>[];
}
declare class Action<NS extends Namespaces, IN extends z.AnyZodTuple, OUT extends z.AnyZodTuple | undefined = undefined> extends AbstractAction {
    #private;
    constructor(action: ActionWithAckDef<IN, NonNullable<OUT>, NS, keyof NS> | ActionNoAckDef<IN, NS, keyof NS>);
    getEvent(): string;
    getNamespace(): keyof NS;
    getSchema(variant: "input"): IN;
    getSchema(variant: "output"): OUT;
    execute({ params, logger, ...rest }: {
        params: unknown[];
    } & ClientContext<EmissionMap, z.SomeZodObject>): Promise<void>;
    example(variant: "input", payload: z.input<IN>): this;
    example(variant: "output", payload: OUT extends z.AnyZodTuple ? z.output<OUT> : never): this;
    getExamples(variant: "input"): z.input<IN>[];
    getExamples(variant: "output"): OUT extends z.AnyZodTuple ? z.output<OUT>[] : never;
}

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>;

interface IntegrationProps {
    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;
    /**
     * @deprecated unused
     * @todo remove in next major
     * */
    serializer?: (schema: z.ZodTypeAny) => string;
    /**
     * @desc configures the style of object's optional properties
     * @default { withQuestionMark: true, withUndefined: true }
     */
    optionalPropStyle?: {
        /**
         * @desc add question mark to the optional property definition
         * @example { someProp?: boolean }
         * */
        withQuestionMark?: boolean;
        /**
         * @desc add undefined to the property union type
         * @example { someProp: boolean | undefined }
         */
        withUndefined?: boolean;
    };
}
declare const registryScopes: string[];
declare class Integration {
    protected program: ts.Node[];
    protected aliases: Record<string, // namespace
    Map<z.ZodTypeAny, ts.TypeAliasDeclaration>>;
    protected ids: {
        path: ts.Identifier;
        socket: ts.Identifier;
        socketBase: ts.Identifier;
        ioClient: ts.StringLiteral;
        emission: ts.Identifier;
        actions: ts.Identifier;
    };
    protected registry: Record<string, // namespace
    Record<(typeof registryScopes)[number], {
        event: string;
        node: ts.TypeNode;
    }[]>>;
    protected makeAlias(ns: string, schema: z.ZodTypeAny, produce: () => ts.TypeNode): ts.TypeReferenceNode;
    constructor({ config: { namespaces }, actions, optionalPropStyle, maxOverloads, }: IntegrationProps);
    print(printerOptions?: ts.PrinterOptions): string;
}

/** @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 {
    }
}

/**
 * @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>;
    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?: Record<string, 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;
}

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, scheme: SecuritySchemeObject): this;
    getSpec(): AsyncApiObject;
    getSpecAsJson(replacer?: (key: string, value: unknown) => unknown, space?: string | number): string;
    getSpecAsYaml(): string;
}

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 {
    #private;
    constructor({ actions, config: { namespaces, security: globalSecurity }, title, version, documentId, description, contact, license, servers, }: DocumentationParams);
}

/** @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 originalError: ZodError;
    name: string;
    constructor(originalError: ZodError);
}
/** @desc An error of validating the outgoing data */
declare class OutputValidationError extends IOSchemaError {
    readonly originalError: ZodError;
    name: string;
    constructor(originalError: ZodError);
}

export { AbstractAction, type AbstractLogger, ActionsFactory, type ClientContext, Config, Documentation, type EmissionMap, InputValidationError, Integration, type LoggerOverrides, type Namespace, OutputValidationError, attachSockets, createSimpleConfig };
