{"version":3,"file":"index.mjs","names":["isObject","hasOwnProperty","compareMethod","hashMethod","isObject","create"],"sources":["../src/cache/adapters/memory.ts","../src/redis/check.ts","../src/redis/factory.ts","../src/cache/adapters/redis.ts","../src/cache/helper.ts","../src/core/service.ts","../src/core/junction-service.ts","../src/crypto/hash/compare.ts","../src/crypto/hash/hash.ts","../src/crypto/key/asymmetric/constants.ts","../src/crypto/key/base.ts","../src/crypto/key/asymmetric/helpers/wrap.ts","../src/crypto/key/asymmetric/key-usages.ts","../src/crypto/key/asymmetric/normalize.ts","../src/crypto/key/asymmetric/module.ts","../src/crypto/key/asymmetric/check.ts","../src/crypto/key/asymmetric/create.ts","../src/crypto/key/symmetric/constants.ts","../src/crypto/key/symmetric/check.ts","../src/crypto/key/symmetric/key-usages.ts","../src/crypto/key/symmetric/normalize.ts","../src/crypto/key/symmetric/module.ts","../src/crypto/key/symmetric/create.ts","../src/crypto/json-web-token/extract.ts","../src/crypto/json-web-token/utils.ts","../src/crypto/json-web-token/sign/module.ts","../src/crypto/json-web-token/verify/module.ts","../src/crypto/symmetric-cipher/module.ts","../src/domain-event/utils.ts","../src/domain-event/handlers/redis/module.ts","../src/domain-event/handlers/socket/module.ts","../src/domain-event/module.ts","../src/logger/module.ts","../src/utils/has-property.ts"],"sourcesContent":["/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { TTLCacheOptions } from '@isaacs/ttlcache';\nimport { TTLCache } from '@isaacs/ttlcache';\nimport type { CacheClearOptions, CacheSetOptions, ICache } from '../types';\n\nexport class MemoryCache implements ICache {\n    protected instance : TTLCache<string, unknown>;\n\n    constructor(options: TTLCacheOptions<string, unknown> = {}) {\n        this.instance = new TTLCache<string, unknown>({\n            checkAgeOnGet: true,\n            ttl: Infinity,\n            ...(options || {}),\n        });\n    }\n\n    async pop<T = unknown>(key: string): Promise<T | null> {\n        if (this.instance.has(key)) {\n            const output = this.instance.get(key);\n            this.instance.delete(key);\n            return output as T;\n        }\n\n        return null;\n    }\n\n    async has(key: string) : Promise<boolean> {\n        return this.instance.has(key);\n    }\n\n    async get<T =unknown>(key: string): Promise<T | null> {\n        // Distinguish \"absent/expired\" (undefined) from a stored falsy value —\n        // a `0` counter or `false`/`''` must round-trip, not read back as null.\n        const output = this.instance.get(key);\n        if (typeof output === 'undefined') {\n            return null;\n        }\n\n        return output as T;\n    }\n\n    async set(key: string, value: unknown, options: CacheSetOptions): Promise<void> {\n        this.instance.set(key, value, { ttl: options.ttl });\n    }\n\n    async add(key: string, value: unknown, options: CacheSetOptions = {}): Promise<boolean> {\n        // The check + set run in a single synchronous tick (no await between),\n        // so this is atomic within the single-threaded process.\n        if (this.instance.has(key)) {\n            return false;\n        }\n\n        this.instance.set(key, value, { ttl: options.ttl });\n        return true;\n    }\n\n    async renewIfValue(key: string, value: string, ttl: number): Promise<boolean> {\n        if (this.instance.get(key) !== value) {\n            return false;\n        }\n\n        this.instance.set(key, value, { ttl });\n        return true;\n    }\n\n    async dropIfValue(key: string, value: string): Promise<boolean> {\n        if (this.instance.get(key) !== value) {\n            return false;\n        }\n\n        return this.instance.delete(key);\n    }\n\n    async increment(key: string, value = 1, options: CacheSetOptions = {}): Promise<number> {\n        // The read + write run in a single synchronous tick (no await\n        // between), so this is atomic within the single-threaded process.\n        const current = this.instance.get(key);\n        if (typeof current !== 'undefined' && typeof current !== 'number') {\n            throw new Error(`The value at key ${key} is not a number.`);\n        }\n\n        const output = (current ?? 0) + value;\n        this.instance.set(key, output, { ttl: options.ttl });\n        return output;\n    }\n\n    async drop(key: string): Promise<void> {\n        this.instance.delete(key);\n    }\n\n    async dropMany(keys: string[]) : Promise<void> {\n        for (const key of keys) {\n            this.instance.delete(key);\n        }\n    }\n\n    async clear(options: CacheClearOptions = {}) : Promise<void> {\n        if (options.prefix) {\n            const keys = this.instance.keys();\n            let iterator = keys.next();\n            while (!iterator.done) {\n                if (typeof iterator.value !== 'string') {\n                    continue;\n                }\n\n                if (iterator.value.startsWith(options.prefix)) {\n                    this.instance.delete(iterator.value);\n                }\n\n                iterator = keys.next();\n            }\n\n            return;\n        }\n\n        this.instance.clear();\n    }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from 'smob';\nimport type { RedisClient } from './module';\n\nexport function isRedisClient(data: unknown) : data is RedisClient {\n    return isObject(data) &&\n        typeof data.connect === 'function' &&\n        typeof data.disconnect === 'function';\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createClient } from 'redis-extension';\nimport { isRedisClient } from './check';\nimport type { RedisClient, RedisClientOptions } from './module';\n\nexport type RedisClientCreateInput = string | boolean | RedisClient | RedisClientOptions;\n\nexport function createRedisClient(input: RedisClientCreateInput) {\n    if (typeof input === 'boolean') {\n        return createClient({ connectionString: 'redis://127.0.0.1' });\n    }\n\n    if (typeof input === 'string') {\n        return createClient({ connectionString: input });\n    }\n\n    if (!isRedisClient(input)) {\n        return createClient({ options: input });\n    }\n\n    return input;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Client } from 'redis-extension';\nimport { JsonAdapter } from 'redis-extension';\nimport type { RedisClient, RedisClientOptions } from '../../redis';\nimport { createRedisClient } from '../../redis';\nimport type { CacheClearOptions, CacheSetOptions, ICache } from '../types';\n\nconst RENEW_IF_VALUE_SCRIPT = `\nif redis.call('get', KEYS[1]) == ARGV[1] then\n    return redis.call('pexpire', KEYS[1], ARGV[2])\nend\nreturn 0\n`;\n\nconst DROP_IF_VALUE_SCRIPT = `\nif redis.call('get', KEYS[1]) == ARGV[1] then\n    return redis.call('del', KEYS[1])\nend\nreturn 0\n`;\n\nexport class RedisCache implements ICache {\n    protected client : Client;\n\n    protected jsonAdapter : JsonAdapter;\n\n    constructor(input: string | boolean | RedisClient | RedisClientOptions) {\n        this.client = createRedisClient(input);\n        this.jsonAdapter = new JsonAdapter(this.client);\n    }\n\n    async get(key: string): Promise<any> {\n        // jsonAdapter.get returns undefined for an absent key — distinguish that\n        // from a stored falsy value (`0` counter, `false`, `''`) which must\n        // round-trip instead of reading back as null.\n        const output = await this.jsonAdapter.get(key);\n        if (typeof output === 'undefined') {\n            return null;\n        }\n\n        return output;\n    }\n\n    async pop<T = unknown>(key: string): Promise<T | null> {\n        const raw = await this.client.getdel(key);\n        if (!raw) {\n            return null;\n        }\n\n        try {\n            return JSON.parse(raw) as T;\n        } catch {\n            return null;\n        }\n    }\n\n    async has(key: string) : Promise<boolean> {\n        // EXISTS, not a truthiness check on the value — a stored falsy value\n        // (`0`/`false`/`''`) is still present.\n        return (await this.client.exists(key)) > 0;\n    }\n\n    async set(key: string, value: any, options: CacheSetOptions): Promise<void> {\n        await this.jsonAdapter.set(key, value, { milliseconds: options.ttl });\n    }\n\n    async add(key: string, value: any, options: CacheSetOptions = {}): Promise<boolean> {\n        // Atomic set-if-absent via `SET key value [PX ttl] NX` — returns 'OK'\n        // when stored, null when the key already existed.\n        const payload = JSON.stringify(value);\n        const result = options.ttl ?\n            await this.client.set(key, payload, 'PX', options.ttl, 'NX') :\n            await this.client.set(key, payload, 'NX');\n\n        return result === 'OK';\n    }\n\n    async renewIfValue(key: string, value: string, ttl: number): Promise<boolean> {\n        const result = await this.client.eval(\n            RENEW_IF_VALUE_SCRIPT,\n            1,\n            key,\n            JSON.stringify(value),\n            ttl,\n        );\n\n        return result === 1;\n    }\n\n    async dropIfValue(key: string, value: string): Promise<boolean> {\n        const result = await this.client.eval(\n            DROP_IF_VALUE_SCRIPT,\n            1,\n            key,\n            JSON.stringify(value),\n        );\n\n        return result === 1;\n    }\n\n    async increment(key: string, value = 1, options: CacheSetOptions = {}): Promise<number> {\n        // INCRBY is atomic; the follow-up PEXPIRE only (re)arms the expiry,\n        // so an interleaved concurrent increment is harmless. Rejects when\n        // the key holds a non-integer value.\n        const output = await this.client.incrby(key, value);\n        if (options.ttl) {\n            await this.client.pexpire(key, options.ttl);\n        }\n\n        return output;\n    }\n\n    async drop(key: string): Promise<void> {\n        await this.jsonAdapter.drop(key);\n    }\n\n    async dropMany(keys: string[]) : Promise<void> {\n        const pipeline = this.client.pipeline();\n\n        for (const key of keys) {\n            pipeline.del(key);\n        }\n\n        await pipeline.exec();\n    }\n\n    async clear(options: CacheClearOptions = {}) : Promise<void> {\n        if (options.prefix) {\n            const pipeline = this.client.pipeline();\n\n            const keys = await this.client.keys(`${options.prefix}*`);\n            for (const key of keys) {\n                pipeline.del(key);\n            }\n\n            await pipeline.exec();\n\n            return;\n        }\n        await this.client.flushdb();\n    }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { buildRedisKeyPath } from '../redis';\nimport type { CacheKeyBuildOptions } from './types';\n\nexport function buildCacheKey(options: CacheKeyBuildOptions) {\n    return buildRedisKeyPath(options);\n}\n","/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType } from '@authup/access';\nimport { hasOwnProperty, isObject } from '@authup/kit';\nimport type { ActorContext } from './actor/types';\n\nexport abstract class AbstractEntityService {\n    protected getActorRealmId(actor: ActorContext): string | undefined {\n        if (!actor.identity) {\n            return undefined;\n        }\n\n        const { data } = actor.identity;\n        if (data.realmId) {\n            return data.realmId;\n        }\n\n        if (isObject(data.realm) && data.realm.id) {\n            return data.realm.id;\n        }\n\n        return undefined;\n    }\n\n    /**\n     * Resource-realm entry for a permission `evaluate()` input, spread into the PolicyData\n     * literal: `new PolicyData({ [ATTRIBUTES]: x, ...this.resourceRealmMatch(x) })`. It mirrors\n     * ATTRIBUTES `realmId` PRESENCE — the `realmMatch` key is set only when the source carries\n     * `realmId`, so a self-edit UPDATE (where the validator strips `realmId`) leaves the key\n     * ABSENT and the realm_scope reach factor neutral-passes, exactly as the pre-key behavior.\n     * A present `realmId: null` (global resource) is carried as `null` (and `own` denies it).\n     */\n    protected resourceRealmMatch(source: Record<string, any>): Record<string, any> {\n        return hasOwnProperty(source, 'realmId') ?\n            { [BuiltInPolicyType.REALM_MATCH]: source.realmId ?? null } :\n            {};\n    }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AbstractEntityService } from './service';\n\n/**\n * Base class for junction/association entity services (role-permission, user-role,\n * client-scope, …) whose rows carry no top-level `realmId`, only the realm of the\n * entities they link. The OWNER entity's realm gates a junction write — it is supplied to\n * the realm_scope reach factor under the `realmMatch` PolicyData key (RealmMatchPolicyEvaluator\n * SCOPE MODE), NOT stamped into ATTRIBUTES — so junction ATTRIBUTES carry only genuine\n * columns and an ATTRIBUTE_NAMES policy never mis-sees a synthetic `realmId`.\n */\nexport abstract class JunctionEntityService extends AbstractEntityService {\n    /**\n     * Attribute carrying the OWNER entity's realm — the realm-bound entity whose\n     * sub-resource this junction manages (e.g. `roleRealmId` for role-permission,\n     * `userRealmId` for user-role). `abstract` => every junction service MUST declare\n     * it; a missing declaration is a compile error, which is what closes the fail-open\n     * gap (a structural guard, not a convention).\n     */\n    protected abstract readonly ownerRealmKey: string;\n\n    /**\n     * The junction's genuine attributes for a permission `evaluate()` — a COPY of the row\n     * (never the persisted entity). No synthetic `realmId`; the owner realm travels\n     * separately via {@link junctionResourceRealm}.\n     */\n    protected junctionAttributes(entity: Record<string, any>): Record<string, any> {\n        return { ...entity };\n    }\n\n    /**\n     * The OWNER realm for the realm_scope reach factor — set under the `realmMatch` PolicyData\n     * key alongside ATTRIBUTES. A `null` owner (global) is matched (and `own` correctly denies\n     * it). Reading `ownerRealmKey` keeps the compile-time guard: a junction cannot silently\n     * skip its realm.\n     */\n    protected junctionResourceRealm(entity: Record<string, any>): string | null {\n        return entity[this.ownerRealmKey] ?? null;\n    }\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { compare as compareMethod } from '@node-rs/bcrypt';\n\nexport async function compare(value: string, hashedValue: string) : Promise<boolean> {\n    return compareMethod(value, hashedValue);\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hash as hashMethod } from '@node-rs/bcrypt';\n\nexport async function hash(str: string, rounds: number = 10) : Promise<string> {\n    return hashMethod(str, rounds);\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum CryptoAsymmetricAlgorithm {\n    RSA_PSS = 'RSA-PSS',\n    RSASSA_PKCS1_V1_5 = 'RSASSA-PKCS1-v1_5',\n    RSA_OAEP = 'RSA-OAEP',\n    ECDSA = 'ECDSA',\n    ECDH = 'ECDH',\n}\n","/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { arrayBufferToBase64 } from '@authup/kit';\nimport { subtle } from 'uncrypto';\n\nexport abstract class BaseKey {\n    protected key : CryptoKey;\n\n    // ----------------------------------------------\n\n    constructor(cryptoKey : CryptoKey) {\n        this.key = cryptoKey;\n    }\n\n    // ----------------------------------------------\n\n    async toArrayBuffer(): Promise<ArrayBuffer> {\n        if (this.key.type === 'private') {\n            return subtle.exportKey('pkcs8', this.key);\n        }\n\n        if (this.key.type === 'public') {\n            return subtle.exportKey('spki', this.key);\n        }\n\n        return subtle.exportKey('raw', this.key);\n    }\n\n    async toUint8Array(): Promise<Uint8Array> {\n        const arrayBuffer = await this.toArrayBuffer();\n        return new Uint8Array(arrayBuffer);\n    }\n\n    async toBase64() : Promise<string> {\n        const arrayBuffer = await this.toArrayBuffer();\n        return arrayBufferToBase64(arrayBuffer);\n    }\n\n    async toJWK() : Promise<JsonWebKey> {\n        return subtle.exportKey('jwk', this.key);\n    }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nfunction enc(\n    type: 'PRIVATE KEY' | 'PUBLIC KEY',\n    input: string,\n) {\n    return `-----BEGIN ${type}-----\\n${input}\\n-----END ${type}-----`;\n}\n\nexport function encodePKCS8ToPEM(base64: string) {\n    return enc('PRIVATE KEY', base64);\n}\n\nexport function encodeSPKIToPem(input: string) {\n    return enc('PUBLIC KEY', input);\n}\n\n// ------------------------------------------------------------\n\nfunction dec(\n    type: 'PRIVATE KEY' | 'PUBLIC KEY',\n    input: string,\n) {\n    input = input.replace(`-----BEGIN ${type}-----\\n`, '');\n\n    input = input.replace(`\\n-----END ${type}-----\\n`, '');\n    input = input.replace(`-----END ${type}-----\\n`, '');\n    input = input.replace(`\\n-----END ${type}-----`, '');\n\n    return input;\n}\n\nexport function decodePemToPKCS8(input: string) {\n    return dec('PRIVATE KEY', input);\n}\n\nexport function decodePemToSpki(input: string) {\n    return dec('PUBLIC KEY', input);\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { CryptoAsymmetricAlgorithm } from './constants';\n\n/**\n * @see https://nodejs.org/api/webcrypto.html#cryptokeyusages\n */\nexport function getKeyUsagesForAsymmetricAlgorithm(\n    name: string,\n    format?: Exclude<KeyFormat, 'jwk'>,\n) : KeyUsage[] {\n    if (\n        name === CryptoAsymmetricAlgorithm.RSA_PSS ||\n        name === CryptoAsymmetricAlgorithm.ECDSA ||\n        name === CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5\n    ) {\n        if (format === 'spki') {\n            return ['verify'];\n        } if (format === 'pkcs8') {\n            return ['sign'];\n        }\n\n        return ['sign', 'verify'];\n    }\n\n    if (name === CryptoAsymmetricAlgorithm.ECDH) {\n        if (format === 'spki') {\n            return [];\n        }\n\n        return [\n            'deriveKey',\n            'deriveBits',\n        ];\n    }\n\n    if (name === CryptoAsymmetricAlgorithm.RSA_OAEP) {\n        if (format === 'spki') {\n            return ['encrypt'];\n        } if (format === 'pkcs8') {\n            return ['decrypt'];\n        }\n\n        return ['encrypt', 'decrypt'];\n    }\n\n    throw new SyntaxError(`Key usages can not be determined for asymmetric algorithm: ${name}`);\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { CryptoAsymmetricAlgorithm } from './constants';\nimport type {\n    AsymmetricKeyImportOptionsInput,\n    AsymmetricKeyPairCreateOptions,\n    AsymmetricKeyPairCreateOptionsInput,\n    AsymmetricKeyPairImportOptions,\n} from './types';\n\nexport function normalizeAsymmetricKeyPairCreateOptions(\n    options: AsymmetricKeyPairCreateOptionsInput,\n) : AsymmetricKeyPairCreateOptions {\n    let optionsNormalized : AsymmetricKeyPairCreateOptions;\n    switch (options.name) {\n        case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:\n        case CryptoAsymmetricAlgorithm.RSA_PSS:\n        case CryptoAsymmetricAlgorithm.RSA_OAEP: {\n            optionsNormalized = {\n                modulusLength: 2048,\n                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n                hash: 'SHA-256',\n                ...options,\n            };\n            break;\n        }\n        case CryptoAsymmetricAlgorithm.ECDSA:\n        case CryptoAsymmetricAlgorithm.ECDH: {\n            optionsNormalized = {\n                namedCurve: 'P-256',\n                ...options,\n            };\n        }\n    }\n\n    return optionsNormalized;\n}\n\nexport function normalizeAsymmetricKeyImportOptions(\n    options: AsymmetricKeyImportOptionsInput,\n) : AsymmetricKeyPairImportOptions {\n    let optionsNormalized : AsymmetricKeyPairImportOptions;\n    switch (options.name) {\n        case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:\n        case CryptoAsymmetricAlgorithm.RSA_PSS:\n        case CryptoAsymmetricAlgorithm.RSA_OAEP: {\n            optionsNormalized = {\n                hash: 'SHA-256',\n                ...options,\n            };\n            break;\n        }\n        case CryptoAsymmetricAlgorithm.ECDSA:\n        case CryptoAsymmetricAlgorithm.ECDH: {\n            optionsNormalized = {\n                namedCurve: 'P-256',\n                ...options,\n            };\n        }\n    }\n\n    return optionsNormalized;\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { base64ToArrayBuffer } from '@authup/kit';\nimport { JWTAlgorithm } from '@authup/specs';\nimport { subtle } from 'uncrypto';\nimport { BaseKey } from '../base';\nimport { CryptoAsymmetricAlgorithm } from './constants';\nimport type { AsymmetricKeyImportContext } from './types';\nimport {\n    decodePemToPKCS8, \n    decodePemToSpki, \n    encodePKCS8ToPEM, \n    encodeSPKIToPem,\n} from './helpers';\nimport { getKeyUsagesForAsymmetricAlgorithm } from './key-usages';\nimport { normalizeAsymmetricKeyImportOptions } from './normalize';\n\nexport class AsymmetricKey extends BaseKey {\n    async toPem(): Promise<string> {\n        const base64 = await this.toBase64();\n\n        if (this.key.type === 'public') {\n            return encodeSPKIToPem(base64);\n        }\n\n        if (this.key.type === 'private') {\n            return encodePKCS8ToPEM(base64);\n        }\n\n        throw new Error(`${this.key.type} can not be converted to pem.`);\n    }\n\n    // ----------------------------------------------------------------\n\n    static async fromPem(ctx: AsymmetricKeyImportContext<string>): Promise<AsymmetricKey> {\n        if (ctx.format === 'pkcs8') {\n            return AsymmetricKey.fromBase64({\n                ...ctx,\n                key: decodePemToPKCS8(ctx.key), \n            });\n        }\n        return AsymmetricKey.fromBase64({\n            ...ctx,\n            key: decodePemToSpki(ctx.key), \n        });\n    }\n\n    static async fromBase64(\n        ctx: AsymmetricKeyImportContext<string>,\n    ) : Promise<AsymmetricKey> {\n        const arrayBuffer = base64ToArrayBuffer(ctx.key);\n\n        return AsymmetricKey.fromArrayBuffer({\n            ...ctx,\n            key: arrayBuffer,\n        });\n    }\n\n    static async fromArrayBuffer(\n        ctx: AsymmetricKeyImportContext<ArrayBuffer>,\n    ) : Promise<AsymmetricKey> {\n        const normalizedOptions = normalizeAsymmetricKeyImportOptions(ctx.options);\n\n        const cryptoKey = await subtle.importKey(\n            ctx.format,\n            ctx.key,\n            normalizedOptions,\n            true,\n            getKeyUsagesForAsymmetricAlgorithm(normalizedOptions.name, ctx.format),\n        );\n\n        return new AsymmetricKey(cryptoKey);\n    }\n\n    // ----------------------------------------------------------------\n\n    static buildImportOptionsForJWTAlgorithm(alg: `${JWTAlgorithm}`) {\n        if (alg === JWTAlgorithm.RS256) {\n            return {\n                name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,\n                hash: 'SHA-256',\n            };\n        }\n\n        if (alg === JWTAlgorithm.RS384) {\n            return {\n                name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,\n                hash: 'SHA-384',\n            };\n        }\n\n        if (alg === JWTAlgorithm.RS512) {\n            return {\n                name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,\n                hash: 'SHA-512',\n            };\n        }\n\n        if (alg === JWTAlgorithm.ES256) {\n            return {\n                name: CryptoAsymmetricAlgorithm.ECDSA,\n                namedCurve: 'P-256',\n            };\n        }\n\n        if (alg === JWTAlgorithm.ES384) {\n            return {\n                name: CryptoAsymmetricAlgorithm.ECDSA,\n                namedCurve: 'P-384',\n            };\n        }\n\n        if (alg === JWTAlgorithm.ES512) {\n            return {\n                name: CryptoAsymmetricAlgorithm.ECDSA,\n                namedCurve: 'P-521',\n            };\n        }\n\n        throw new Error(`Signature algorithm ${alg} is not supported.`);\n    }\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { CryptoAsymmetricAlgorithm } from './constants';\n\nexport function isAsymmetricAlgorithm(input: string) : input is CryptoAsymmetricAlgorithm {\n    return (Object.values(CryptoAsymmetricAlgorithm) as string[]).includes(input);\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { subtle } from 'uncrypto';\nimport { getKeyUsagesForAsymmetricAlgorithm } from './key-usages';\nimport { normalizeAsymmetricKeyPairCreateOptions } from './normalize';\nimport type { AsymmetricKeyPairCreateOptionsInput } from './types';\n\nexport async function createAsymmetricKeyPair(options: AsymmetricKeyPairCreateOptionsInput) : Promise<CryptoKeyPair> {\n    const optionsNormalized = normalizeAsymmetricKeyPairCreateOptions(options);\n    return subtle.generateKey(\n        optionsNormalized,\n        true,\n        getKeyUsagesForAsymmetricAlgorithm(optionsNormalized.name),\n    );\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum SymmetricAlgorithm {\n    HMAC = 'HMAC',\n    AES_CTR = 'AES-CTR',\n    AES_CBC = 'AES-CBC',\n    AES_GCM = 'AES-GCM',\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { SymmetricAlgorithm } from './constants';\n\nexport function isSymmetricAlgorithm(input: string) : input is SymmetricAlgorithm {\n    return (Object.values(SymmetricAlgorithm) as string[]).includes(input);\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { SymmetricAlgorithm } from './constants';\n\nexport function getKeyUsagesForSymmetricAlgorithm(name: string) : KeyUsage[] {\n    /**\n     * @see https://nodejs.org/api/webcrypto.html#cryptokeyusages\n     */\n    if (name === SymmetricAlgorithm.HMAC) {\n        return [\n            'sign',\n            'verify',\n        ];\n    }\n\n    if (\n        name === SymmetricAlgorithm.AES_CBC ||\n        name === SymmetricAlgorithm.AES_GCM ||\n        name === SymmetricAlgorithm.AES_CTR\n    ) {\n        return [\n            'encrypt',\n            'decrypt',\n        ];\n    }\n\n    throw new SyntaxError(`Key usages can not be determined for symmetric algorithm: ${name}`);\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { SymmetricAlgorithm } from './constants';\nimport type {\n    SymmetricKeyCreateOptions, \n    SymmetricKeyCreateOptionsInput, \n    SymmetricKeyImportOptions, \n    SymmetricKeyImportOptionsInput,\n} from './types';\n\nexport function normalizeSymmetricKeyCreateOptions(\n    input: SymmetricKeyCreateOptionsInput,\n) : SymmetricKeyCreateOptions {\n    if (input.name === SymmetricAlgorithm.HMAC) {\n        return {\n            hash: 'SHA-256',\n            ...input,\n        };\n    }\n\n    return {\n        length: 256,\n        name: input.name,\n    };\n}\n\nexport function normalizeSymmetricKeyImportOptions(\n    input: SymmetricKeyImportOptionsInput,\n) : SymmetricKeyImportOptions {\n    if (input.name === SymmetricAlgorithm.HMAC) {\n        return {\n            hash: 'SHA-256',\n            ...input,\n        };\n    }\n\n    return input;\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { base64ToArrayBuffer } from '@authup/kit';\nimport { JWTAlgorithm } from '@authup/specs';\nimport { subtle } from 'uncrypto';\nimport { BaseKey } from '../base';\nimport { SymmetricAlgorithm } from './constants';\nimport { getKeyUsagesForSymmetricAlgorithm } from './key-usages';\nimport { normalizeSymmetricKeyImportOptions } from './normalize';\nimport type { SymmetricKeyImportContext, SymmetricKeyImportOptions } from './types';\n\nexport class SymmetricKey extends BaseKey {\n    static async fromBase64(\n        ctx: SymmetricKeyImportContext<string>,\n    ) : Promise<SymmetricKey> {\n        const arrayBuffer = base64ToArrayBuffer(ctx.key);\n\n        return SymmetricKey.fromArrayBuffer({\n            ...ctx,\n            key: arrayBuffer,\n        });\n    }\n\n    static async fromArrayBuffer(\n        ctx: SymmetricKeyImportContext<ArrayBuffer>,\n    ) : Promise<SymmetricKey> {\n        const normalizedOptions : SymmetricKeyImportOptions = normalizeSymmetricKeyImportOptions(ctx.options);\n\n        const cryptoKey = await subtle.importKey(\n            ctx.format,\n            ctx.key,\n            normalizedOptions,\n            true,\n            getKeyUsagesForSymmetricAlgorithm(normalizedOptions.name),\n        );\n\n        return new SymmetricKey(cryptoKey);\n    }\n\n    static buildImportOptionsForJWTAlgorithm(alg: `${JWTAlgorithm}`) {\n        if (alg === JWTAlgorithm.HS256) {\n            return {\n                name: SymmetricAlgorithm.HMAC,\n                hash: 'SHA-256',\n            };\n        }\n\n        if (alg === JWTAlgorithm.HS384) {\n            return {\n                name: SymmetricAlgorithm.HMAC,\n                hash: 'SHA-384',\n            };\n        }\n\n        if (alg === JWTAlgorithm.HS512) {\n            return {\n                name: SymmetricAlgorithm.HMAC,\n                hash: 'SHA-512',\n            };\n        }\n\n        throw new Error(`Signature algorithm ${alg} is not supported.`);\n    }\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { subtle } from 'uncrypto';\nimport { getKeyUsagesForSymmetricAlgorithm } from './key-usages';\nimport { normalizeSymmetricKeyCreateOptions } from './normalize';\nimport type { SymmetricKeyCreateOptionsInput } from './types';\n\nexport async function createSymmetricKey(input: SymmetricKeyCreateOptionsInput) : Promise<CryptoKey> {\n    const optionsNormalized = normalizeSymmetricKeyCreateOptions(input);\n\n    return subtle.generateKey(\n        optionsNormalized,\n        true,\n        getKeyUsagesForSymmetricAlgorithm(optionsNormalized.name),\n    );\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { JWTClaims, JWTHeader } from '@authup/specs';\nimport { JWTError } from '@authup/specs';\n\n/**\n * Decode a JWT token with no verification.\n *\n * @param token\n *\n * @throws JWTError\n */\nexport function extractTokenHeader(\n    token: string,\n) : JWTHeader {\n    const parts = token.split('.');\n    if (parts.length !== 3) {\n        throw JWTError.invalid();\n    }\n\n    const [headerBase64] = parts;\n\n    try {\n        const payload = atob(headerBase64);\n\n        return JSON.parse(payload);\n\n        /*\n        return {\n            typ: 'JWT',\n            alg: transformInternalToJWTAlgorithm(header.algorithm),\n            cty: header.contentType,\n            jku: header.jsonKeyUrl,\n            kid: header.keyId,\n            x5u: header.x5Url,\n            x5c: header.x5CertChain,\n            x5t: header.x5CertThumbprint,\n            'x5t#S256': header.x5TS256CertThumbprint,\n        };\n         */\n    } catch {\n        throw JWTError.headerInvalid('The token header could not be extracted.');\n    }\n}\n\n/**\n * @param token\n *\n * @throws JWTError\n */\nexport function extractTokenPayload(\n    token: string,\n) : JWTClaims {\n    const parts = token.split('.');\n    if (parts.length !== 3) {\n        throw JWTError.invalid();\n    }\n\n    const [, payloadBase64] = parts;\n\n    try {\n        // A JWT payload is base64URL (RFC 7515 §2), which `atob` rejects on\n        // its `-`/`_` characters, and `atob` yields latin1 while the payload\n        // is UTF-8 (RFC 7519 §3). Any claim outside ASCII produces one or the\n        // other, so a token carrying a name like `Пётр` or an emoji failed to\n        // decode at all.\n        const normalized = payloadBase64.replace(/-/g, '+').replace(/_/g, '/');\n        const binary = atob(normalized);\n        const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n\n        return JSON.parse(new TextDecoder().decode(bytes));\n    } catch {\n        throw JWTError.payloadInvalid('The token payload could not be extracted.');\n    }\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { JWTAlgorithm, JWTError } from '@authup/specs';\nimport { Algorithm } from '@node-rs/jsonwebtoken';\nimport { isObject } from 'smob';\n\nexport function createErrorForJWTError(e: unknown) : JWTError {\n    if (isObject(e)) {\n        if (typeof e.name === 'string') {\n            switch (e.name) {\n                case 'TokenExpiredError': {\n                    return JWTError.expired();\n                }\n                case 'NotBeforeError': {\n                    if (typeof e.date === 'string' || e.date instanceof Date) {\n                        return JWTError.notActiveBefore(e.date);\n                    }\n                    break;\n                }\n                case 'JsonWebTokenError': {\n                    if (typeof e.message === 'string') {\n                        return JWTError.payloadInvalid(e.message);\n                    }\n\n                    break;\n                }\n            }\n        }\n\n        // @see https://github.com/Keats/jsonwebtoken/blob/master/src/errors.rs\n        switch (e.message) {\n            case 'ExpiredSignature': {\n                return JWTError.expired();\n            }\n            case 'ImmatureSignature': {\n                return JWTError.notActiveBefore();\n            }\n            case 'InvalidToken':\n            case 'InvalidSignature': {\n                return JWTError.payloadInvalid();\n            }\n        }\n    }\n\n    return new JWTError({\n        cause: e as Error,\n        message: 'The JWT error could not be determined.',\n    });\n}\n\nexport function transformJWTAlgorithmToInternal(algorithm: `${JWTAlgorithm}`) : Algorithm {\n    switch (algorithm) {\n        case JWTAlgorithm.HS256: {\n            return Algorithm.HS256;\n        }\n        case JWTAlgorithm.HS384: {\n            return Algorithm.HS384;\n        }\n        case JWTAlgorithm.HS512: {\n            return Algorithm.HS512;\n        }\n        case JWTAlgorithm.RS256: {\n            return Algorithm.RS256;\n        }\n        case JWTAlgorithm.RS384: {\n            return Algorithm.RS384;\n        }\n        case JWTAlgorithm.RS512: {\n            return Algorithm.RS512;\n        }\n        case JWTAlgorithm.ES256: {\n            return Algorithm.ES256;\n        }\n        case JWTAlgorithm.ES384: {\n            return Algorithm.ES384;\n        }\n        case JWTAlgorithm.PS256: {\n            return Algorithm.PS256;\n        }\n        case JWTAlgorithm.PS384: {\n            return Algorithm.PS384;\n        }\n        case JWTAlgorithm.PS512: {\n            return Algorithm.PS512;\n        }\n    }\n\n    throw new Error(`The algorithm ${algorithm} is not supported.`);\n}\n\nexport function transformInternalToJWTAlgorithm(input: Algorithm) : JWTAlgorithm {\n    switch (input) {\n        case Algorithm.HS256:\n            return JWTAlgorithm.HS256;\n        case Algorithm.HS384:\n            return JWTAlgorithm.HS384;\n        case Algorithm.HS512:\n            return JWTAlgorithm.HS512;\n        case Algorithm.RS256:\n            return JWTAlgorithm.RS256;\n        case Algorithm.RS384:\n            return JWTAlgorithm.RS384;\n        case Algorithm.RS512:\n            return JWTAlgorithm.RS512;\n        case Algorithm.ES256:\n            return JWTAlgorithm.ES256;\n        case Algorithm.ES384:\n            return JWTAlgorithm.ES384;\n        case Algorithm.PS256:\n            return JWTAlgorithm.PS256;\n        case Algorithm.PS384:\n            return JWTAlgorithm.PS384;\n        case Algorithm.PS512:\n            return JWTAlgorithm.PS512;\n    }\n\n    throw new SyntaxError(`The algorithm ${input} is not supported.`);\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { JWKType, JWTError } from '@authup/specs';\nimport type { JWTClaims } from '@authup/specs';\nimport { Algorithm, sign } from '@node-rs/jsonwebtoken';\nimport { AsymmetricKey, SymmetricKey, encodePKCS8ToPEM } from '../../key';\nimport { transformJWTAlgorithmToInternal } from '../utils';\nimport type { TokenSignOptions } from './types';\n\nconst getUtcTimestamp = () => Math.floor(new Date().getTime() / 1000);\n\nexport async function signToken(claims: JWTClaims, context: TokenSignOptions): Promise<string> {\n    if (typeof claims.exp !== 'number') {\n        claims.exp = getUtcTimestamp() + 3600;\n    }\n    if (typeof claims.iat !== 'number') {\n        claims.iat = getUtcTimestamp();\n    }\n\n    switch (context.type) {\n        case JWKType.RSA:\n        case JWKType.EC: {\n            let algorithm : Algorithm;\n\n            let key : string;\n            if (typeof context.key === 'string') {\n                key = encodePKCS8ToPEM(context.key);\n            } else {\n                const keyContainer = new AsymmetricKey(context.key);\n                key = await keyContainer.toPem();\n            }\n\n            if (context.type === JWKType.RSA) {\n                algorithm = context.algorithm ?\n                    transformJWTAlgorithmToInternal(context.algorithm) :\n                    Algorithm.RS256;\n            } else {\n                algorithm = context.algorithm ?\n                    transformJWTAlgorithmToInternal(context.algorithm) :\n                    Algorithm.ES256;\n            }\n\n            return sign(claims, key, {\n                algorithm,\n                keyId: context.keyId,\n            });\n        }\n        case JWKType.OCT: {\n            const algorithm : Algorithm = context.algorithm ?\n                transformJWTAlgorithmToInternal(context.algorithm) :\n                Algorithm.HS256;\n\n            let key : string | Uint8Array;\n            if (typeof context.key === 'string') {\n                key = context.key;\n            } else {\n                const keyContainer = new SymmetricKey(context.key);\n                key = await keyContainer.toUint8Array();\n            }\n\n            return sign(claims, key, {\n                algorithm,\n                keyId: context.keyId,\n            });\n        }\n    }\n\n    throw new JWTError();\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { JWKType, JWTError } from '@authup/specs';\nimport type { JWTClaims, OAuth2TokenPayload } from '@authup/specs';\nimport { Algorithm, verify } from '@node-rs/jsonwebtoken';\nimport { AsymmetricKey, SymmetricKey, encodeSPKIToPem } from '../../key';\nimport { createErrorForJWTError, transformJWTAlgorithmToInternal } from '../utils';\nimport type { TokenVerifyOptions } from './types';\n\n/**\n * Verify JWT.\n *\n * @param token\n * @param context\n *\n * @throws OAuth2Error\n */\nexport async function verifyToken(\n    token: string,\n    context: TokenVerifyOptions,\n    options: { ignoreExpiry?: boolean } = {},\n) : Promise<OAuth2TokenPayload> {\n    let promise : Promise<JWTClaims> | undefined;\n\n    let output : JWTClaims | undefined;\n\n    // Signature, nbf and issuer/kind checks always apply; only exp is skipped\n    // when explicitly requested (e.g. an id_token_hint on RP-initiated logout).\n    const validateExp = !options.ignoreExpiry;\n\n    try {\n        switch (context.type) {\n            case JWKType.RSA:\n            case JWKType.EC: {\n                let algorithms : Algorithm[];\n\n                if (context.type === JWKType.RSA) {\n                    algorithms = context.algorithms ?\n                        context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) :\n                        [\n                            Algorithm.RS256,\n                            Algorithm.RS384,\n                            Algorithm.RS512,\n                            Algorithm.PS256,\n                            Algorithm.PS384,\n                            Algorithm.PS512,\n                        ];\n                } else {\n                    algorithms = context.algorithms ?\n                        context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) :\n                        [\n                            Algorithm.ES256,\n                            Algorithm.ES384,\n                        ];\n                }\n\n                let key : string;\n                if (typeof context.key === 'string') {\n                    key = encodeSPKIToPem(context.key);\n                } else {\n                    const keyContainer = new AsymmetricKey(context.key);\n                    key = await keyContainer.toPem();\n                }\n\n                promise = verify(token, key, {\n                    algorithms,\n                    validateNbf: true,\n                    validateExp,\n                });\n                break;\n            }\n            case JWKType.OCT: {\n                const algorithms : Algorithm[] = context.algorithms ?\n                    context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) :\n                    [\n                        Algorithm.HS256,\n                        Algorithm.HS384,\n                        Algorithm.HS512,\n                    ];\n\n                let key : string | Uint8Array;\n                if (typeof context.key === 'string') {\n                    key = context.key;\n                } else {\n                    const keyContainer = new SymmetricKey(context.key);\n                    key = await keyContainer.toUint8Array();\n                }\n\n                promise = verify(token, key, {\n                    algorithms,\n                    validateNbf: true,\n                    validateExp,\n                });\n            }\n        }\n\n        if (promise) {\n            output = await promise;\n        }\n    } catch (e) {\n        throw createErrorForJWTError(e);\n    }\n\n    if (!output) {\n        throw new JWTError();\n    }\n\n    return output as OAuth2TokenPayload;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { arrayBufferToBase64, base64ToArrayBuffer } from '@authup/kit';\nimport { getRandomValues, subtle } from 'uncrypto';\nimport { SymmetricAlgorithm } from '../key/symmetric/constants';\nimport { getKeyUsagesForSymmetricAlgorithm } from '../key/symmetric/key-usages';\nimport type { ISymmetricCipher } from './types';\n\nconst IV_BYTE_LENGTH = 12;\nconst KEY_BYTE_LENGTH = 32;\n\n/**\n * AES-256-GCM cipher over a base64-encoded 32-byte key. Blob format:\n * base64(iv ‖ ciphertext ‖ tag) — WebCrypto appends the GCM tag to the\n * ciphertext, so the layout is iv (12 bytes) followed by the sealed rest.\n */\nexport class SymmetricCipher implements ISymmetricCipher {\n    protected key : Promise<CryptoKey>;\n\n    constructor(key: string) {\n        // Validate the key SYNCHRONOUSLY so a bad key throws at construction\n        // (i.e. at boot / DI mount) — a clean startup error, never an\n        // unobserved promise rejection that only surfaces at first\n        // encrypt/decrypt. Only the subtle import (over already-validated\n        // 32-byte material) stays async, and it does not reject in practice.\n        const raw = base64ToArrayBuffer(key.trim());\n        if (raw.byteLength !== KEY_BYTE_LENGTH) {\n            throw new Error(`The cipher key must decode to ${KEY_BYTE_LENGTH} bytes (got ${raw.byteLength}).`);\n        }\n\n        this.key = subtle.importKey(\n            'raw',\n            raw,\n            { name: SymmetricAlgorithm.AES_GCM },\n            false,\n            getKeyUsagesForSymmetricAlgorithm(SymmetricAlgorithm.AES_GCM),\n        );\n    }\n\n    async encrypt(plain: string): Promise<string> {\n        const key = await this.key;\n\n        const iv = getRandomValues(new Uint8Array(IV_BYTE_LENGTH));\n        const sealed = await subtle.encrypt(\n            { name: SymmetricAlgorithm.AES_GCM, iv },\n            key,\n            new TextEncoder().encode(plain),\n        );\n\n        const blob = new Uint8Array(iv.byteLength + sealed.byteLength);\n        blob.set(iv, 0);\n        blob.set(new Uint8Array(sealed), iv.byteLength);\n\n        return arrayBufferToBase64(blob.buffer);\n    }\n\n    async decrypt(blob: string): Promise<string> {\n        const key = await this.key;\n\n        const raw = new Uint8Array(base64ToArrayBuffer(blob));\n        if (raw.byteLength <= IV_BYTE_LENGTH) {\n            throw new Error('The cipher blob is malformed.');\n        }\n\n        const plain = await subtle.decrypt(\n            { name: SymmetricAlgorithm.AES_GCM, iv: raw.subarray(0, IV_BYTE_LENGTH) },\n            key,\n            raw.subarray(IV_BYTE_LENGTH),\n        );\n\n        return new TextDecoder().decode(plain);\n    }\n}\n","/*\n * Copyright (c) 2023-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ObjectLiteral } from '@authup/kit';\nimport { isObject } from '@authup/kit';\nimport type { DomainEventChannelName } from './types';\n\nexport function transformDomainEventData<T extends ObjectLiteral>(input: T) : T {\n    const keys = Object.keys(input);\n    for (const key_ of keys) {\n        const key = key_ as keyof T;\n\n        const value = input[key] as T[keyof T];\n        if (!isObject(value)) {\n            continue;\n        }\n\n        if ((value as Record<string, any>) instanceof Date) {\n            input[key] = value.toISOString() as T[keyof T];\n        }\n    }\n\n    return input;\n}\n\nexport function buildDomainEventChannelName(\n    input: DomainEventChannelName,\n    id?: string | number,\n) : string {\n    if (typeof input === 'string') {\n        return input;\n    }\n\n    return input(id);\n}\n","/*\n * Copyright (c) 2023-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Client } from 'redis-extension';\nimport type { RedisClientCreateInput } from '../../../redis';\nimport { createRedisClient } from '../../../redis';\nimport type { DomainEventPublishContext, IDomainEventHandler } from '../../types';\nimport { buildDomainEventChannelName, transformDomainEventData } from '../../utils';\n\nexport class DomainEventRedisHandler implements IDomainEventHandler {\n    protected driver : Client;\n\n    constructor(input: RedisClientCreateInput) {\n        this.driver = createRedisClient(input);\n    }\n\n    async handle(ctx: DomainEventPublishContext) : Promise<void> {\n        const data = JSON.stringify(transformDomainEventData(ctx.content));\n\n        const pipeline = this.driver.pipeline();\n        for (let i = 0; i < ctx.destinations.length; i++) {\n            const { namespace } = ctx.destinations[i];\n            const keyPrefix = (namespace ? `${namespace}:` : '');\n\n            let key = keyPrefix + buildDomainEventChannelName(ctx.destinations[i].channel);\n            pipeline.publish(key, data);\n\n            if (typeof ctx.destinations[i].channel === 'function') {\n                key = keyPrefix + buildDomainEventChannelName(ctx.destinations[i].channel, ctx.content.data.id);\n                pipeline.publish(key, data);\n            }\n        }\n\n        await pipeline.exec();\n    }\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { buildEventFullName } from '@authup/core-realtime-kit';\nimport { Emitter } from '@socket.io/redis-emitter';\nimport type { RedisClientCreateInput } from '../../../redis';\nimport { createRedisClient } from '../../../redis';\nimport type { DomainEventPublishContext, IDomainEventHandler } from '../../types';\nimport { buildDomainEventChannelName, transformDomainEventData } from '../../utils';\n\nexport class DomainEventSocketHandler implements IDomainEventHandler {\n    protected driver : Emitter;\n\n    constructor(input: RedisClientCreateInput) {\n        const client = createRedisClient(input);\n        this.driver = new Emitter(client);\n    }\n\n    async handle(ctx: DomainEventPublishContext) : Promise<void> {\n        ctx.content = transformDomainEventData(ctx.content);\n\n        for (let i = 0; i < ctx.destinations.length; i++) {\n            const destination = ctx.destinations[i];\n\n            let emitter : Emitter;\n\n            if (destination.namespace) {\n                emitter = this.driver.of(destination.namespace);\n            } else {\n                emitter = this.driver;\n            }\n\n            let roomName = buildDomainEventChannelName(destination.channel);\n\n            const fullEventName = buildEventFullName(ctx.content.type, ctx.content.event);\n\n            emitter\n                .in(roomName)\n                .emit(fullEventName, {\n                    ...ctx.content,\n                    meta: { roomName },\n                });\n\n            if (typeof destination.channel === 'function') {\n                roomName = buildDomainEventChannelName(destination.channel, ctx.content.data.id);\n\n                emitter\n                    .in(roomName)\n                    .emit(fullEventName, {\n                        ...ctx.content,\n                        meta: {\n                            roomName,\n                            roomId: ctx.content.data.id,\n                        },\n                    });\n            }\n        }\n    }\n}\n","/*\n * Copyright (c) 2024-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { buildEventFullName } from '@authup/core-realtime-kit';\nimport type { EventPayload } from '@authup/core-realtime-kit';\nimport type { Logger } from '../logger';\nimport type {\n    DomainEventPublishContext,\n    IDomainEventHandler,\n    IDomainEventPublisher,\n} from './types';\n\nexport type DomainEventPublisherContext = {\n    logger?: Logger\n};\n\nexport class DomainEventPublisher implements IDomainEventPublisher {\n    protected handlers : Set<IDomainEventHandler>;\n\n    protected logger? : Logger;\n\n    constructor(ctx: DomainEventPublisherContext = {}) {\n        this.handlers = new Set<IDomainEventHandler>();\n        this.logger = ctx.logger;\n    }\n\n    register(handler: IDomainEventHandler): void {\n        this.handlers.add(handler);\n    }\n\n    async dispose() : Promise<void> {\n        for (const handler of this.handlers) {\n            if (handler.dispose) {\n                await handler.dispose();\n            }\n        }\n\n        this.handlers.clear();\n    }\n\n    async safePublish<T extends EventPayload>(\n        ctx: DomainEventPublishContext<T>,\n    ) : Promise<void> {\n        try {\n            await this.publish(ctx);\n        } catch (e) {\n            if (this.logger) {\n                this.logger.error(`Publishing event ${buildEventFullName(ctx.content.type, ctx.content.event)} failed.`);\n                this.logger.error(e);\n            }\n        }\n    }\n\n    async publish<T extends EventPayload>(\n        ctx: DomainEventPublishContext<T>,\n    ) : Promise<void> {\n        if (this.handlers.size === 0) {\n            return;\n        }\n\n        if (this.logger) {\n            this.logger.debug(`Publishing event ${buildEventFullName(ctx.content.type, ctx.content.event)}...`);\n        }\n\n        const handlers = this.handlers.values();\n        while (true) {\n            const it = handlers.next();\n            if (it.done) {\n                return;\n            }\n\n            await it.value.handle(ctx);\n        }\n    }\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\nimport process from 'node:process';\nimport type { LoggerOptions } from 'winston';\nimport { createLogger as create, format, transports } from 'winston';\nimport type { Logger, LoggerCreateContext } from './types';\n\nexport function createNoopLogger() : Logger {\n    return create({ silent: true });\n}\n\nexport function createLogger(context: LoggerCreateContext) : Logger {\n    let items : LoggerOptions['transports'];\n\n    const cwd = context.directory || process.cwd();\n\n    if (context.env === 'production') {\n        items = [\n            new transports.Console({ level: 'info' }),\n            new transports.File({\n                filename: path.join(cwd, 'http.log'),\n                level: 'http',\n                maxsize: 10 * 1024 * 1024, // 10MB\n                maxFiles: 5,\n            }),\n            new transports.File({\n                filename: path.join(cwd, 'error.log'),\n                level: 'warn',\n                maxsize: 10 * 1024 * 1024, // 10MB\n                maxFiles: 5,\n            }),\n        ];\n    } else {\n        items = [\n            new transports.Console({ level: 'debug' }),\n        ];\n    }\n\n    // @see https://github.com/winstonjs/triple-beam/blob/master/config/npm.js\n    return create({\n        format: format.combine(\n            format.errors({ stack: true }),\n            format.timestamp(),\n            format.colorize(),\n            format.simple(),\n        ),\n        transports: items,\n    });\n}\n","/*\n * Copyright (c) 2022-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function hasOwnProperty<X extends Record<string, any>, Y extends PropertyKey>(\n    obj: X,\n    prop: Y,\n): obj is X & Record<Y, unknown> {\n    return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n"],"mappings":"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"}