import { Deferred } from "./util";
import { Msg, MsgHdrs, Nanos, NatsConnection, NatsError, PublishOptions, Sub } from "./types";
import { QueuedIterator, QueuedIteratorImpl } from "./queued_iterator";
/**
 * Services have common backplane subject pattern:
 *
 * `$SRV.PING|STATS|INFO|SCHEMA` - pings or retrieves status for all services
 * `$SRV.PING|STATS|INFO|SCHEMA.<name>` - pings or retrieves status for all services having the specified name
 * `$SRV.PING|STATS|INFO|SCHEMA.<name>.<id>` - pings or retrieves status of a particular service
 *
 * Note that <name> and <id> are upper-cased.
 */
export declare const ServiceApiPrefix = "$SRV";
export declare const ServiceErrorHeader = "Nats-Service-Error";
export declare const ServiceErrorCodeHeader = "Nats-Service-Error-Code";
export declare enum ServiceVerb {
    PING = "PING",
    STATS = "STATS",
    INFO = "INFO",
    SCHEMA = "SCHEMA"
}
export interface ServiceIdentity {
    /**
     * The kind of the service reporting the stats
     */
    name: string;
    /**
     * The unique ID of the service reporting the stats
     */
    id: string;
    /**
     * A version for the service
     */
    version: string;
}
export interface ServiceMsg extends Msg {
    respondError(code: number, description: string, data?: Uint8Array, opts?: PublishOptions): boolean;
}
export declare class ServiceMsgImpl implements ServiceMsg {
    msg: Msg;
    constructor(msg: Msg);
    get data(): Uint8Array;
    get sid(): number;
    get subject(): string;
    respond(data?: Uint8Array, opts?: PublishOptions): boolean;
    respondError(code: number, description: string, data?: Uint8Array, opts?: PublishOptions): boolean;
}
export interface Service extends QueuedIterator<ServiceMsg> {
    /**
     * A promise that gets resolved to null or Error once the service ends.
     * If an error, then service exited because of an error.
     */
    stopped: Promise<null | Error>;
    /**
     * True if the service is stopped
     */
    isStopped: boolean;
    /**
     * Returns the stats for the service.
     */
    stats(): Promise<ServiceStats>;
    /**
     * Returns a service info for the service
     */
    info(): ServiceInfo;
    /**
     * Resets all the stats
     */
    reset(): void;
    /**
     * Stop the service returning a promise once the service completes.
     * If the service was stopped due to an error, that promise resolves to
     * the specified error
     */
    stop(err?: Error): Promise<null | Error>;
}
/**
 * Statistics for an endpoint
 */
export type EndpointStats = ServiceIdentity & {
    /**
     * The number of requests received by the endpoint
     */
    num_requests: number;
    /**
     * Number of errors that the endpoint has raised
     */
    num_errors: number;
    /**
     * If set, the last error triggered by the endpoint
     */
    last_error?: string;
    /**
     * A field that can be customized with any data as returned by stats handler see {@link ServiceConfig}
     */
    data?: unknown;
    /**
     * Total processing_time for the service
     */
    processing_time: Nanos;
    /**
     * Average processing_time is the total processing_time divided by the num_requests
     */
    average_processing_time: Nanos;
    /**
     * ISO Date string when the service started
     */
    started: string;
};
export type ServiceSchema = ServiceIdentity & {
    schema: SchemaInfo;
};
export type SchemaInfo = {
    request: string;
    response: string;
};
export type ServiceInfo = ServiceIdentity & {
    /**
     * Description for the service
     */
    description: string;
    /**
     * Subject where the service can be invoked
     */
    subject: string;
};
export type ServiceConfig = {
    /**
     * A type for a service
     */
    name: string;
    /**
     * A version identifier for the service
     */
    version: string;
    /**
     * Description for the service
     */
    description?: string;
    /**
     * Schema for the service
     */
    schema?: SchemaInfo;
    /**
     * A list of endpoints, typically one, but some services may
     * want more than one endpoint
     */
    endpoint: Endpoint;
    /**
     * A customized handler for the stats of an endpoint. The
     * data returned by the endpoint will be serialized as is
     * @param endpoint
     */
    statsHandler?: (endpoint: Endpoint) => Promise<unknown | null>;
};
/**
 * A service Endpoint
 */
export type Endpoint = {
    /**
     * Subject where the endpoint is listening
     */
    subject: string;
    /**
     * Handler for the endpoint - if not set the service is an iterator
     * @param err
     * @param msg
     */
    handler?: (err: NatsError | null, msg: ServiceMsg) => void;
};
/**
 * The stats of a service
 */
export type ServiceStats = ServiceIdentity & EndpointStats;
type ServiceSubscription<T = unknown> = Endpoint & {
    internal: boolean;
    sub: Sub<T>;
};
export declare class ServiceError extends Error {
    code: number;
    constructor(code: number, message: string);
    static isServiceError(msg: Msg): boolean;
    static toServiceError(msg: Msg): ServiceError | null;
}
export declare class ServiceImpl extends QueuedIteratorImpl<ServiceMsg> implements Service {
    nc: NatsConnection;
    _id: string;
    config: ServiceConfig;
    handler: ServiceSubscription;
    internal: ServiceSubscription[];
    _stopped: boolean;
    _done: Deferred<Error | null>;
    _stats: EndpointStats;
    _lastException?: Error;
    _schema?: Uint8Array;
    /**
     * @param verb
     * @param name
     * @param id
     * @param prefix - this is only supplied by tooling when building control subject that crosses an account
     */
    static controlSubject(verb: ServiceVerb, name?: string, id?: string, prefix?: string): string;
    constructor(nc: NatsConnection, config: ServiceConfig);
    get subject(): string;
    get id(): string;
    get name(): string;
    get description(): string;
    get version(): string;
    errorToHeader(err: Error): MsgHdrs;
    countError(err: Error): void;
    setupNATS(h: Endpoint, internal?: boolean): void;
    info(): ServiceInfo;
    stats(): Promise<ServiceStats>;
    addInternalHandler(verb: ServiceVerb, handler: (err: NatsError | null, msg: Msg) => Promise<void>): void;
    _doAddInternalHandler(name: string, verb: ServiceVerb, handler: (err: NatsError | null, msg: Msg) => Promise<void>, kind?: string, id?: string): void;
    start(): Promise<Service>;
    close(err?: Error): Promise<null | Error>;
    get stopped(): Promise<null | Error>;
    get isStopped(): boolean;
    stop(err?: Error): Promise<null | Error>;
    get schema(): Uint8Array;
    reset(): void;
}
export {};
