/**
 * 清除全局 scope 注册表（用于测试）
 */
declare const clearPendingRegistry: () => void;
/**
 * Scope 冲突错误
 */
declare class PendingScopeConflictError extends Error {
    readonly scope: string;
    constructor(scope: string);
}
/**
 * pendingFn 回调函数接收的参数
 */
type PendingFnParams = {
    /** 解析后的 scope key */
    scope: string;
    /** 获取当前等待中的 caller 数量（实时值） */
    getPendingCount: () => number;
};
/**
 * pendingFn 的回调函数类型
 */
type PendingCallbackFn<T, Args extends unknown[]> = (params: PendingFnParams, ...args: Args) => T;
/**
 * 感知 pending 状态的 inflight 去重
 *
 * fn 的第一个参数为 PendingFnParams，包含 scope 和 getPendingCount，
 * 允许根据 pending 状态做自定义处理（如短路检查、日志等）。
 * 返回的函数剥掉 PendingFnParams，只暴露业务参数。
 *
 * @param scope 静态 scope 字符串，或基于参数动态生成 scope 的函数
 * @param fn 接收 PendingFnParams 的回调函数
 * @returns 只保留业务参数的包装函数
 *
 * @example
 * ```ts
 * const mountScript = pendingFn(
 *   (url: string) => `script:${url}`,
 *   ({ scope, getPendingCount }, url: string) => {
 *     // 短路：已挂载
 *     const existing = document.getElementById(scope);
 *     if (existing) return { element: existing };
 *
 *     // 实际挂载，执行期间 getPendingCount() 可获取等待数
 *     return loadScript(url);
 *   },
 * );
 *
 * // 并发调用，只执行一次挂载
 * await Promise.all([mountScript('/lib.js'), mountScript('/lib.js')]);
 * ```
 */
declare const pendingFn: <T, Args extends unknown[]>(scope: string | ((...args: Args) => string), fn: PendingCallbackFn<T, Args>) => ((...args: Args) => Promise<Awaited<T>>);
/**
 * 基于 scope 的 inflight 去重
 *
 * 同一 scope 下并发调用只执行一次 fn，所有 callers 共享同一个 Promise 结果。
 * 执行完毕后 scope 释放，下一次调用开启新的执行周期。
 *
 * @param scope 静态 scope 字符串，或基于参数动态生成 scope 的函数
 * @param fn 要包装的函数（同步或异步）
 * @returns 包装后的去重函数
 *
 * @example 静态 scope
 * ```ts
 * const fetchConfig = pending('config', () => fetch('/api/config').then(r => r.json()));
 *
 * // 并发调用 3 次，只执行 1 次 fetch
 * const [a, b, c] = await Promise.all([fetchConfig(), fetchConfig(), fetchConfig()]);
 * // a === b === c
 * ```
 *
 * @example 动态 scope
 * ```ts
 * const fetchUser = pending(
 *   (id: string) => `user:${id}`,
 *   (id: string) => fetch(`/api/user/${id}`).then(r => r.json()),
 * );
 *
 * // 相同 id 去重，不同 id 独立执行
 * await Promise.all([fetchUser('1'), fetchUser('1'), fetchUser('2')]);
 * // fetchUser('1') 只执行一次，fetchUser('2') 独立执行一次
 * ```
 */
declare const pending: <F extends AnyFn>(scope: string | ((...args: Parameters<F>) => string), fn: F) => ((...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>>);

/**
 * 异步工具模块
 */

type AnyFn = (...args: any[]) => any;
/**
 * 重试回调参数
 */
type RetryFnParams = {
    /** 当前尝试次数（从 1 开始） */
    attempt: number;
    /** 触发重试的错误（首次执行时为 undefined） */
    error: unknown;
    /** 只读的重试选项 */
    readonly options: RetryOptions;
};
/**
 * 重试选项
 */
type RetryOptions = {
    /** 最大尝试次数，默认 3 */
    attempts?: number;
    /** 重试间隔（毫秒），支持固定值或基于 RetryFnParams 的动态计算 */
    delay?: number | ((params: RetryFnParams) => number);
    /** 重试前的回调，可用于日志记录 */
    onRetry?: (params: RetryFnParams) => void;
};
/**
 * retryFn 的回调函数类型
 */
type RetryCallbackFn<T, Args extends unknown[]> = (params: RetryFnParams, ...args: Args) => T;
/**
 * 重试耗尽错误
 *
 * 当异步操作在达到最大重试次数后仍然失败时抛出
 */
declare class RetryExhaustedError extends Error {
    readonly attempt: number;
    readonly error: unknown;
    readonly options: RetryOptions;
    constructor(params: RetryFnParams);
}
/**
 * 超时错误
 *
 * 当异步操作超过指定时间仍未完成时抛出
 */
declare class TimeoutError extends Error {
    readonly ms: number;
    /**
     * @param ms 超时毫秒数
     */
    constructor(ms: number);
}
/**
 * 透明包装异步/同步函数，返回自动重试的版本
 *
 * 返回的函数保持原函数的参数签名，返回值统一为 Promise
 *
 * @param fn 要包装的函数（同步或异步）
 * @param options 重试选项
 * @returns 包装后的函数
 *
 * @example
 * ```ts
 * const fetchUserWithRetry = retry(
 *   (id: string) => fetch(`/api/user/${id}`).then(r => r.json()),
 *   { attempts: 3, delay: 1000 },
 * );
 *
 * const user = await fetchUserWithRetry('123');
 * ```
 *
 * @example 指数退避
 * ```ts
 * const fetchWithBackoff = retry(fetchData, {
 *   attempts: 5,
 *   delay: ({ attempt }) => Math.min(1000 * 2 ** (attempt - 1), 30000),
 * });
 * ```
 */
declare const retry: <F extends AnyFn>(fn: F, options?: RetryOptions) => ((...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>>);
/**
 * 创建感知重试状态的函数
 *
 * fn 的第一个参数为 RetryFnParams，包含 attempt 和 options，
 * 允许根据重试次数做差异化处理。返回的函数剥掉 RetryFnParams，
 * 只暴露业务参数。
 *
 * @param fn 接收 RetryFnParams 的回调函数
 * @param options 重试选项
 * @returns 只保留业务参数的包装函数
 *
 * @example
 * ```ts
 * const fetchWithFallback = retryFn(
 *   ({ attempt }, id: string) => {
 *     const url = attempt === 1 ? '/api/primary' : '/api/fallback';
 *     return fetch(`${url}/${id}`).then(r => r.json());
 *   },
 *   { attempts: 3 },
 * );
 *
 * const data = await fetchWithFallback('123');
 * ```
 */
declare const retryFn: <T, Args extends unknown[]>(fn: RetryCallbackFn<T, Args>, options?: RetryOptions) => ((...args: Args) => Promise<Awaited<T>>);
/**
 * 包装函数，添加超时控制
 *
 * 返回的函数保持原函数的参数签名，返回值统一为 Promise。
 * 如果执行超过指定时间，将抛出 TimeoutError。
 *
 * @param fn 要包装的函数（同步或异步）
 * @param ms 超时毫秒数
 * @returns 包装后的函数
 *
 * @example
 * ```ts
 * const fetchWithTimeout = timeout(
 *   (url: string) => fetch(url).then(r => r.json()),
 *   5000,
 * );
 *
 * const data = await fetchWithTimeout('/api/data');
 * ```
 */
declare const timeout: <F extends AnyFn>(fn: F, ms: number) => ((...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>>);
/**
 * 延迟指定毫秒数，可选延迟后执行函数
 *
 * @param ms 延迟毫秒数
 * @param fn 延迟后执行的函数（可选）
 * @returns 无 fn 时返回 Promise<void>，有 fn 时返回 Promise<Awaited<ReturnType<F>>>
 *
 * @example
 * ```ts
 * // 纯等待
 * await sleep(1000);
 *
 * // 延迟后执行
 * const data = await sleep(1000, () => fetchData());
 * ```
 */
declare function sleep(ms: number): Promise<void>;
declare function sleep<F extends AnyFn>(ms: number, fn: F): Promise<Awaited<ReturnType<F>>>;

/**
 * Type Guards 和基础类型工具模块
 */
/**
 * 判定 val 是否为字符串类型（含 infer）
 *
 * @see https://stackoverflow.com/questions/4059147/check-if-a-variable-is-a-string-in-javascript
 * @param val
 */
declare const isStr: (val: unknown) => val is string;
/**
 * 检查 val 是否为非空字符串（含 infer）
 *
 * @param val
 */
declare const notEmptyStr: (val: unknown) => val is string;
/**
 * 判断是否为有效的数字类型
 *
 * @param val
 */
declare const isNumber: (val: unknown) => val is number;
/**
 * 判断是否包含有效的数值
 *
 * - 允许字符串包含数值，如 `"123"`
 * - 允许数字类型，如 `123`
 *
 * @param val
 */
declare const isNumberVal: (val: unknown) => boolean;
/**
 * 将包含有效数值的 val 转换为对应的数字类型，只支持以下情形：
 *
 * - 字符串包含数值，如 `"123"`，转换为 `123`
 * - 数字类型，如 `123`，转换为 `123`
 * - 布尔类型，如 `true`，转换为 `1`，`false` 转换为 `0`
 *
 * @param val
 * @param dft 默认值，仅当 val 为 `null` 或 `undefined` 或 非包含有效数值时生效
 */
declare const toNumber: (val: unknown, dft?: number) => number;
/**
 * 限制 val 在最小值范围内
 *
 * @param val
 * @param {number} min 最小值
 * @param {number} dft 默认值，仅当 val 为 `null` 或 `undefined` 或 非包含有效数值时生效
 */
declare const limitNumberMin: (val: unknown, min: number, dft?: number) => number;
/**
 * 限制 val 在最大值范围内
 * @param val
 * @param max 最大值
 * @param dft 默认值，仅当 val 为 `null` 或 `undefined` 或 非包含有效数值时生效
 */
declare const limitNumberMax: (val: unknown, max: number, dft?: number) => number;
/**
 * 限制 val 在最小值和最大值范围内
 * @param val
 * @param min 最小值
 * @param max 最大值
 * @param dft 默认值，仅当 val 为 `null` 或 `undefined` 或 非包含有效数值时生效
 */
declare const limitNumberMinMax: (val: unknown, min: number, max: number, dft?: number) => number;
/**
 * 数字精度调整，支持 `round`、`ceil`、`floor` 三种类型
 *
 * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/round#%E5%B0%8F%E6%95%B0%E8%88%8D%E5%85%A5
 * @param {"round" | "ceil" | "floor"} type 调整类型
 * @param {number} value
 * @param {number} exp 指数（10的 exp 次方 —— 10 进制位数，0 表示个位，1 表示十位，-1 表示小数点后一位，-2 表示小数点后两位，以此类推）。
 * @returns {number}
 */
declare const decimalAdjust: (type: "round" | "ceil" | "floor", value: number, exp?: number) => number;
declare const round10: (value: number, exp?: number) => number;
declare const floor10: (value: number, exp?: number) => number;
declare const ceil10: (value: number, exp?: number) => number;
/**
 * 计算进度值，返回的结果为一个浮点值，表示进度比例，取值在 0 - 1 之间。
 *
 * @param value
 * @param total
 */
declare const calcProgress: (value: number, total: number) => number;
type RecordObj = Record<string, unknown>;
/**
 * 检查 obj 是否为 Object，结果为真时，推导 obj 为 T 类型
 *
 * - 未指定泛型 T，则 T 默认为 `Record<string, unknown>`
 * - 如果指定泛型 T ，而未传入 fn ，只要 obj 是 Object 即推断 obj 为 T
 * ```ts
 * type TestA = {
 *   name?: string;
 * }
 *
 * if (isInferObj<TestA>(obj)) {
 *   // obj 推断为 TestA
 *   console.log(obj.name || 'noname');
 * }
 * ```
 * - 若果传入了 fn ，则先检查是否 Object，再附加 fn 结果进行推断
 * ```ts
 * type TestB = {
 *   name: string;
 * }
 *
 * if (isInferObj<TestB>(obj, it => typeof it.name === 'string')) {
 *   // obj 推断为 TestB
 *   console.log(obj.name);
 * }
 * ```
 * - 通过传入 `x is T` 的 fn ，可省略指定泛型 T（一般用于复杂的结构判定）
 * ```ts
 * // 由 fn 的结果推导 isInferObj 的 T
 * type WithVersion = {
 *  version: number;
 * };
 *
 * const isWithVersion = (it: WithVersion): it is WithVersion =>
 *   typeof it.version === 'number';
 *
 * const ver1 = { ver: 1 };
 * const ver2 = { version: 2 };
 *
 * if (isInferObj(ver1, isWithVersion)) {
 *   // 不符合
 * }
 *
 * if (isInferObj(ver2, isWithVersion)) {
 *   // ver2 推断为 Version
 *   ver2.version += 1;
 * }
 * ```
 *
 * @param obj 任意类型变量
 * @param fn 断言类型判断函数
 */
declare const isInferObj: <T = RecordObj>(obj: unknown, fn?: (it: T) => boolean) => obj is T;
/**
 * 可能是一个包含错误消息的结构
 */
type ErrLike = {
    message?: string;
    error?: string;
};
/**
 * 判断目标是否是 {@link ErrLike}
 *
 * @param err
 */
declare const isErrLike: (err: unknown) => err is ErrLike;
/**
 * 取回错误消息
 *
 * @param err
 */
declare const errMsg: (err: unknown) => string;
/**
 * 检查值是否为布尔值
 *
 * @param val 任意值
 *
 * @example
 * ```ts
 * if (isBool(value)) {
 *   console.log(value ? 'yes' : 'no');
 * }
 * ```
 */
declare const isBool: (val: unknown) => val is boolean;
/**
 * 检查值是否为 null
 *
 * @param val 任意值
 */
declare const isNull: (val: unknown) => val is null;
/**
 * 检查值是否为 undefined
 *
 * @param val 任意值
 */
declare const isUndefined: (val: unknown) => val is undefined;
/**
 * 检查值是否为 null 或 undefined
 *
 * @param val 任意值
 */
declare const isNil: (val: unknown) => val is null | undefined;
/**
 * 检查值是否不为 null 且不为 undefined
 *
 * @param val 任意值
 *
 * @example
 * ```ts
 * if (isPresent(value)) {
 *   console.log(value);
 * }
 * ```
 */
declare const isPresent: <T>(val: T | null | undefined) => val is T;
/**
 * 检查值是否为一个普通对象（不包括数组、Date、RegExp 等特殊对象）
 *
 * @param val 任意值
 *
 * @example
 * ```ts
 * if (isPlainObj(value)) {
 *   console.log(Object.keys(value));
 * }
 * ```
 */
declare const isPlainObj: <T extends Record<string, unknown> = Record<string, unknown>>(val: unknown) => val is T;
/**
 * 检查值是否为数组
 *
 * @param val 任意值
 */
declare const isAry: <T = unknown>(val: unknown) => val is T[];
/**
 * 检查值是否为非空数组，支持可选的元素类型守卫
 *
 * @param val 任意值
 * @param guard 可选的元素类型守卫
 *
 * @example
 * ```ts
 * if (notEmptyAry(value)) {
 *   console.log(value[0]); // value is unknown[]
 * }
 *
 * if (notEmptyAry(value, isStr)) {
 *   console.log(value[0].toUpperCase()); // value is string[]
 * }
 * ```
 */
declare function notEmptyAry<T = unknown>(val: unknown): val is T[];
declare function notEmptyAry<T>(val: unknown, guard: (item: unknown) => item is T): val is T[];
/**
 * 柯里化的数组类型守卫
 *
 * @param guard 元素类型守卫
 * @returns 数组类型守卫函数
 *
 * @example
 * ```ts
 * const isStrAry = aryGuard(isStr);
 *
 * if (isStrAry(value)) {
 *   // value is string[]
 * }
 *
 * // 配合 and 使用
 * const isNonEmptyStrAry = and(isStrAry, (arr) => arr.length > 0);
 * ```
 */
declare const aryGuard: <T>(guard: (item: unknown) => item is T) => TypeGuard<T[]>;
/**
 * 检查值是否为 Promise
 *
 * @param val 任意值
 *
 * @example
 * ```ts
 * if (isPromise(value)) {
 *   await value;
 * }
 * ```
 */
declare const isPromise: <T = unknown>(val: unknown) => val is Promise<T>;
/**
 * 类型守卫函数类型
 */
type TypeGuard<T = unknown> = (val: unknown) => val is T;
/**
 * 组合守卫（AND）
 *
 * 第一个守卫收窄类型到 T，后续守卫在 T 上做进一步筛选
 *
 * @param guards 第一个为类型守卫，后续为断言函数
 * @returns 组合后的守卫函数
 *
 * @example
 * ```ts
 * const isStrAry = aryGuard(isStr);
 * const isNonEmptyStrAry = and(isStrAry, (arr) => arr.length > 0);
 * ```
 */
declare const and: <T>(...guards: [(val: unknown) => val is T, ...((val: T) => boolean)[]]) => TypeGuard<T>;
/**
 * 从 TypeGuard 提取被守卫的类型
 */
type InferGuard<G> = G extends TypeGuard<infer T> ? T : never;
/**
 * 组合守卫（OR）
 *
 * 任意一个守卫通过即返回 true，自动推断联合类型
 *
 * @param guards 一个或多个守卫函数
 * @returns 组合后的守卫函数
 *
 * @example
 * ```ts
 * const isStrOrNum = or(isStr, isNumber);
 * if (isStrOrNum(value)) {
 *   // value: string | number
 * }
 * ```
 */
declare const or: <G extends [TypeGuard<any>, ...TypeGuard<any>[]]>(...guards: G) => TypeGuard<InferGuard<G[number]>>;
/**
 * 守卫取反（NOT）
 *
 * 返回运行时取反函数。由于 TS 类型系统不支持否定类型，
 * 返回值为 `(val: unknown) => boolean`，不作为类型守卫使用。
 *
 * @param guard 要取反的守卫函数
 * @returns 取反后的判断函数
 *
 * @example
 * ```ts
 * const isNotNull = not(isNull);
 * if (isNotNull(value)) {
 *   // 运行时正确，但不会收窄类型
 * }
 * ```
 */
declare const not: (guard: TypeGuard) => ((val: unknown) => boolean);

type DirectorySeparator = '/' | '\\';
type PathInput = string | undefined | null;
declare const UnixDS = "/";
declare const WinDS = "\\";
type PathReplacementCallback = (path: string, separator: string) => string;
type PathUtilsOptions = {
    separator: string;
    dangerReplace?: PathReplacementCallback;
    duplicateReplace?: PathReplacementCallback;
};
/**
 * 创建路径处理工具
 *
 * @param {PathUtilsOptions} options
 * @returns
 */
declare const createPathUtils: ({ separator: inputSeparator, dangerReplace, duplicateReplace, }: PathUtilsOptions) => {
    purgePath: (path: PathInput) => string;
    joinPath: (...paths: PathInput[]) => string;
};
declare const purgeHttpPath: (path: PathInput) => string;
declare const joinHttpPath: (...paths: PathInput[]) => string;

/**
 * 单个 Http Header 的数组类型
 *
 * ```ts
 * const header: HeaderAry = ['content-type', 'application/json'];
 * ```
 */
type AryHeaderItem = [string, string];
type HeadersInitInput = HeadersInit | undefined | null;
/**
 * 将任意 `HeadersInit` 转为多个 {@link AryHeaderItem} 的数组
 *
 * 浏览器环境或 bun 环境下，`HeadersInit` 类型如下：
 *
 * `type HeadersInit = [string, string][] | Record<string, string> | Headers;`
 *
 * 需要注意的是，在使用 `headers<Headers>.entries()` 时，Header 的 Key 会转为小写：
 *
 * ```ts
 * const h = new Headers();
 * h.set('Content-Type', 'application/json');
 * console.log([...h.keys()]); // 将输出 => ['content-type']
 * ```
 *
 * 所以，当输入的 `headers` 为 `[string, string][]` 或 `Record<string, string>` 类
 * 型时，应该确保 Key 为小写。即：
 *
 * ```ts
 * const h1 = [['content-Type', 'application/json']];
 * const h2 = { 'content-Type': 'application/json' };
 * ```
 *
 * @param headers
 * @returns {AryHeaderItem[]}
 */
declare const toAryHeaders: (headers?: HeadersInitInput) => AryHeaderItem[];
/**
 * 合并多个 {@link HeadersInitInput} 为 `Headers` 对象
 *
 * Key(Header name) 会进行 trim 操作：
 *
 * - Key(Header name) 头尾的空格（制表符、回车符）会被去除
 * - 当 Key(Header name) 为空字符（trim 后），将跳过该 Key
 *
 * 注意：当输入的 `headers` 为 `[string, string][]` 或 `Record<string, string>` 类
 * 型时，应该确保 Key(Header name) 为小写（以确保同 Key 的 Header 会被有效覆盖）。
 *
 * @param inputs 多个 {@link HeadersInitInput} 对象，Key(Header name) 应为小写（中划线）
 * @returns {Headers}
 */
declare const mergeHeaders: (...inputs: HeadersInitInput[]) => Headers;

/**
 * 合并多个 AbortSignals
 *
 * ```ts
 * const maybeSignal: AbortSignal | null = null;
 * mergeAbortSignals(new AbortController, AbortSignal.timeout(5000), maybeSignal);
 * // AbortSignal.any([new AbortController, AbortSignal.timeout(5000)])
 * ```
 *
 * @param signals
 * @returns {AbortSignal | undefined}
 */
declare const mergeAbortSignals: (...signals: (AbortSignal | undefined | null)[]) => AbortSignal | undefined;

type HttpStatusCode = number;
type ResponseInitInput = ResponseInit | HttpStatusCode | null | undefined;
/**
 * 合并多个 {@link ResponseInitInput} 为 `ResponseInit` 对象
 *
 * 主要针对：
 * - 允许传入 {@link HttpStatusCode} 作为 `ResponseInit`，即：`new Response(body, mergeRespInit(404))`
 * - 处理多个 `ResponseInit` 对象的 `headers` 合并
 * - 合并多个 `ResponseInit`
 *
 * ```ts
 * new Response(body,
 *   mergeRespInit(
 *     404,
 *     { headers: { 'x-a': '1' } },
 *     { headers: { 'x-b': '2', 'x-a': 'replaced' } },
 *     { status: 502, statusText: 'Bad Gateway' },
 *   )
 * );
 * ```
 *
 * @param opts
 * @returns
 */
declare const mergeRespInit: (...opts: ResponseInitInput[]) => ResponseInit;

declare class MountRemoteError extends Error {
    readonly prev?: unknown | undefined;
    constructor(message: string, prev?: unknown | undefined);
}
type MountRemoteResult<Result extends Record<string, unknown> = Record<string, unknown>> = {
    type: string;
    scope: string;
} & Result;
/**
 * Handler 上下文，继承 PendingFnParams
 */
type MountHandlerContext<Options extends Record<string, unknown> = Record<string, unknown>> = PendingFnParams & {
    type: string;
} & Options;
/**
 * DOM 类型 handler 的通用选项
 */
type MountDomOptions = {
    url: string;
    attrs?: Record<string, string>;
    onLoad?: (el: HTMLElement, res: MountRemoteResult<MountDomResult>) => void | Promise<void>;
    onError?: (err: unknown, ctx: MountHandlerContext<MountDomOptions>, opts: MountDomOptions) => void;
};
/**
 * DOM handler 的扩展返回字段（不含 MountRemoteResult 的基础字段）
 */
type MountDomResult = MountDomOptions & {
    id: string;
    el: HTMLElement;
};
/**
 * 类型安全的 handler 函数
 */
type MountHandlerFn<Options extends Record<string, unknown> = Record<string, unknown>, Result extends Record<string, unknown> = Record<string, unknown>> = (ctx: MountHandlerContext<Options>, opts: Options) => Promise<MountRemoteResult<Result>> | MountRemoteResult<Result>;
/**
 * Handler 类型映射表
 *
 * 通过 interface 声明合并扩展：
 * ```ts
 * declare module '@zenstone/ts-utils/remote' {
 *   interface MountHandlerMap {
 *     wasm: MountHandlerFn<{ url: string; importObject?: WebAssembly.Imports }>;
 *   }
 * }
 * ```
 */
interface MountHandlerMap {
    js: MountHandlerFn<MountDomOptions, MountDomResult>;
    css: MountHandlerFn<MountDomOptions, MountDomResult>;
    mjs: MountHandlerFn<MountDomOptions, MountDomResult>;
}
/**
 * 注册挂载类型处理器
 *
 * @param type 资源类型标识
 * @param handler 处理函数
 *
 * @example
 * ```ts
 * registerMountHandler('wasm', async (ctx, opts) => {
 *   const response = await fetch(opts.url);
 *   const module = await WebAssembly.instantiateStreaming(response, opts.importObject);
 *   return { type: ctx.type, scope: ctx.scope, url: opts.url, module };
 * });
 * ```
 */
declare const registerMountHandler: <K extends keyof MountHandlerMap>(type: K, handler: MountHandlerMap[K]) => void;
/**
 * 创建基于 DOM 元素的挂载处理器
 *
 * 适用于通过 script/link 等标签加载的资源。自动处理：
 * - `getElementById` 短路检查
 * - 创建元素并设置属性
 * - 设置 id（使用 scope）
 * - 监听 load/error 事件
 * - 挂载到 document.head
 *
 * @param tagName 标签名
 * @param setup 元素初始化函数
 *
 * @example
 * ```ts
 * registerMountHandler('img', createDomHandler('img', (el, ctx) => {
 *   el.setAttribute('src', ctx.url);
 * }));
 * ```
 */
declare const createDomHandler: (tagName: string, setup: (el: HTMLElement, ctx: MountHandlerContext<MountDomOptions>) => void) => MountHandlerFn<MountDomOptions, MountDomResult>;
/**
 * 挂载远程资源
 *
 * 基于 scope 做 inflight 去重：并发调用同 scope 只执行一次，结果共享。
 * Options 类型由 `type` 字段决定，通过 {@link MountHandlerMap} 接口扩展。
 *
 * 内置支持 `js`、`mjs`、`css` 三种类型，其他类型需通过
 * {@link registerMountHandler} 注册处理器。
 *
 * @param scope 去重标识，同时用作 DOM 元素 id（对于 DOM handler）
 * @param options 挂载选项，类型由 `type` 决定
 *
 * @example
 * ```ts
 * await mountRemote('jquery', {
 *   type: 'js',
 *   url: 'https://cdn.example.com/jquery.min.js',
 * });
 * ```
 *
 * @example 并发去重
 * ```ts
 * await Promise.all([
 *   mountRemote('lib', { type: 'js', url }),
 *   mountRemote('lib', { type: 'js', url }),
 * ]);
 * // 只加载一次
 * ```
 */
declare function mountRemote<K extends keyof MountHandlerMap>(scope: string, options: {
    type: K;
} & Parameters<MountHandlerMap[K]>[1]): Promise<MountRemoteResult>;
/**
 * 基于 id 移除已挂载的远程资源
 *
 * @param id 元素 ID
 * @param onRemove 移除后回调
 */
declare const unmountDomRemote: (id: string, onRemove?: () => void) => void;

type DownloadUrl = string | URL;
type DownloadRequest = {
    url: DownloadUrl;
} & RequestInit;
type DownloadInput = DownloadUrl | DownloadRequest | Request | Promise<Response>;
type DownloadFetchCallback = () => Promise<Response>;

declare class DownloadTaskError extends Error {
    readonly task: DownloadTask;
    constructor(msg: string, task: DownloadTask);
}
declare enum DownloadTaskState {
    error = -1,
    init = 0,
    fetching = 1,
    reading = 2,
    complete = 3
}
type DownloadTaskProcessCallback = (task: DownloadTask) => void | Promise<void>;
type DownloadTaskProcessOptions = {
    onFetch?: DownloadTaskProcessCallback;
    onHeaders?: DownloadTaskProcessCallback;
    onProgress?: DownloadTaskProcessCallback;
    onComplete?: DownloadTaskProcessCallback;
    onError?: DownloadTaskProcessCallback;
};
declare class DownloadTask {
    #private;
    /**
     * 创建 {@link DownloadTask} 实例，允许多种 input 类型
     *
     * ```ts
     * // URL 输入
     * const task1 = new DownloadTask('url');
     * const task2 = new DownloadTask(new URL('url'));
     *
     * // Request or DownloadRequest 结构
     * const task3 = new DownloadTask(new Request('url'));
     * const task4 = new DownloadTask({ url: 'url' });
     *
     * // Promise<Response>
     * const abort = new AbortController();
     * const task5 = new DownloadTask(fetch('url', { signal: abort.signal }));
     *
     * // Response
     * const task6 = new DownloadTask(await fetch('url'));
     * ```
     *
     * 下载的目标 url ，必须要输出有效的 `content-length`，否则将会抛出异常
     *
     * @param input
     */
    constructor(input: DownloadInput | Response);
    protected _initFetch: (input: DownloadInput) => void;
    /**
     * {@link DownloadTask} Id
     *
     * 用于给 {@link DownloadTask} 的 Key 使用
     */
    get id(): string;
    /**
     * 获取 response
     */
    get resp(): Response | undefined;
    /**
     * 当前状态 {@link DownloadTaskState}
     */
    get state(): DownloadTaskState;
    /**
     * 获取 Response Content-Length
     */
    get contentLength(): number;
    /**
     * 获取 Response Content-Encoding
     */
    get encoding(): string | null;
    /**
     * 获取 Response Content-Type
     */
    get mimeType(): string | null;
    /**
     * 实际接收内容的大小
     */
    get size(): number;
    /**
     * Response 是否经过压缩（基于 Content-Encoding 判定）
     */
    get isCompressed(): boolean;
    /**
     * 强制指定 compressed ，针对一些特殊的场合使用
     *
     * @param isCompressed
     */
    setCompressed: (isCompressed?: boolean) => this;
    /**
     * 已接收 Response body 大小
     */
    get received(): number;
    /**
     * 接收 Response body 进度小数（0 - 1）
     */
    get progress(): number;
    /**
     * 接收 Response body 进度百分比（0 - 100）
     */
    get percent(): number;
    /**
     * 获取 Response body 的 chunks
     */
    get chunks(): Uint8Array<ArrayBufferLike> | undefined;
    /**
     * 是否开始 read
     */
    get isStarted(): boolean;
    /**
     * 是否已经读取（完毕） Response body
     */
    get isReaded(): boolean;
    /**
     * 获取错误信息
     */
    get error(): unknown;
    /**
     * read 完成时间戳
     *
     * - 如果下载未开始，返回 0
     * - 如果下载已开始，但并未下载完成，则会返回当前时间的时间戳
     */
    get completeTs(): number;
    /**
     * read 数据经过多少时间（毫秒）
     *
     * 如果为实际完成，则返回当前时间的时间戳
     *
     * 如果未开始，则返回 0
     */
    get elapsedMs(): number;
    /**
     * 接收速度，单位为字节/秒，需要自行转换
     *
     * 如果未开始，返回 0
     *
     * ```ts
     * import { filesize } from 'filesize';
     *
     * const task = await fetchDownload().read();
     *
     * console.log(`${filesize(task.speed, { bits: true })}/s`); // kbit/s
     * console.log(`${filesize(task.speed)}/s`); // KB/s
     * ```
     */
    get speed(): number;
    /**
     * read response body（下载）
     *
     * 主要的流程：
     *
     * 1. 如果创建 {@link DownloadTask} 实例时输入的非 Response 实例 {@link DownloadInput}
     * 会创建一个函数去 fetch 输入（主要是 fetch headers，如果传入的是 Response 实例，则跳过这一步）。
     *     - `onFetch` 对应 fetch 前
     * 2. 解析 `Response.headers`，并提取 `content-length`、`content-type`、`content-encoding`，
     * 其中 `content-length` 为必须的（缺失或小于或等于0时将抛出错误）。
     *     - `onHeaders`
     * 3. `stream.read` 实际开始下载
     *     - `onProgress` 每一次接收 chunk 流
     *     - `onComplete` 下载完成
     *     - `onError` 出错时
     *
     * 默认状态下，任意错误都会抛出异常，可通过 `opts.isNotThrow` 为 `true` 禁用抛出异常。
     *
     * ```ts
     * const task = new DownloadTask('download_url');
     * await task.read({
     *   onFetch: () => {},    // fetch 前
     *   onHeaders: () => {},  // 读取 headers 时，stream read 之前
     *   onProgress: () => {}, // 每一次接收 chunk 流时
     *   onComplete: () => {}, // 下载完成时
     *   onError: () => {},    // 出错时
     * });
     * ```
     *
     * @param opts
     */
    read: (opts?: DownloadTaskProcessCallback | DownloadTaskProcessOptions) => Promise<this>;
    /**
     * 根据压缩后文件大小，推算出未压缩前的文件大小
     *
     * 文本内容的压缩率，实际取决于源内容的重复率，所以无法一概而论。
     * 这里只是尽可能放大压缩后的尺寸，以取得一个较为接近的值
     *
     * @param compressedSize 压缩后的文件大小
     */
    inferUncompressedSize: (compressedSize: number) => number;
    newErr: (msg: string) => DownloadTaskError;
}

declare class DownloadQueueError extends Error {
    readonly queue: DownloadQueue;
    constructor(msg: string, queue: DownloadQueue);
}
type DownloadQueueInput = DownloadInput | Response | DownloadTask;
type DownloadQueueProcessCallback = (queue: DownloadQueue, task: DownloadTask) => void | Promise<void>;
type DownloadQueueProcessOptions = {
    onFetch?: DownloadQueueProcessCallback;
    onHeaders?: DownloadQueueProcessCallback;
    onProgress?: DownloadQueueProcessCallback;
    onComplete?: DownloadQueueProcessCallback;
    onError?: DownloadQueueProcessCallback;
    onFinish?: (queue: DownloadQueue) => void | Promise<void>;
    onQueueError?: (queue: DownloadQueue) => void | Promise<void>;
};
declare class DownloadQueue {
    #private;
    /**
     * 创建 {@link DownloadQueue} 实例，允许多种 input 类型
     *
     * ```ts
     * // DownloadTask
     * const task1 = new DownloadQueue([new DownloadTask('url')]);
     * const task2 = new DownloadQueue([fetchDownload('url')]);
     *
     * // URL 输入
     * const task3 = new DownloadQueue(['url']);
     * const task4 = new DownloadQueue([new URL('url')]);
     *
     * // Request or DownloadRequest 结构
     * const task5 = new DownloadQueue([new Request('url')]);
     * const task6 = new DownloadQueue([{ url: 'url' }]);
     *
     * // Promise<Response>
     * const abort = new AbortController();
     * const task7 = new DownloadQueue([
     *   fetch('url', { signal: abort.signal }),
     * ]);
     *
     * // Response
     * const task8 = new DownloadTask([
     *   await fetch('url'),
     * ]);
     * ```
     *
     * @param tasks
     */
    constructor(tasks: DownloadQueueInput[]);
    /**
     * {@link DownloadQueue} Id
     */
    get id(): string;
    /**
     * 所有下载任务
     */
    get tasks(): DownloadTask[];
    /**
     * 所有下载任务的总数
     */
    get tasksCount(): number;
    /**
     * 当前状态 {@link DownloadTaskState}
     *
     * 注意 {@link DownloadQueue} 不应该出现 `fetching` 状态
     */
    get state(): DownloadTaskState;
    /**
     * 所有下载任务的实际总大小
     */
    get size(): number;
    /**
     * 所有下载任务的 Content-Length 总和
     */
    get contentLength(): number;
    /**
     * 所有下载任务的已接收 Response body 大小
     */
    get received(): number;
    /**
     * 所有下载任务的接收 Response body 进度小数（0 - 1）
     */
    get progress(): number;
    /**
     * 所有下载任务的接收 Response body 进度百分比（0 - 100）
     */
    get percent(): number;
    /**
     * 是否开始 read
     */
    get isStarted(): boolean;
    /**
     * 是否已经 read 完毕
     */
    get isReaded(): boolean;
    /**
     * 获取错误信息
     */
    get error(): unknown;
    /**
     * read 完成时间戳（所有下载任务都完成）
     *
     * - 如果下载未开始，返回 0
     * - 如果下载已开始，但并未下载完成，则会返回当前时间的时间戳
     */
    get completeTs(): number;
    /**
     * read 数据经过多少时间（毫秒，所有下载任务都完成）
     *
     * 如果为实际完成，则返回当前时间的时间戳
     *
     * 如果未开始，则返回 0
     */
    get elapsedMs(): number;
    /**
     * 接收速度（所有下载任务的平均值），单位为字节/秒，需要自行转换
     *
     * 如果未开始，返回 0
     *
     * ```ts
     * import { filesize } from 'filesize';
     *
     * const task = await fetchDownload().read();
     *
     * console.log(`${filesize(task.speed, { bits: true })}/s`); // kbit/s
     * console.log(`${filesize(task.speed)}/s`); // KB/s
     * ```
     */
    get speed(): number;
    protected _initTasksQueue: (opts?: DownloadQueueProcessOptions) => Promise<DownloadTask>[];
    reduce: <T>(fn: (acc: T, it: DownloadTask) => T, initValue: T) => T;
    /**
     * Queue 读取方法（调用每一个 task 的 read）
     *
     * 1. `onFetch`、`onHeaders`、`onProgress`、`onComplete`、`onError` 保留对应每一个 task 的事件
     * 2. `onFinish` 对应 Queue 全部 tasks 读取完毕
     * 3. `onQueueError` 对应 Queue 任意一个 task 读取过程中出错
     *
     * @param opts
     */
    read: (opts?: DownloadQueueProcessCallback | DownloadQueueProcessOptions) => Promise<this>;
    newErr: (msg: string) => DownloadQueueError;
}

/**
 * 创建 {@link DownloadTask} 或 {@link DownloadQueue} 的快捷方法
 *
 * ```ts
 * // DownloadTask
 * const task = fetchDownload('url');
 *
 * // DownloadQueue
 * const queue = fetchDownload(['url-a', 'url-b', 'url-c']);
 * ```
 *
 * @param input
 */
declare const fetchDownload: <T extends DownloadInput | DownloadInput[], R = T extends DownloadInput ? DownloadTask : DownloadQueue>(input: T) => R;

/**
 * 将 chunks 保存到本机，该方法只可在浏览器中执行
 *
 * ```ts
 * const task = fetchDownload('url');
 * await task.read();
 *
 * saveChunks(task.chunks, 'test.js');
 * ```
 *
 * @param chunks
 * @param filename
 * @param mimeType
 */
declare const saveChunks: (chunks: Uint8Array, filename: string | (() => string), mimeType?: string | null) => void;

export { DownloadQueue, DownloadQueueError, DownloadTask, DownloadTaskError, DownloadTaskState, MountRemoteError, PendingScopeConflictError, RetryExhaustedError, TimeoutError, UnixDS, WinDS, and, aryGuard, calcProgress, ceil10, clearPendingRegistry, createDomHandler, createPathUtils, decimalAdjust, errMsg, fetchDownload, floor10, isAry, isBool, isErrLike, isInferObj, isNil, isNull, isNumber, isNumberVal, isPlainObj, isPresent, isPromise, isStr, isUndefined, joinHttpPath, limitNumberMax, limitNumberMin, limitNumberMinMax, mergeAbortSignals, mergeHeaders, mergeRespInit, mountRemote, not, notEmptyAry, notEmptyStr, or, pending, pendingFn, purgeHttpPath, registerMountHandler, retry, retryFn, round10, saveChunks, sleep, timeout, toAryHeaders, toNumber, unmountDomRemote };
export type { AnyFn, AryHeaderItem, DirectorySeparator, DownloadFetchCallback, DownloadInput, DownloadQueueInput, DownloadQueueProcessCallback, DownloadQueueProcessOptions, DownloadRequest, DownloadTaskProcessCallback, DownloadTaskProcessOptions, DownloadUrl, ErrLike, HeadersInitInput, HttpStatusCode, InferGuard, MountDomOptions, MountDomResult, MountHandlerContext, MountHandlerFn, MountHandlerMap, MountRemoteResult, PathInput, PathReplacementCallback, PathUtilsOptions, PendingCallbackFn, PendingFnParams, RecordObj, ResponseInitInput, RetryCallbackFn, RetryFnParams, RetryOptions, TypeGuard };
