// SPDX-FileCopyrightText: 2026 LiveKit, Inc. // // SPDX-License-Identifier: Apache-2.0 import { Throws } from './throws'; type InferErrors = T extends ThrowsPromise ? E : T extends PromiseLike ? U extends { __throws?(error: infer E): void } ? E : never : never; interface PromiseRejectedResult { status: 'rejected'; reason: E; } type SettledResult = T extends ThrowsPromise ? PromiseFulfilledResult | PromiseRejectedResult : T extends PromiseLike ? PromiseFulfilledResult | PromiseRejectedResult : PromiseFulfilledResult | PromiseRejectedResult; export class ThrowsPromise extends Promise> { constructor( executor: (resolve: (value: T | PromiseLike) => void, reject: (reason: E) => void) => void, ) { super(executor as unknown as ConstructorParameters>>[0]); } catch( onrejected?: ((reason: E) => TResult | PromiseLike) | null | undefined, ): ThrowsPromise { return super.catch(onrejected) as unknown as ThrowsPromise; } static resolve: { (): ThrowsPromise; (value: V): ThrowsPromise, never>; } = (value?: V): ThrowsPromise, never> => { return super.resolve(value) as ThrowsPromise, never>; }; static reject(reason: E): ThrowsPromise { return super.reject(reason) as ThrowsPromise; } static all( values: T, ): ThrowsPromise<{ -readonly [P in keyof T]: Awaited }, InferErrors> { return super.all(values) as any; } static allSettled( values: T, ): ThrowsPromise<{ -readonly [P in keyof T]: SettledResult }, never> { return super.allSettled(values) as any; } static race | any)[]>( values: T, ): ThrowsPromise< T[number] extends ThrowsPromise ? U : T[number] extends PromiseLike ? U : Awaited, InferErrors > { return super.race(values) as any; } /** type cast (third party promise) to a ThrowsPromise */ static fromPromise(promise: Promise): ThrowsPromise { return promise as ThrowsPromise; } /** type cast that strips the throws type */ asPromise(): Promise { return this; } }