import * as pino from 'pino';
import { Logger, ChildLoggerOptions, Bindings } from 'pino';
export { Bindings, ChildLoggerOptions, Logger } from 'pino';
import { Application, RouterOptions, IRouter, Request as Request$1, RequestHandler } from 'express';
export { IRouter, NextFunction, RequestHandler, Response, RouterOptions } from 'express';
import { HttpTerminator } from 'http-terminator';
import { TypedEmitter } from 'tiny-typed-emitter';
import * as Sentry from '@sentry/node';

type CloudRunServiceOptions = {
    router: Application;
    logger: Logger;
    port: number;
    name: string;
    instanceId: string;
    useSentry?: boolean;
};
interface CloudRunServiceEvents {
    shutdown: () => void;
}
declare class CloudRunService extends TypedEmitter<CloudRunServiceEvents> {
    readonly name: string;
    readonly instanceId: string;
    readonly router: Application;
    readonly port: number;
    readonly logger: Logger;
    private readonly useSentry?;
    protected httpTerminator?: HttpTerminator;
    private state;
    constructor({ router, logger, port, name, instanceId, useSentry }: CloudRunServiceOptions);
    start(): Promise<void>;
    stop(): Promise<void>;
}

type SentryOptions = Sentry.NodeOptions;

interface CreateServiceOptions {
    /**
     * The port to listen on. Defaults to the PORT environment variable, or 8080.
     */
    port?: number;
    /**
     * The Google Cloud project ID. Used in logs to connect logs to traces.
     */
    projectId?: string;
    /**
     * Options to be passed to the root Pino logger.
     */
    logOptions?: ChildLoggerOptions;
    /**
     * Additional bindings to be added to the root Pino logger.
     */
    logBindings?: Bindings;
    /**
     * Whether to parse incoming request bodies using
     * [body-parser](https://www.npmjs.com/package/body-parser). Defaults to true.
     */
    parseBody?: boolean;
    /**
     * Maximum incoming request body size. Defaults to "512mb". Only used if
     * `parseBody` is true.
     */
    requestLimit?: string;
    /**
     * Sentry options. If set, Sentry will be configured for error reporting and tracing.
     */
    sentry?: SentryOptions;
    /**
     * Whether the service should handle automatically handle process events
     * (SIGTERM, SIGINT, uncaughtException). Defaults to true, but can be disabled
     * if more fine-grained process control is needed.
     */
    handleProcessEvents?: boolean;
    /**
     * Socket timeout in milliseconds (default: none).
     */
    timeoutMsecs?: number;
}
declare const createService: (name: string, options?: CreateServiceOptions) => CloudRunService;

declare const createRouter: (options?: RouterOptions) => IRouter;

declare enum HttpCode {
    OK = 200,
    ACCEPTED = 202,
    NO_CONTENT = 204,
    BAD_REQUEST = 400,
    UNAUTHORIZED = 401,
    NOT_FOUND = 404,
    REQUEST_TIMEOUT = 408,
    INTERNAL_SERVER_ERROR = 500,
    SERVICE_UNAVAILABLE = 503
}
type AppErrorOptions = ErrorOptions & {
    httpCode?: HttpCode;
    isOperational?: boolean;
};
declare class AppError extends Error {
    /**
     * HTTP code to be used when responding to the client.
     */
    readonly httpCode: HttpCode;
    /**
     * Whether the error is operational, i.e. whether it is safe to return the error message to the client.
     */
    readonly isOperational: boolean;
    constructor(message: string, options?: AppErrorOptions);
}
type ErrorDetail = {
    code: string;
    message?: string;
};
declare class ClientRequestError extends AppError {
    /**
     * Request body that caused the error
     */
    request?: unknown;
    /**
     * List of validation issues
     */
    details?: ErrorDetail[];
    constructor(message: string, args?: AppErrorOptions & {
        request?: unknown;
        details?: ErrorDetail[];
    });
}
declare class Unauthorized extends AppError {
    constructor(message: string, args?: AppErrorOptions);
}
declare const isAppError: (error: unknown) => error is AppError;

declare function assertIsError(error: unknown): asserts error is Error;

declare function parsePubSubMessage(req: Request$1): PubSubMessage;
type PubSubMessage = {
    data: string;
    metadata: {
        deliveryAttempt?: number;
        messageId: string;
        publishTime?: string;
        attributes?: Record<string, unknown>;
        orderingKey?: string;
    };
};

declare const logLevels: readonly ["fatal", "error", "warn", "info", "debug", "trace", "silent"];
type LogLevel = (typeof logLevels)[number];
/**
 * Pino logger that formats logs as JSON for ingest by Cloud Logging when running in GCP Cloud Run,
 * and uses pino-pretty for human readability otherwise.
 */
declare const logger: pino.Logger<never, boolean>;

declare global {
    namespace Express {
        interface Request {
            log: Logger;
        }
    }
}
type LoggerProps = {
    projectId?: string;
    bindings?: Bindings;
    options?: ChildLoggerOptions;
};
declare const createPinoLoggerMiddleware: ({ projectId, options, bindings }: LoggerProps) => RequestHandler;
interface Request extends Request$1 {
    /**
     * Pino Logger configured for Google Cloud Logging
     */
    log: Logger;
}

declare function parseTraceparent(traceparent: string | undefined): {
    traceId: string | undefined;
    spanId: string | undefined;
};

/**
 * Get the client IP address when behind a GCP load balancer.
 *
 * When behind a load blancer, the client IP address is the penultimate element in the
 * comma separated x-forwarded-for header.
 * Ref: https://cloud.google.com/load-balancing/docs/https#x-forwarded-for_header
 */
declare const getClientIpAddress: (req: Request$1) => string | undefined;

declare const isCloudRunEnvironment: () => boolean;

export { AppError, ClientRequestError, CloudRunService, type CreateServiceOptions, HttpCode, type LogLevel, type PubSubMessage, type Request, type SentryOptions, Unauthorized, assertIsError, createPinoLoggerMiddleware, createRouter, createService, getClientIpAddress, isAppError, isCloudRunEnvironment, logger, parsePubSubMessage, parseTraceparent };
