diff --git a/src/common/aborts.ts b/src/common/aborts.ts index d9705f8..b54fe0d 100644 --- a/src/common/aborts.ts +++ b/src/common/aborts.ts @@ -7,26 +7,38 @@ export function timeoutSignal(ms: number): { controller.abort(new DOMException("Operation timed out", "TimeoutError")); }, ms); - const cleanup = () => clearTimeout(timeout); - controller.signal.addEventListener("abort", cleanup); + const cleanup = () => { + clearTimeout(timeout); + controller.signal.removeEventListener("abort", cleanup); + }; + controller.signal.addEventListener("abort", cleanup); return { signal: controller.signal, cleanup }; } export function combineSignals(...signals: AbortSignal[]): AbortSignal { const controller = new AbortController(); + const cleanups = [] as (() => void)[]; for (const signal of signals) { if (signal.aborted) { controller.abort(signal.reason); return controller.signal; } - signal.addEventListener("abort", () => { + + const handler = () => { if (!controller.signal.aborted) { controller.abort(signal.reason); } - }); + }; + + signal.addEventListener("abort", handler); + cleanups.push(() => signal.removeEventListener("abort", handler)); } + controller.signal.addEventListener("abort", () => { + cleanups.forEach((cb) => cb()); + }); + return controller.signal; } diff --git a/src/common/crypto-algos.ts b/src/common/crypto-algos.ts index a6b1f65..7f84703 100644 --- a/src/common/crypto-algos.ts +++ b/src/common/crypto-algos.ts @@ -1,4 +1,4 @@ // TODO, is there a better way of getting the algo type? export type Algo = Parameters[2]; export const encrAlgo = { name: "AES-GCM", length: 256 } satisfies Algo; -export const signAlgo = { name: "ECDSA", namedCurve: "P-256" } satisfies Algo; +export const signAlgo = { name: "ES256" } satisfies Algo; diff --git a/src/common/crypto-sig.ts b/src/common/crypto-sig.ts index e0e5df3..f88b5b4 100644 --- a/src/common/crypto-sig.ts +++ b/src/common/crypto-sig.ts @@ -99,8 +99,8 @@ export const jwkPairSchema = z.object({ export const serializedJwkPairSchema = z.object({ __type: z.literal("jwkpair"), - publicJwk: z.any(), - privateJwk: z.any(), + publicKey: z.any(), + privateKey: z.any(), }); export type SerializedJwkPair = z.infer; @@ -110,23 +110,23 @@ export async function generateJwkPair(): Promise { } export async function serializeJwkPair(jwks: CryptoKeyPair): Promise { - const [publicJwk, privateJwk] = await Promise.all([ + const [publicKey, privateKey] = await Promise.all([ exportJWK(jwks.publicKey), exportJWK(jwks.privateKey), ]); return { __type: "jwkpair", - publicJwk, - privateJwk, + publicKey, + privateKey, }; } export async function deserializeJwkPair(data: unknown): Promise { - const { publicJwk, privateJwk } = serializedJwkPairSchema.parse(data); - const [publicKey, privateKey] = await Promise.all([ - importJWK(publicJwk, signAlgo.name, { extractable: true }) as Promise, - importJWK(privateJwk, signAlgo.name, { extractable: true }) as Promise, + let { publicKey, privateKey } = serializedJwkPairSchema.parse(data); + [publicKey, privateKey] = await Promise.all([ + importJWK(publicKey, signAlgo.name, { extractable: true }) as Promise, + importJWK(privateKey, signAlgo.name, { extractable: true }) as Promise, ]); return { diff --git a/src/common/sleep.ts b/src/common/sleep.ts new file mode 100644 index 0000000..7c9841e --- /dev/null +++ b/src/common/sleep.ts @@ -0,0 +1,20 @@ +export function sleep(ms: number, signal?: AbortSignal) { + signal?.throwIfAborted(); + + const { resolve, reject, promise } = Promise.withResolvers(); + const timeout = setTimeout(resolve, ms); + + if (signal) { + const abortHandler = () => { + clearTimeout(timeout); + reject(signal.reason); + }; + + signal.addEventListener("abort", abortHandler); + promise.finally(() => { + signal.removeEventListener("abort", abortHandler); + }); + } + + return promise; +} diff --git a/src/types/replace.ts b/src/types/replace.ts new file mode 100644 index 0000000..af3fbdc --- /dev/null +++ b/src/types/replace.ts @@ -0,0 +1,2 @@ +/** replace a key with a different type */ +export type Replace = Omit & Record;