/// <reference types="node" />
import { Job, JobDTO } from "./job";
import * as z from "zod";
import fetch from "cross-fetch";
import type { IncomingHttpHeaders } from "http";
export { Job };
export interface JobMeta extends Pick<JobDTO, "id" | "count" | "exclusive" | "retry"> {
    /**
     * If this is a repeated job, the next repetition will be scheduled for this Date.
     */
    readonly nextRepetition?: Date;
}
export declare type QuirrelLogger<Payload = unknown> = {
    receivedJob: (route: string, data: Payload) => void;
    processingError: (route: string, data: Payload, error: unknown) => void;
};
export declare type QuirrelJobHandler<T> = (job: T, meta: JobMeta) => Promise<void>;
export declare type DefaultJobOptions = Pick<EnqueueJobOptions, "exclusive" | "retry">;
interface CreateQuirrelClientArgs<T> {
    route: string;
    handler: QuirrelJobHandler<T>;
    options?: QuirrelOptions<T>;
    config?: {
        /**
         * Recommended way to set this: process.env.QUIRREL_BASE_URL
         */
        applicationBaseUrl?: string;
        /**
         * Overrides URL of the Quirrel Endpoint.
         * @default https://api.quirrel.dev or http://localhost:9181
         * Recommended way to set this: process.env.QUIRREL_API_URL
         */
        quirrelBaseUrl?: string;
        /**
         * Same as quirrelBaseUrl, for migrating.
         */
        quirrelOldBaseUrl?: string;
        /**
         * Bearer Secret for authenticating with Quirrel.
         * Obtain on quirrel.dev or using the API of a self-hosted instance.
         * Recommended way to set this: process.env.QUIRREL_TOKEN
         */
        token?: string;
        /**
         *  Same as token, for migrating.
         */
        oldToken?: string;
        /**
         * Secret used for end-to-end encryption.
         * Needs to be 32 characters long.
         * Recommended way to set this: process.env.QUIRREL_ENCRYPTION_SECRET
         */
        encryptionSecret?: string;
        /**
         * Public key used for verifying signatures.
         * Recommended way to set this: process.env.QUIRREL_SIGNATURE_PUBLIC_KEY
         */
        signaturePublicKey?: string;
        /**
         * Old Secrets that have been rotated out.
         * @see https://docs.quirrel.dev/docs/faq#my-encryption-secret-has-been-leaked-what-now
         * Recommended way to set this: process.env.QUIRREL_OLD_SECRETS
         */
        oldSecrets?: string[];
    };
    fetch?: typeof fetch;
    catchDecryptionErrors?(error: unknown): void;
}
export declare const cronExpression: z.ZodEffects<z.ZodString, string, string>;
export declare const timezone: z.ZodEffects<z.ZodString, string, string>;
export declare const cron: z.ZodUnion<[z.ZodEffects<z.ZodString, string, string>, z.ZodTuple<[z.ZodEffects<z.ZodString, string, string>, z.ZodEffects<z.ZodString, string, string>], null>]>;
/**
 * @deprecated renamed to EnqueueJobOptions
 */
export declare type EnqueueJobOpts = EnqueueJobOptions;
export interface EnqueueJobOptions {
    /**
     * Can be used to make a job easier to manage.
     * If there's already a job with the same ID, this job will be trashed.
     */
    id?: string;
    /**
     * If set to `true`,
     * no other job (on the same queue)
     * will be executed at the same time.
     */
    exclusive?: boolean;
    /**
     * If a job fails, retry it at along the specified intervals.
     * @example ["5min", "1h", "1d"] // retries it after 5 minutes, 1:05 hours, and 1 day 1:05 hours
     */
    retry?: (number | string)[];
    /**
     * Determines what to do when a job
     * with the same ID already exists.
     * false: do nothing (default)
     * true: replace the job
     */
    override?: boolean;
    /**
     * Will delay the job's execution by the specified amount of milliseconds.
     * Supports human-readable notation as of @see https://github.com/vercel/ms.
     * If used together with `repeat`, this will delay the first job to be executed.
     */
    delay?: number | string;
    /**
     * Schedules the job for execution at the specified timestamp.
     */
    runAt?: Date;
    repeat?: {
        /**
         * Will make the job repeat every X milliseconds.
         * Supports human-readable notation as of @see https://github.com/vercel/ms.
         * If `delay` isn't set, the first repetition will be executed immediately.
         */
        every?: number | string;
        /**
         * Can be used in conjunction with @field every and @field cron
         * to limit the number of executions.
         */
        times?: number;
        /**
         * Schedules the job according to the Cron expression.
         * @see https://github.com/harrisiirak/cron-parser for supported syntax
         * If `delay` isn't set, the first repetition will be executed immediately.
         *
         * To specify the timezone, pass a tuple with the IANA timezone in second place.
         * Defaults to Etc/UTC.
         */
        cron?: string | [expression: string, timezone: string];
    };
}
export interface QuirrelOptions<T = unknown> extends DefaultJobOptions {
    logger?: QuirrelLogger<T>;
}
export declare class QuirrelClient<T> {
    private handler;
    private route;
    private defaultJobOptions;
    private encryptor;
    private defaultHeaders;
    private oldDefaultHeaders;
    private quirrelBaseUrl;
    private quirrelOldBaseUrl;
    private quirrelOldToken;
    private applicationBaseUrl;
    private token;
    private fetch;
    private catchDecryptionErrors;
    private signaturePublicKey;
    private logger;
    constructor(args: CreateQuirrelClientArgs<T>);
    private get baseUrl();
    private get oldBaseUrl();
    makeRequest(uri: string, init?: RequestInit): Promise<Response>;
    private payloadAndOptionsToBody;
    /**
     * Enqueue a job to the specified endpoint.
     * @param options job options
     */
    enqueue(payload: T, options?: EnqueueJobOptions): Promise<Job<T>>;
    /**
     * Enqueue multiple jobs
     */
    enqueueMany(jobs: {
        payload: T;
        options?: EnqueueJobOptions;
    }[]): Promise<Job<T>[]>;
    private decryptAndDecodeBody;
    private toJob;
    /**
     * Iterate through scheduled jobs.
     * @example
     * for await (const jobs of queue.get()) {
     *   // do smth
     * }
     */
    get(): AsyncGenerator<Job<T>[]>;
    private fetchAgainstCurrent;
    private fetchAgainstOld;
    private fetchAndRetryNotFound;
    /**
     * Get a specific job.
     * @returns null if no job was found.
     */
    getById(id: string): Promise<Job<T> | null>;
    /**
     * Schedule a job for immediate execution.
     * @returns false if job could not be found.
     */
    invoke(id: string): Promise<boolean>;
    /**
     * Delete a job, preventing it from executing.
     * @returns false if job could not be found.
     */
    delete(id: string): Promise<boolean>;
    private isValidSignature;
    respondTo(body: string, headers: IncomingHttpHeaders): Promise<{
        status: number;
        headers: Record<string, string>;
        body: string;
    }>;
}
