@nice-code/util 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["fromBase64","fromJwk","fromSerializedObject","fromFormattedString","extractableOrNonExtractable"],"sources":["../src/data_type/string/nullEmpty.ts","../src/crypto/x25519/createSharedBitsFromX25519.ts","../src/crypto/aes_gcm/createAesGcmKeyFromX25519Keys.ts","../src/crypto/aes_gcm/decryptBytesWithAesGcmKey.ts","../src/crypto/aes_gcm/decryptTextDataWithAesGcmKey.ts","../src/crypto/aes_gcm/encryptBytesWithAesGcmKey.ts","../src/crypto/aes_gcm/encryptTextDataWithAesGcmKey.ts","../src/crypto/ed25519/signTextDataWithKeyEd25519.ts","../src/crypto/ed25519/signCombinedTextDataWithKeyEd25519.ts","../src/crypto/client_key_link/buildVerifyKeyBoundInfoString.ts","../src/storage_adapter/typed_storage/createTypedStorage.ts","../src/crypto/ed25519/generateEd25519KeyPair.ts","../src/core/createDataStringConverter_stringToObject.ts","../src/core/core_valibot_schemas.ts","../src/crypto/crypto.schema.ts","../src/crypto/crypto.converters.ts","../src/crypto/ed25519/importEd25519Key.ts","../src/crypto/ed25519/serializeEd25519Key_Jwk.ts","../src/crypto/ed25519/serializeEd25519Key_Raw.ts","../src/crypto/ed25519/verifyWithKeyEd25519.ts","../src/crypto/x25519/generateX25519KeyPair.ts","../src/crypto/x25519/importX25519Key.ts","../src/crypto/x25519/serializeX25519Key_Jwk.ts","../src/crypto/x25519/serializeX25519Key_Raw.ts","../src/crypto/client_key_link/ClientCryptoKeyLink.ts","../src/storage_adapter/storage_adapter.types.ts","../src/storage_adapter/StorageAdapter.ts","../src/storage_adapter/specific/browser/browser_storage.ts","../src/storage_adapter/specific/cloudflare/durable_object/durable_object_storage.ts","../src/storage_adapter/specific/cloudflare/kv/kv_storage.ts","../src/storage_adapter/specific/memory/memory_storage.ts"],"sourcesContent":["export const notNullEmpty = (str: string | null | undefined): str is string => {\n return str != null && str.length > 0;\n};\n\nexport const nullEmpty = (str: string | null | undefined): str is null | undefined | \"\" => {\n return !notNullEmpty(str);\n};\n\nexport const firstNotNullEmpty = (\n ...strItems: (string | null | undefined)[]\n): string | undefined => {\n for (const item of strItems) {\n if (notNullEmpty(item)) {\n return item;\n }\n }\n\n return undefined;\n};\n","export const createSharedBitsFromX25519 = async ({\n privateKey,\n publicKey,\n}: {\n privateKey: CryptoKey;\n publicKey: CryptoKey;\n}): Promise<Uint8Array> => {\n return new Uint8Array(\n await crypto.subtle.deriveBits({ name: \"X25519\", public: publicKey }, privateKey, 256),\n );\n};\n","import { notNullEmpty } from \"../../data_type/string/nullEmpty\";\nimport { createSharedBitsFromX25519 } from \"../x25519/createSharedBitsFromX25519\";\n\nconst DEFAULT_INFO_STRING = \"METEOR_BRIDGE_DEFAULT_INFO_STRING\";\n\nexport const createAesGcmKeyFromX25519Keys = async ({\n externalX25519PublicKey,\n internalX25519PrivateKey,\n infoString,\n saltString,\n}: {\n internalX25519PrivateKey: CryptoKey;\n externalX25519PublicKey: CryptoKey;\n saltString?: string;\n infoString?: string;\n}): Promise<CryptoKey> => {\n const sharedBits = await createSharedBitsFromX25519({\n privateKey: internalX25519PrivateKey,\n publicKey: externalX25519PublicKey,\n });\n\n // Initial Key Material\n const ikm = await crypto.subtle.importKey(\"raw\", new Uint8Array(sharedBits), \"HKDF\", false, [\n \"deriveKey\",\n ]);\n\n const salt = notNullEmpty(saltString) ? new TextEncoder().encode(saltString) : new Uint8Array();\n const info = new TextEncoder().encode(\n notNullEmpty(infoString) ? infoString : DEFAULT_INFO_STRING,\n );\n\n // Run HKDF to get your final usable key (e.g., AES-GCM)\n return await crypto.subtle.deriveKey(\n {\n name: \"HKDF\",\n hash: \"SHA-256\",\n salt, // Salt\n info, // Context string\n },\n ikm,\n { name: \"AES-GCM\", length: 256 },\n false, // The final AES key shouldn't be exportable\n [\"encrypt\", \"decrypt\"],\n );\n};\n","import type { TEncryptedAesGcmBytes } from \"../crypto.schema\";\r\n\r\n/**\r\n * Decrypts a raw-bytes AES-GCM payload (binary nonce + ciphertext) back to bytes. The counterpart of\r\n * {@link decryptTextDataWithAesGcmKey}. AES-GCM verifies integrity, so a tampered ciphertext throws.\r\n */\r\nexport const decryptBytesWithAesGcmKey = async ({\r\n aesGcmKey,\r\n dataToDecrypt,\r\n}: {\r\n aesGcmKey: CryptoKey;\r\n dataToDecrypt: TEncryptedAesGcmBytes;\r\n}): Promise<Uint8Array> => {\r\n const decryptedData = await crypto.subtle.decrypt(\r\n // Re-view nonce + ciphertext over plain ArrayBuffers so WebCrypto's `BufferSource` is satisfied\r\n // regardless of the source's backing buffer (msgpack output may be pooled / SharedArrayBuffer-typed).\r\n { name: \"AES-GCM\", iv: new Uint8Array(dataToDecrypt.nonce) },\r\n aesGcmKey,\r\n new Uint8Array(dataToDecrypt.ciphertext),\r\n );\r\n\r\n return new Uint8Array(decryptedData);\r\n};\r\n","import { base64 } from \"@scure/base\";\nimport type { TEncryptedAesGcmPayload } from \"../crypto.schema\";\n\nexport const decryptTextDataWithAesGcmKey = async ({\n aesGcmKey,\n dataToDecrypt,\n}: {\n aesGcmKey: CryptoKey;\n dataToDecrypt: TEncryptedAesGcmPayload;\n}): Promise<string> => {\n const decryptedData = await crypto.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(base64.decode(dataToDecrypt.nonce)),\n },\n aesGcmKey,\n new Uint8Array(base64.decode(dataToDecrypt.ciphertext)),\n );\n\n return new TextDecoder().decode(decryptedData);\n};\n","import type { TEncryptedAesGcmBytes } from \"../crypto.schema\";\r\n\r\n/**\r\n * Encrypts raw bytes with an AES-GCM key, returning the binary nonce + ciphertext. The bytes\r\n * counterpart of {@link encryptTextDataWithAesGcmKey} — use it for binary channels (msgpack frames)\r\n * to avoid base64 inflation. A fresh 12-byte nonce is generated per call (never reuse a nonce).\r\n */\r\nexport const encryptBytesWithAesGcmKey = async ({\r\n aesGcmKey,\r\n dataToEncrypt,\r\n}: {\r\n aesGcmKey: CryptoKey;\r\n dataToEncrypt: Uint8Array;\r\n}): Promise<TEncryptedAesGcmBytes> => {\r\n const nonce = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encryptedData = await crypto.subtle.encrypt(\r\n { name: \"AES-GCM\", iv: nonce },\r\n aesGcmKey,\r\n // Re-view over a plain ArrayBuffer so WebCrypto's `BufferSource` is satisfied regardless of the\r\n // source's backing buffer (msgpack output may be pooled / SharedArrayBuffer-typed).\r\n new Uint8Array(dataToEncrypt),\r\n );\r\n\r\n return { nonce, ciphertext: new Uint8Array(encryptedData) };\r\n};\r\n","import { base64 } from \"@scure/base\";\nimport type { TEncryptedAesGcmPayload } from \"../crypto.schema\";\n\nexport const encryptTextDataWithAesGcmKey = async ({\n aesGcmKey,\n dataToEncrypt,\n}: {\n aesGcmKey: CryptoKey;\n dataToEncrypt: string;\n}): Promise<TEncryptedAesGcmPayload> => {\n const nonce = crypto.getRandomValues(new Uint8Array(12));\n\n const encryptedData = await crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: nonce,\n },\n aesGcmKey,\n new TextEncoder().encode(dataToEncrypt),\n );\n\n return {\n nonce: base64.encode(nonce),\n ciphertext: base64.encode(new Uint8Array(encryptedData)),\n };\n};\n","export const signTextDataWithKeyEd25519 = async (\n data: string,\n cryptoKey: CryptoKey,\n): Promise<Uint8Array> => {\n const dataBuffer = new TextEncoder().encode(data);\n const signature = await crypto.subtle.sign(\n {\n name: \"ED25519\",\n },\n cryptoKey,\n dataBuffer,\n );\n\n return new Uint8Array(signature);\n};\n","import { signTextDataWithKeyEd25519 } from \"./signTextDataWithKeyEd25519\";\n\nexport const DEFAULT_COMBINED_TEXT_DATA_SEPARATOR = \"::\";\n\nexport const signCombinedTextDataWithKeyEd25519 = async (\n data: string[],\n cryptoKey: CryptoKey,\n separator = DEFAULT_COMBINED_TEXT_DATA_SEPARATOR,\n): Promise<Uint8Array> => {\n return await signTextDataWithKeyEd25519(data.join(separator), cryptoKey);\n};\n","import type { TSerializedCryptoKeyData_Ed25519_Raw } from \"../crypto.schema\";\nimport { DEFAULT_COMBINED_TEXT_DATA_SEPARATOR } from \"../ed25519/signCombinedTextDataWithKeyEd25519\";\n\ninterface IBuildVerifyKeyBoundInfoString_Input {\n infoString?: string;\n verifyPublicKeys: [TSerializedCryptoKeyData_Ed25519_Raw, TSerializedCryptoKeyData_Ed25519_Raw];\n}\n\n/**\n * The canonical HKDF `info` for a client-to-client shared key that binds both sides' verify\n * public keys into the derivation.\n *\n * When the two keys are relayed through an intermediary, a tampered key produces mismatched AES\n * keys on the two sides — the very first decryption fails, so key substitution is detected without\n * any extra signature ceremony.\n *\n * The keys are sorted lexicographically so the result is independent of which side is \"local\" —\n * both ends of a link compute the identical string without coordinating an order. Used internally\n * by ClientCryptoKeyLink (`bindVerifyKeysIntoDerivation`); exported for code that derives the same\n * key outside the link.\n */\nexport const buildVerifyKeyBoundInfoString = ({\n infoString,\n verifyPublicKeys,\n}: IBuildVerifyKeyBoundInfoString_Input): string => {\n const sortedKeys = [...verifyPublicKeys].sort();\n\n return [...(infoString != null ? [infoString] : []), ...sortedKeys].join(\n DEFAULT_COMBINED_TEXT_DATA_SEPARATOR,\n );\n};\n","import type { StringKeys } from \"../../typescript/special_typescript_types\";\nimport type { StorageAdapter } from \"../StorageAdapter\";\n\nexport interface ITypedStorage<T extends Record<string, any>> {\n getJson<K extends StringKeys<T>>(key: K): Promise<T[K] | undefined>;\n getJsonOrDef<K extends StringKeys<T>>(key: K, defVal: T[K]): Promise<T[K]>;\n setJson<K extends StringKeys<T>>(key: K, val: T[K]): Promise<void>;\n removeItem<K extends StringKeys<T>>(key: K): Promise<void>;\n updateJson<K extends StringKeys<T>>(\n key: K,\n updater: (currentVal: T[K] | undefined) => T[K],\n ): Promise<void>;\n updateJsonWithDef<K extends StringKeys<T>>(\n key: K,\n defaultVal: T[K],\n updater: (currentVal: T[K]) => T[K],\n ): Promise<void>;\n clearAll(): Promise<void>;\n}\n\ninterface ITypedStorage_Create_Input {\n storageAdapter: StorageAdapter;\n}\n\nexport function createTypedStorage<T extends Record<string, any>>({\n storageAdapter,\n}: ITypedStorage_Create_Input): ITypedStorage<T> {\n const getJson = async <K extends StringKeys<T>>(key: K): Promise<T[K] | undefined> => {\n return storageAdapter.getJson<T[K]>(key);\n };\n\n const getJsonOrDef = async <K extends StringKeys<T>>(key: K, defVal: T[K]): Promise<T[K]> => {\n return (await storageAdapter.getJson<T[K]>(key)) ?? defVal;\n };\n\n const setJson = async <K extends StringKeys<T>>(key: K, val: T[K]): Promise<void> => {\n return storageAdapter.setJson(key, val);\n };\n\n const removeItem = async <K extends StringKeys<T>>(key: K): Promise<void> => {\n await storageAdapter.removeItem(key);\n };\n\n const updateJson = async <K extends StringKeys<T>>(\n key: K,\n updater: (currentVal: T[K] | undefined) => T[K],\n ): Promise<void> => {\n await storageAdapter.updateJson(key, updater);\n };\n\n const updateJsonWithDef = async <K extends StringKeys<T>>(\n key: K,\n defaultVal: T[K],\n updater: (currentVal: T[K]) => T[K],\n ): Promise<void> => {\n await storageAdapter.updateJsonOrDef(key, defaultVal, updater);\n };\n\n return {\n getJson,\n getJsonOrDef,\n setJson,\n removeItem,\n updateJson,\n updateJsonWithDef,\n clearAll: async () => {\n await storageAdapter.clearAll();\n },\n };\n}\n","export const generateEd25519KeyPair = async (): Promise<CryptoKeyPair> => {\n const keyPair = (await crypto.subtle.generateKey({ name: \"Ed25519\" }, true, [\n \"sign\",\n \"verify\",\n ])) as CryptoKeyPair;\n\n return keyPair;\n};\n","import type { ECryptoKeyFormat } from \"../crypto/crypto.schema\";\n\ninterface ICreateDataStringConverter_StringToObject {\n transformJsonForFormats?: ECryptoKeyFormat[];\n transformJson?: boolean;\n}\n\nexport const createDataStringConverter_stringToObject =\n <T extends string, F extends ECryptoKeyFormat, D = string>({\n transformJsonForFormats = [],\n transformJson = false,\n }: ICreateDataStringConverter_StringToObject = {}) =>\n (\n inputDataString: `${T}::${F}::${string}`,\n ): { formattedString: `${T}::${F}::${string}`; type: T; format: F; data: D } => {\n const [type, format, dataString] = inputDataString.split(\"::\") as [\n string,\n ECryptoKeyFormat,\n string,\n ];\n let parsedData: D = dataString as D;\n\n if (transformJson || transformJsonForFormats.includes(format)) {\n try {\n parsedData = JSON.parse(dataString) as D;\n } catch (error) {\n const err = new Error(\n `Failed to parse type and format data string. Given input: \"${inputDataString}\", expected JSON parsable \"data\" value in the format \"${type}::${format}::data\" ${error instanceof Error ? error.message : String(error)}`,\n );\n\n err.cause = error;\n throw err;\n }\n }\n\n return {\n formattedString: inputDataString,\n type: type as T,\n format: format as F,\n data: parsedData,\n };\n };\n","import * as v from \"valibot\";\n\n// export const vBase64HashSha256 = v.pipe(v.string(), v.base64());\nexport const vBase64 = v.pipe(v.string(), v.base64());\n\nexport const vCreateSchema_TypePrefixedDataString = <P extends string>(\n typeValues: P[],\n typeKind: string,\n) => {\n const _typeKind = typeKind ?? \"data_type\";\n\n return v.pipe(\n v.custom<`${P}::${string}`>(\n (input) => {\n return (\n typeof input === \"string\" && typeValues.some((prefix) => input.startsWith(`${prefix}::`))\n );\n },\n `Invalid format, expected '<${_typeKind}>::<value>' where \"${_typeKind}\" is one of [${typeValues.join(\", \")}] and \"value\" is a string of base64-encoded data of that type`,\n ),\n );\n};\n\nexport interface ICreateTypePrefixedDataStringResult<T extends string, F extends string> {\n type: T;\n format: F;\n typeKind: string;\n formatKind?: string;\n transformJson?: boolean;\n}\n\nexport const vCreateSchema_TypeAndFormatPrefixedDataString = <T extends string, F extends string>({\n type,\n format,\n typeKind,\n formatKind,\n // transformJson = false,\n}: ICreateTypePrefixedDataStringResult<T, F>) => {\n const _typeKind = typeKind ?? \"data_type\";\n const _formatKind = formatKind ?? \"data_format\";\n\n return v.pipe(\n v.custom<`${T}::${F}::${string}`>((input) => {\n if (typeof input !== \"string\") return false;\n\n const [typePart, formatPart, dataPart] = input.split(\"::\") as [string, string, string];\n\n return typePart === type && formatPart === format && typeof dataPart === \"string\";\n }, `Invalid format, expected '<${_typeKind}>::<${_formatKind}>::<value>' where \"${_typeKind}\" is \"${type}\", \"${_formatKind}\" is \"${format}\", and \"value\" is a string in the specified format`),\n );\n};\n\nexport const vCreateSchema_TypeAndId = <S extends string>(dataType: S | S[]) =>\n v.pipe(\n v.custom<`${S}::${string}`>((input) => {\n if (typeof input !== \"string\") {\n return false;\n }\n\n let checkDataTypes: string[];\n\n if (typeof dataType === \"string\") {\n checkDataTypes = [dataType];\n } else if (Array.isArray(dataType)) {\n checkDataTypes = dataType;\n } else {\n throw new Error(\n \"Create Schema for TypeAndId: dataType must be a string or an array of strings\",\n );\n }\n\n if (checkDataTypes.length > 0) {\n return true;\n }\n\n for (const dataTypeCheck in checkDataTypes) {\n if (input.startsWith(`${dataTypeCheck}::`)) return true;\n }\n\n return false;\n }, `Invalid Type and ID formatted string, expected '<data_type>::<id>'`),\n );\n\nexport type TTypeAndId<S extends string = string> = `${S}::${string}`;\n","import * as v from \"valibot\";\r\nimport {\r\n vBase64,\r\n vCreateSchema_TypeAndFormatPrefixedDataString,\r\n} from \"../core/core_valibot_schemas\";\r\n\r\nexport enum ECryptoKeyAlgo {\r\n ed25519 = \"ed25519\",\r\n x25519 = \"x25519\",\r\n}\r\n\r\nexport enum ECryptoKeyFormat {\r\n raw_base64 = \"raw_base64\",\r\n jwk = \"jwk\",\r\n}\r\n\r\nexport const vSerializedCryptoKeyDataEd25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.ed25519,\r\n ECryptoKeyFormat.raw_base64\r\n>({\r\n format: ECryptoKeyFormat.raw_base64,\r\n type: ECryptoKeyAlgo.ed25519,\r\n typeKind: \"algo\",\r\n});\r\n\r\nexport const vSerializedCryptoKeyDataEd25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.ed25519,\r\n ECryptoKeyFormat.jwk\r\n>({\r\n format: ECryptoKeyFormat.jwk,\r\n type: ECryptoKeyAlgo.ed25519,\r\n typeKind: \"algo\",\r\n transformJson: true,\r\n});\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Raw = v.InferInput<\r\n typeof vSerializedCryptoKeyDataEd25519_Raw\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Raw_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.raw_base64}::${string}`;\r\n type: ECryptoKeyAlgo.ed25519;\r\n format: ECryptoKeyFormat.raw_base64;\r\n data: string;\r\n};\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Jwk = v.InferInput<\r\n typeof vSerializedCryptoKeyDataEd25519_Jwk\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.jwk}::${string}`;\r\n type: ECryptoKeyAlgo.ed25519;\r\n format: ECryptoKeyFormat.jwk;\r\n data: JsonWebKey;\r\n};\r\n\r\nexport const vSerializedCryptoKeyDataX25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.x25519,\r\n ECryptoKeyFormat.raw_base64\r\n>({\r\n format: ECryptoKeyFormat.raw_base64,\r\n type: ECryptoKeyAlgo.x25519,\r\n typeKind: \"algo\",\r\n});\r\n\r\nexport const vSerializedCryptoKeyDataX25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.x25519,\r\n ECryptoKeyFormat.jwk\r\n>({\r\n format: ECryptoKeyFormat.jwk,\r\n type: ECryptoKeyAlgo.x25519,\r\n typeKind: \"algo\",\r\n transformJson: true,\r\n});\r\n\r\nexport const vCryptoKeyPairDataX25519 = v.object({\r\n publicKey: vSerializedCryptoKeyDataX25519_Raw,\r\n privateKey: vSerializedCryptoKeyDataX25519_Jwk,\r\n});\r\n\r\nexport type TSerializedCryptoKeyPairDataX25519 = v.InferInput<typeof vCryptoKeyPairDataX25519>;\r\n\r\nexport const vCryptoKeyPairDataEd25519 = v.object({\r\n publicKey: vSerializedCryptoKeyDataEd25519_Raw,\r\n privateKey: vSerializedCryptoKeyDataEd25519_Jwk,\r\n});\r\n\r\nexport type TSerializedCryptoKeyPairDataEd25519 = v.InferInput<typeof vCryptoKeyPairDataEd25519>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Raw = v.InferInput<\r\n typeof vSerializedCryptoKeyDataX25519_Raw\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Raw_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.raw_base64}::${string}`;\r\n type: ECryptoKeyAlgo.x25519;\r\n format: ECryptoKeyFormat.raw_base64;\r\n data: string;\r\n};\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Jwk = v.InferInput<\r\n typeof vSerializedCryptoKeyDataX25519_Jwk\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Jwk_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.jwk}::${string}`;\r\n type: ECryptoKeyAlgo.x25519;\r\n format: ECryptoKeyFormat.jwk;\r\n data: JsonWebKey;\r\n};\r\n\r\nexport const vVerifyChallengeWithSignature_Input = v.object({\r\n challenge: v.string(),\r\n signatureBase64: vBase64,\r\n});\r\n\r\nexport const vVerifyChallengeWithSignature_WithThrow_Input = v.intersect([\r\n vVerifyChallengeWithSignature_Input,\r\n v.object({\r\n throwOnInvalid: v.optional(v.boolean()),\r\n }),\r\n]);\r\n\r\nexport type TVerifyChallengeWithSignature_Input = v.InferInput<\r\n typeof vVerifyChallengeWithSignature_Input\r\n>;\r\n\r\nexport type TVerifyChallengeWithSignature_WithThrow_Input = v.InferInput<\r\n typeof vVerifyChallengeWithSignature_WithThrow_Input\r\n>;\r\n\r\nexport const vEncryptedAesGcmPayload = v.object({\r\n nonce: vBase64,\r\n ciphertext: vBase64,\r\n});\r\n\r\nexport type TEncryptedAesGcmPayload = v.InferInput<typeof vEncryptedAesGcmPayload>;\r\nexport type TEncryptedAesGcmPayload_Transformed = v.InferOutput<typeof vEncryptedAesGcmPayload>;\r\n\r\n/**\r\n * Raw-bytes counterpart of {@link TEncryptedAesGcmPayload} — keeps `nonce`/`ciphertext` as binary\r\n * instead of base64 strings. For binary channels (e.g. msgpack WebSocket frames) this avoids the\r\n * ~33% base64 inflation the text payload incurs.\r\n */\r\nexport type TEncryptedAesGcmBytes = {\r\n nonce: Uint8Array;\r\n ciphertext: Uint8Array;\r\n};\r\n\r\ninterface ISerializedKeyData<T, P> {\r\n transformed: T;\r\n prefixed: P;\r\n}\r\n\r\nexport interface ISerializedKeyData_Ed25519_Raw\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\r\n TSerializedCryptoKeyData_Ed25519_Raw\r\n > {}\r\n\r\nexport interface ISerializedKeyData_Ed25519_Jwk\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\r\n TSerializedCryptoKeyData_Ed25519_Jwk\r\n > {}\r\n\r\nexport interface ISerializedKeyData_X25519_Raw\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_X25519_Raw_Transformed,\r\n TSerializedCryptoKeyData_X25519_Raw\r\n > {}\r\n\r\nexport interface ISerializedKeyData_X25519_Jwk\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_X25519_Jwk_Transformed,\r\n TSerializedCryptoKeyData_X25519_Jwk\r\n > {}\r\n\r\nexport type TSerializedKeyData =\r\n | ISerializedKeyData_Ed25519_Raw\r\n | ISerializedKeyData_Ed25519_Jwk\r\n | ISerializedKeyData_X25519_Raw\r\n | ISerializedKeyData_X25519_Jwk;\r\n","import { createDataStringConverter_stringToObject } from \"../core/createDataStringConverter_stringToObject\";\nimport {\n type ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Jwk,\n type ISerializedKeyData_Ed25519_Raw,\n type ISerializedKeyData_X25519_Jwk,\n type ISerializedKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n type TSerializedCryptoKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"./crypto.schema\";\n\n/**\n *\n * [CRYPTO ALGO] ED25519\n *\n */\n\nexport const convertEd25519RawDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.raw_base64\n>();\n\nexport const convertEd25519JwkDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.jwk,\n JsonWebKey\n>({ transformJson: true });\n\nexport const convertEd25519FormattedStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.raw_base64 | ECryptoKeyFormat.jwk\n>({\n transformJsonForFormats: [ECryptoKeyFormat.jwk],\n});\n\nexport const convertEd25519RawDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_Ed25519_Raw,\n): ISerializedKeyData_Ed25519_Raw => {\n const transformed = convertEd25519RawDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertEd25519JwkDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_Ed25519_Jwk,\n): ISerializedKeyData_Ed25519_Jwk => {\n const transformed = convertEd25519JwkDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertEd25519FormattedStringToSerializedKeyData = <\n I extends TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk,\n O extends I extends TSerializedCryptoKeyData_Ed25519_Raw\n ? TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n : TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n>(\n input: I,\n): O => {\n return convertEd25519FormattedStringToObject(input) as O;\n};\n\n/**\n *\n * [CRYPTO ALGO] X25519\n *\n */\n\nexport const convertX25519RawDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.raw_base64\n>();\n\nexport const convertX25519JwkDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.jwk,\n JsonWebKey\n>({ transformJson: true });\n\nexport const convertX25519FormattedStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.raw_base64 | ECryptoKeyFormat.jwk\n>({\n transformJsonForFormats: [ECryptoKeyFormat.jwk],\n});\n\nexport const convertX25519RawDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_X25519_Raw,\n): ISerializedKeyData_X25519_Raw => {\n const transformed = convertX25519RawDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertX25519JwkDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_X25519_Jwk,\n): ISerializedKeyData_X25519_Jwk => {\n const transformed = convertX25519JwkDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertX25519FormattedStringToSerializedKeyData = <\n I extends TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk,\n O extends I extends TSerializedCryptoKeyData_X25519_Raw\n ? TSerializedCryptoKeyData_X25519_Raw_Transformed\n : TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n>(\n input: I,\n): O => {\n return convertX25519FormattedStringToObject(input) as O;\n};\n","import { base64 } from \"@scure/base\";\nimport { convertEd25519FormattedStringToSerializedKeyData } from \"../crypto.converters\";\nimport {\n ECryptoKeyFormat,\n type TSerializedCryptoKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nconst fromBase64 = async (\n dataBase64: string,\n keyUsage: KeyUsage[],\n extractable: boolean,\n): Promise<CryptoKey> => {\n const keyBuffer = Uint8Array.from(base64.decode(dataBase64));\n\n return await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"Ed25519\" },\n extractable,\n keyUsage,\n );\n};\n\nconst fromJwk = async (\n jwk: JsonWebKey,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n return await crypto.subtle.importKey(\"jwk\", jwk, { name: \"Ed25519\" }, extractable, keyUsage);\n};\n\nconst fromSerializedObject = async <\n D extends\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed =\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n>(\n serialized: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n if (serialized.format === ECryptoKeyFormat.jwk) {\n return await fromJwk(serialized.data, keyUsage, extractable);\n }\n\n return await fromBase64(serialized.data, keyUsage, extractable);\n};\n\nconst fromFormattedString = async <\n D extends TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk =\n | TSerializedCryptoKeyData_Ed25519_Raw\n | TSerializedCryptoKeyData_Ed25519_Jwk,\n>(\n dataString: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n const transformed = convertEd25519FormattedStringToSerializedKeyData(dataString);\n return await fromSerializedObject(transformed, keyUsage, extractable);\n};\n\nconst extractableOrNonExtractable = <I>(\n keyUsage: KeyUsage[],\n func: (input: I, keyUsage: KeyUsage[], extractable: boolean) => Promise<CryptoKey>,\n) =>\n ({\n extractable: (input: I) => func(input, keyUsage, true),\n nonExtractable: (input: I) => func(input, keyUsage, false),\n }) as const;\n\nexport const importEd25519Key = {\n private: {\n fromFormattedString: extractableOrNonExtractable(\n [\"sign\"],\n fromFormattedString<TSerializedCryptoKeyData_Ed25519_Jwk>,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"sign\"],\n fromSerializedObject<TSerializedCryptoKeyData_Ed25519_Jwk_Transformed>,\n ),\n fromJwk: extractableOrNonExtractable([\"sign\"], fromJwk),\n },\n public: {\n fromBase64: extractableOrNonExtractable([\"verify\"], fromBase64),\n fromFormattedString: extractableOrNonExtractable(\n [\"verify\"],\n fromFormattedString<\n TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk\n >,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"verify\"],\n fromSerializedObject<\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed\n >,\n ),\n fromJwk: extractableOrNonExtractable([\"verify\"], fromJwk),\n },\n};\n","import {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeEd25519Key_Jwk = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_Ed25519_Jwk> => {\n const keyJwk = await crypto.subtle.exportKey(\"jwk\", key);\n\n const prefixed =\n `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.jwk}::${JSON.stringify(keyJwk)}` as const;\n\n const transformed: TSerializedCryptoKeyData_Ed25519_Jwk_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.ed25519,\n data: keyJwk,\n format: ECryptoKeyFormat.jwk,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\nimport {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeEd25519Key_Raw = async (\n publicKey: CryptoKey,\n): Promise<ISerializedKeyData_Ed25519_Raw> => {\n const publicKeyBuffer = await crypto.subtle.exportKey(\"raw\", publicKey);\n const publicKeyBase64 = base64.encode(new Uint8Array(publicKeyBuffer));\n\n const prefixed =\n `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.raw_base64}::${publicKeyBase64}` as const;\n\n const transformed: TSerializedCryptoKeyData_Ed25519_Raw_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.ed25519,\n data: publicKeyBase64,\n format: ECryptoKeyFormat.raw_base64,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\n\nexport const verifyWithKeyEd25519 = async ({\n challenge,\n signatureBase64,\n publicKey,\n}: {\n challenge: string;\n signatureBase64: string;\n publicKey: CryptoKey;\n}): Promise<boolean> => {\n const signatureBuffer = Uint8Array.from(base64.decode(signatureBase64));\n const challengeBuffer = new TextEncoder().encode(challenge);\n\n return await crypto.subtle.verify(\n {\n name: \"ED25519\",\n },\n publicKey,\n signatureBuffer,\n challengeBuffer,\n );\n};\n","export const generateX25519KeyPair = async (): Promise<CryptoKeyPair> => {\n const keyPair = (await crypto.subtle.generateKey({ name: \"X25519\" }, true, [\n \"deriveKey\",\n \"deriveBits\",\n ])) as CryptoKeyPair;\n\n return keyPair;\n};\n","import { base64 } from \"@scure/base\";\nimport { convertX25519FormattedStringToSerializedKeyData } from \"../crypto.converters\";\nimport {\n ECryptoKeyFormat,\n type TSerializedCryptoKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nconst fromBase64 = async (\n dataBase64: string,\n keyUsage: KeyUsage[],\n extractable: boolean,\n): Promise<CryptoKey> => {\n const keyBuffer = Uint8Array.from(base64.decode(dataBase64));\n\n return await crypto.subtle.importKey(\"raw\", keyBuffer, { name: \"X25519\" }, extractable, keyUsage);\n};\n\nconst fromJwk = async (\n jwk: JsonWebKey,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n return await crypto.subtle.importKey(\"jwk\", jwk, { name: \"X25519\" }, extractable, keyUsage);\n};\n\nconst fromSerializedObject = async <\n D extends\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed =\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n>(\n serialized: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n if (serialized.format === ECryptoKeyFormat.jwk) {\n return await fromJwk(serialized.data, keyUsage, extractable);\n }\n\n return await fromBase64(serialized.data, keyUsage, extractable);\n};\n\nconst fromFormattedString = async <\n D extends TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk =\n | TSerializedCryptoKeyData_X25519_Raw\n | TSerializedCryptoKeyData_X25519_Jwk,\n>(\n dataString: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n const transformed = convertX25519FormattedStringToSerializedKeyData(dataString);\n return await fromSerializedObject(transformed, keyUsage, extractable);\n};\n\nconst extractableOrNonExtractable = <I>(\n keyUsage: KeyUsage[],\n func: (input: I, keyUsage: KeyUsage[], extractable: boolean) => Promise<CryptoKey>,\n) =>\n ({\n extractable: (input: I) => func(input, keyUsage, true),\n nonExtractable: (input: I) => func(input, keyUsage, false),\n }) as const;\n\nexport const importX25519Key = {\n private: {\n fromFormattedString: extractableOrNonExtractable(\n [\"deriveKey\", \"deriveBits\"],\n fromFormattedString<TSerializedCryptoKeyData_X25519_Jwk>,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"deriveKey\", \"deriveBits\"],\n fromSerializedObject<TSerializedCryptoKeyData_X25519_Jwk_Transformed>,\n ),\n fromJwk: extractableOrNonExtractable([\"deriveKey\", \"deriveBits\"], fromJwk),\n },\n public: {\n fromBase64: extractableOrNonExtractable([], fromBase64),\n fromFormattedString: extractableOrNonExtractable(\n [],\n fromFormattedString<\n TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk\n >,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [],\n fromSerializedObject<\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed\n >,\n ),\n fromJwk: extractableOrNonExtractable([], fromJwk),\n },\n};\n","import {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeX25519Key_Jwk = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_X25519_Jwk> => {\n const publicKeyJwk = await crypto.subtle.exportKey(\"jwk\", key);\n\n const prefixed =\n `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.jwk}::${JSON.stringify(publicKeyJwk)}` as const;\n\n const transformed: TSerializedCryptoKeyData_X25519_Jwk_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.x25519,\n data: publicKeyJwk,\n format: ECryptoKeyFormat.jwk,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\nimport {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeX25519Key_Raw = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_X25519_Raw> => {\n const publicKeyBuffer = await crypto.subtle.exportKey(\"raw\", key);\n const publicKeyBase64 = base64.encode(new Uint8Array(publicKeyBuffer));\n\n const prefixed =\n `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.raw_base64}::${publicKeyBase64}` as const;\n\n const transformed: TSerializedCryptoKeyData_X25519_Raw_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.x25519,\n data: publicKeyBase64,\n format: ECryptoKeyFormat.raw_base64,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\r\nimport type { TTypeAndId } from \"../../core/core_valibot_schemas\";\r\nimport type { StorageAdapter } from \"../../storage_adapter/StorageAdapter\";\r\nimport {\r\n createTypedStorage,\r\n type ITypedStorage,\r\n} from \"../../storage_adapter/typed_storage/createTypedStorage\";\r\nimport { createAesGcmKeyFromX25519Keys } from \"../aes_gcm/createAesGcmKeyFromX25519Keys\";\r\nimport { decryptBytesWithAesGcmKey } from \"../aes_gcm/decryptBytesWithAesGcmKey\";\r\nimport { decryptTextDataWithAesGcmKey } from \"../aes_gcm/decryptTextDataWithAesGcmKey\";\r\nimport { encryptBytesWithAesGcmKey } from \"../aes_gcm/encryptBytesWithAesGcmKey\";\r\nimport { encryptTextDataWithAesGcmKey } from \"../aes_gcm/encryptTextDataWithAesGcmKey\";\r\nimport type {\r\n TEncryptedAesGcmBytes,\r\n TEncryptedAesGcmPayload,\r\n TSerializedCryptoKeyData_Ed25519_Raw,\r\n TSerializedCryptoKeyData_X25519_Raw,\r\n TSerializedCryptoKeyPairDataEd25519,\r\n TSerializedCryptoKeyPairDataX25519,\r\n} from \"../crypto.schema\";\r\nimport { generateEd25519KeyPair } from \"../ed25519/generateEd25519KeyPair\";\r\nimport { importEd25519Key } from \"../ed25519/importEd25519Key\";\r\nimport { serializeEd25519Key_Jwk } from \"../ed25519/serializeEd25519Key_Jwk\";\r\nimport { serializeEd25519Key_Raw } from \"../ed25519/serializeEd25519Key_Raw\";\r\nimport { signCombinedTextDataWithKeyEd25519 } from \"../ed25519/signCombinedTextDataWithKeyEd25519\";\r\nimport { signTextDataWithKeyEd25519 } from \"../ed25519/signTextDataWithKeyEd25519\";\r\nimport { verifyWithKeyEd25519 } from \"../ed25519/verifyWithKeyEd25519\";\r\nimport { generateX25519KeyPair } from \"../x25519/generateX25519KeyPair\";\r\nimport { importX25519Key } from \"../x25519/importX25519Key\";\r\nimport { serializeX25519Key_Jwk } from \"../x25519/serializeX25519Key_Jwk\";\r\nimport { serializeX25519Key_Raw } from \"../x25519/serializeX25519Key_Raw\";\r\nimport { buildVerifyKeyBoundInfoString } from \"./buildVerifyKeyBoundInfoString\";\r\n\r\ninterface IClientCryptoKeyLink_Constructor {\r\n storageAdapter?: StorageAdapter;\r\n}\r\n\r\ninterface ITypedStorage_ClientCryptoKeyLink {\r\n localExchangeKeyPair?: TSerializedCryptoKeyPairDataX25519;\r\n localVerifyKeyPair?: TSerializedCryptoKeyPairDataEd25519;\r\n linkedClientPublicKeys: {\r\n [key: TTypeAndId<string>]: {\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n // HKDF inputs for the shared-key derivation. Persisted only via linkClientAndStore — these\r\n // are typically session secrets, so prefer the in-memory linkClient for ephemeral links.\r\n saltString?: string;\r\n infoString?: string;\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n };\r\n };\r\n}\r\n\r\ninterface IExternalClientCryptoKeys {\r\n verify?: {\r\n publicKey: CryptoKey;\r\n publicKeySerialized: TSerializedCryptoKeyData_Ed25519_Raw;\r\n };\r\n exchange?: {\r\n publicKey: CryptoKey;\r\n // Serialized form retained so re-linking can detect a changed key and invalidate the cache.\r\n publicKeySerialized: TSerializedCryptoKeyData_X25519_Raw;\r\n saltString?: string;\r\n infoString?: string;\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n sharedEncryptKey?: CryptoKey;\r\n };\r\n}\r\n\r\ninterface ILinkedClientPublicKeys {\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n}\r\n\r\ninterface ILocalPublicKeys {\r\n verifyPublicKey: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey: TSerializedCryptoKeyData_X25519_Raw;\r\n}\r\n\r\ninterface ILinkClientKeys {\r\n linkedClientId: TTypeAndId;\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n // HKDF salt/info bound into the shared AES-GCM key derivation with this client. Passing either\r\n // (or a new exchange public key) invalidates a previously cached shared key for the link.\r\n saltString?: string;\r\n infoString?: string;\r\n // When true, both sides' verify public keys (local + linked, sorted so both ends agree without\r\n // coordinating an order) are folded into the HKDF info alongside `infoString`. If either relayed\r\n // verify key was tampered with in transit, the two sides derive mismatched keys and the first\r\n // decryption fails — authenticating the keys without extra signatures. Requires the linked\r\n // client's verify key to be set. Both ends of the link must use the same setting.\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n}\r\n\r\ninterface IEncryptDataForLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n dataToEncrypt: string;\r\n}\r\n\r\ninterface IDecryptDataFromLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n dataToDecrypt: TEncryptedAesGcmPayload;\r\n}\r\n\r\ninterface IDecryptAndVerifyDataFromLinkedClient extends IDecryptDataFromLinkedClient {\r\n signatureBase64: string;\r\n}\r\n\r\ninterface IVerifyChallengeFromLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n challenge: string;\r\n signatureBase64: string;\r\n}\r\n\r\nexport class ClientCryptoKeyLink {\r\n private localExchangeKeyPair: CryptoKeyPair | undefined;\r\n private localVerifyKeyPair: CryptoKeyPair | undefined;\r\n private linkedClientKeys = new Map<TTypeAndId, IExternalClientCryptoKeys>();\r\n private storage: ITypedStorage<ITypedStorage_ClientCryptoKeyLink> | undefined;\r\n private initialized = false;\r\n private initializePromise: Promise<void> | undefined;\r\n private localExchangeKeyPairPromise: Promise<CryptoKeyPair> | undefined;\r\n private localVerifyKeyPairPromise: Promise<CryptoKeyPair> | undefined;\r\n\r\n constructor({ storageAdapter }: IClientCryptoKeyLink_Constructor = {}) {\r\n if (storageAdapter != null) {\r\n this.storage = createTypedStorage({ storageAdapter });\r\n }\r\n }\r\n\r\n /**\r\n * Loads the local key pairs and any linked client public keys from storage (when a storage\r\n * adapter was provided), generating and persisting fresh local key pairs if none exist yet.\r\n *\r\n * Must be called (and awaited) before any sign/verify/encrypt/decrypt operation.\r\n */\r\n async initialize(): Promise<void> {\r\n if (this.initialized) {\r\n return;\r\n }\r\n\r\n // Guard against concurrent initialize() calls (e.g. parallel callers on the frontend, where\r\n // there is no blockConcurrencyWhile) generating and persisting duplicate local key pairs.\r\n this.initializePromise ??= this.runInitialize();\r\n\r\n try {\r\n await this.initializePromise;\r\n } finally {\r\n this.initializePromise = undefined;\r\n }\r\n }\r\n\r\n private async runInitialize(): Promise<void> {\r\n await this.loadStoredLocalKeys();\r\n await this.loadLinkedClients();\r\n\r\n this.initialized = true;\r\n }\r\n\r\n /**\r\n * Loads the local key pairs from storage if they were previously persisted. Does NOT generate\r\n * fresh keys — local identity is created lazily on first use (see {@link ensureLocalExchangeKeyPair}\r\n * / {@link ensureLocalVerifyKeyPair}), so a verify-only or otherwise key-less consumer never\r\n * generates or stores keys it does not need.\r\n */\r\n private async loadStoredLocalKeys(): Promise<void> {\r\n const storedExchange = await this.storage?.getJson(\"localExchangeKeyPair\");\r\n if (storedExchange != null) {\r\n this.localExchangeKeyPair = {\r\n privateKey: await importX25519Key.private.fromFormattedString.extractable(\r\n storedExchange.privateKey,\r\n ),\r\n publicKey: await importX25519Key.public.fromFormattedString.extractable(\r\n storedExchange.publicKey,\r\n ),\r\n };\r\n }\r\n\r\n const storedVerify = await this.storage?.getJson(\"localVerifyKeyPair\");\r\n if (storedVerify != null) {\r\n this.localVerifyKeyPair = {\r\n privateKey: await importEd25519Key.private.fromFormattedString.extractable(\r\n storedVerify.privateKey,\r\n ),\r\n publicKey: await importEd25519Key.public.fromFormattedString.extractable(\r\n storedVerify.publicKey,\r\n ),\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Returns the local exchange (X25519) key pair, generating and persisting it on first use.\r\n * Concurrent callers share a single generation.\r\n */\r\n private async ensureLocalExchangeKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localExchangeKeyPair != null) {\r\n return this.localExchangeKeyPair;\r\n }\r\n\r\n this.localExchangeKeyPairPromise ??= (async () => {\r\n const keyPair = await generateX25519KeyPair();\r\n this.localExchangeKeyPair = keyPair;\r\n if (this.storage != null) {\r\n await this.storage.setJson(\r\n \"localExchangeKeyPair\",\r\n await this.serializeExchangeKeyPair(keyPair),\r\n );\r\n }\r\n return keyPair;\r\n })();\r\n\r\n try {\r\n return await this.localExchangeKeyPairPromise;\r\n } finally {\r\n this.localExchangeKeyPairPromise = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the local verify (Ed25519) key pair, generating and persisting it on first use.\r\n * Concurrent callers share a single generation.\r\n */\r\n private async ensureLocalVerifyKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localVerifyKeyPair != null) {\r\n return this.localVerifyKeyPair;\r\n }\r\n\r\n this.localVerifyKeyPairPromise ??= (async () => {\r\n const keyPair = await generateEd25519KeyPair();\r\n this.localVerifyKeyPair = keyPair;\r\n if (this.storage != null) {\r\n await this.storage.setJson(\r\n \"localVerifyKeyPair\",\r\n await this.serializeVerifyKeyPair(keyPair),\r\n );\r\n }\r\n return keyPair;\r\n })();\r\n\r\n try {\r\n return await this.localVerifyKeyPairPromise;\r\n } finally {\r\n this.localVerifyKeyPairPromise = undefined;\r\n }\r\n }\r\n\r\n private async loadLinkedClients(): Promise<void> {\r\n const storedLinkedClients = await this.storage?.getJson(\"linkedClientPublicKeys\");\r\n\r\n if (storedLinkedClients == null) {\r\n return;\r\n }\r\n\r\n for (const [linkedClientId, publicKeys] of Object.entries(storedLinkedClients) as [\r\n TTypeAndId,\r\n ITypedStorage_ClientCryptoKeyLink[\"linkedClientPublicKeys\"][TTypeAndId],\r\n ][]) {\r\n await this.linkClient({\r\n linkedClientId,\r\n verifyPublicKey: publicKeys.verifyPublicKey,\r\n exchangePublicKey: publicKeys.exchangePublicKey,\r\n saltString: publicKeys.saltString,\r\n infoString: publicKeys.infoString,\r\n bindVerifyKeysIntoDerivation: publicKeys.bindVerifyKeysIntoDerivation,\r\n });\r\n }\r\n }\r\n\r\n private async serializeExchangeKeyPair(\r\n keyPair: CryptoKeyPair,\r\n ): Promise<TSerializedCryptoKeyPairDataX25519> {\r\n return {\r\n publicKey: (await serializeX25519Key_Raw(keyPair.publicKey)).prefixed,\r\n privateKey: (await serializeX25519Key_Jwk(keyPair.privateKey)).prefixed,\r\n };\r\n }\r\n\r\n private async serializeVerifyKeyPair(\r\n keyPair: CryptoKeyPair,\r\n ): Promise<TSerializedCryptoKeyPairDataEd25519> {\r\n return {\r\n publicKey: (await serializeEd25519Key_Raw(keyPair.publicKey)).prefixed,\r\n privateKey: (await serializeEd25519Key_Jwk(keyPair.privateKey)).prefixed,\r\n };\r\n }\r\n\r\n /**\r\n * The local public keys that should be shared with a linked client so that it can verify this\r\n * client's signatures and derive a shared encryption key. Generates the local identity on first\r\n * use.\r\n */\r\n async getLocalPublicKeys(): Promise<ILocalPublicKeys> {\r\n return {\r\n verifyPublicKey: await this.getLocalVerifyPublicKey(),\r\n exchangePublicKey: await this.getLocalExchangePublicKey(),\r\n };\r\n }\r\n\r\n /**\r\n * The local exchange (X25519) public key, generating the exchange key pair on first use. Does not\r\n * touch the verify key pair — useful for an exchange-only consumer (e.g. a bridge) that never\r\n * signs.\r\n */\r\n async getLocalExchangePublicKey(): Promise<TSerializedCryptoKeyData_X25519_Raw> {\r\n const exchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n return (await serializeX25519Key_Raw(exchangeKeyPair.publicKey)).prefixed;\r\n }\r\n\r\n /**\r\n * The local verify (Ed25519) public key, generating the verify key pair on first use. Does not\r\n * touch the exchange key pair.\r\n */\r\n async getLocalVerifyPublicKey(): Promise<TSerializedCryptoKeyData_Ed25519_Raw> {\r\n const verifyKeyPair = await this.ensureLocalVerifyKeyPair();\r\n return (await serializeEd25519Key_Raw(verifyKeyPair.publicKey)).prefixed;\r\n }\r\n\r\n /**\r\n * Registers (or updates) the public keys of a linked client in memory only — nothing is written\r\n * to storage. Use this for ephemeral links (e.g. a per-session bridge or end-to-end peer keyed by\r\n * a session salt/info), so the derived shared key never outlives the process.\r\n *\r\n * Re-linking with a new exchange public key, salt, or info invalidates any previously cached\r\n * shared key for the link.\r\n */\r\n async linkClient({\r\n linkedClientId,\r\n verifyPublicKey,\r\n exchangePublicKey,\r\n saltString,\r\n infoString,\r\n bindVerifyKeysIntoDerivation,\r\n }: ILinkClientKeys): Promise<void> {\r\n const existing = this.linkedClientKeys.get(linkedClientId);\r\n\r\n const verify =\r\n verifyPublicKey != null\r\n ? {\r\n publicKey:\r\n await importEd25519Key.public.fromFormattedString.extractable(verifyPublicKey),\r\n publicKeySerialized: verifyPublicKey,\r\n }\r\n : existing?.verify;\r\n\r\n const verifyKeyChanged =\r\n verifyPublicKey != null && verifyPublicKey !== existing?.verify?.publicKeySerialized;\r\n\r\n let exchange = existing?.exchange;\r\n\r\n // `undefined` means \"leave as-is\"; only fields actually passed override the existing link.\r\n const exchangeParamsProvided =\r\n exchangePublicKey != null ||\r\n saltString !== undefined ||\r\n infoString !== undefined ||\r\n bindVerifyKeysIntoDerivation !== undefined;\r\n\r\n if (exchangeParamsProvided) {\r\n const nextPublicKeySerialized = exchangePublicKey ?? existing?.exchange?.publicKeySerialized;\r\n\r\n if (nextPublicKeySerialized == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: Cannot set salt/info for ${linkedClientId} without an exchange public key`,\r\n );\r\n }\r\n\r\n const nextSalt = saltString !== undefined ? saltString : existing?.exchange?.saltString;\r\n const nextInfo = infoString !== undefined ? infoString : existing?.exchange?.infoString;\r\n const nextBind =\r\n bindVerifyKeysIntoDerivation !== undefined\r\n ? bindVerifyKeysIntoDerivation\r\n : existing?.exchange?.bindVerifyKeysIntoDerivation;\r\n\r\n const publicKey =\r\n exchangePublicKey != null\r\n ? await importX25519Key.public.fromFormattedString.extractable(exchangePublicKey)\r\n : // Safe: nextPublicKeySerialized fell back to the existing key, so it exists.\r\n existing!.exchange!.publicKey;\r\n\r\n const unchanged =\r\n nextPublicKeySerialized === existing?.exchange?.publicKeySerialized &&\r\n nextSalt === existing?.exchange?.saltString &&\r\n nextInfo === existing?.exchange?.infoString &&\r\n nextBind === existing?.exchange?.bindVerifyKeysIntoDerivation &&\r\n // With verify keys bound into the derivation, a new verify key changes the derived key.\r\n !(nextBind === true && verifyKeyChanged);\r\n\r\n exchange = {\r\n publicKey,\r\n publicKeySerialized: nextPublicKeySerialized,\r\n saltString: nextSalt,\r\n infoString: nextInfo,\r\n bindVerifyKeysIntoDerivation: nextBind,\r\n // Keep the cached shared key only when no derivation input changed.\r\n sharedEncryptKey: unchanged ? existing?.exchange?.sharedEncryptKey : undefined,\r\n };\r\n } else if (\r\n exchange?.bindVerifyKeysIntoDerivation === true &&\r\n verifyKeyChanged &&\r\n exchange.sharedEncryptKey != null\r\n ) {\r\n // Verify-only re-link, but the verify key participates in this link's derivation.\r\n exchange = { ...exchange, sharedEncryptKey: undefined };\r\n }\r\n\r\n this.linkedClientKeys.set(linkedClientId, { verify, exchange });\r\n }\r\n\r\n /**\r\n * Like {@link linkClient}, but also persists the linked client's public keys (and salt/info) to\r\n * storage so the link survives a reload.\r\n *\r\n * NOTE: salt/info are written in plaintext. When they are session secrets (e.g. a partner secret\r\n * or bridge salt), prefer {@link linkClient} and re-establish the link per session instead.\r\n */\r\n async linkClientAndStore(input: ILinkClientKeys): Promise<void> {\r\n await this.linkClient(input);\r\n\r\n if (this.storage == null) {\r\n return;\r\n }\r\n\r\n const {\r\n linkedClientId,\r\n verifyPublicKey,\r\n exchangePublicKey,\r\n saltString,\r\n infoString,\r\n bindVerifyKeysIntoDerivation,\r\n } = input;\r\n\r\n await this.storage.updateJsonWithDef(\"linkedClientPublicKeys\", {}, (current) => ({\r\n ...current,\r\n [linkedClientId]: {\r\n ...current[linkedClientId],\r\n ...(verifyPublicKey != null ? { verifyPublicKey } : {}),\r\n ...(exchangePublicKey != null ? { exchangePublicKey } : {}),\r\n ...(saltString !== undefined ? { saltString } : {}),\r\n ...(infoString !== undefined ? { infoString } : {}),\r\n ...(bindVerifyKeysIntoDerivation !== undefined ? { bindVerifyKeysIntoDerivation } : {}),\r\n },\r\n }));\r\n }\r\n\r\n /**\r\n * Whether a linked client is currently registered (in memory) under this id.\r\n */\r\n hasLinkedClient(linkedClientId: TTypeAndId): boolean {\r\n return this.linkedClientKeys.has(linkedClientId);\r\n }\r\n\r\n /**\r\n * The serialized public keys registered for a linked client, or undefined when the client is not\r\n * linked. Useful when a holder needs to relay a linked client's keys onward (e.g. a backend\r\n * relaying a wallet's verify key to a partner).\r\n */\r\n getLinkedClientPublicKeys(linkedClientId: TTypeAndId): ILinkedClientPublicKeys | undefined {\r\n const linkedClient = this.linkedClientKeys.get(linkedClientId);\r\n\r\n if (linkedClient == null) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n verifyPublicKey: linkedClient.verify?.publicKeySerialized,\r\n exchangePublicKey: linkedClient.exchange?.publicKeySerialized,\r\n };\r\n }\r\n\r\n /**\r\n * Removes a single linked client from memory and, when storage is available, from persisted\r\n * state. Any cached shared key for the link is dropped with it.\r\n */\r\n async unlinkClient(linkedClientId: TTypeAndId): Promise<void> {\r\n this.linkedClientKeys.delete(linkedClientId);\r\n\r\n if (this.storage != null) {\r\n await this.storage.updateJson(\"linkedClientPublicKeys\", (current) => {\r\n if (current == null) {\r\n return {};\r\n }\r\n\r\n const { [linkedClientId]: _removed, ...rest } = current;\r\n return rest;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Removes all linked clients from memory and persisted state, while keeping the local identity\r\n * key pairs intact.\r\n */\r\n async unlinkAllClients(): Promise<void> {\r\n this.linkedClientKeys.clear();\r\n\r\n if (this.storage != null) {\r\n await this.storage.setJson(\"linkedClientPublicKeys\", {});\r\n }\r\n }\r\n\r\n /**\r\n * Wipes everything this instance owns — local identity key pairs and all linked clients, in\r\n * memory and in storage. After a reset, {@link initialize} must be called again before use (it\r\n * will generate a fresh local identity).\r\n *\r\n * Only the keys owned by this util are removed, so a shared storage adapter's other data is left\r\n * untouched.\r\n */\r\n async reset(): Promise<void> {\r\n this.linkedClientKeys.clear();\r\n this.localExchangeKeyPair = undefined;\r\n this.localVerifyKeyPair = undefined;\r\n this.initialized = false;\r\n\r\n if (this.storage != null) {\r\n await this.storage.removeItem(\"linkedClientPublicKeys\");\r\n await this.storage.removeItem(\"localExchangeKeyPair\");\r\n await this.storage.removeItem(\"localVerifyKeyPair\");\r\n }\r\n }\r\n\r\n private getLinkedClient(linkedClientId: TTypeAndId): IExternalClientCryptoKeys {\r\n const linkedClient = this.linkedClientKeys.get(linkedClientId);\r\n\r\n if (linkedClient == null) {\r\n throw new Error(`ClientCryptoKeyLink: No linked client for ${linkedClientId}`);\r\n }\r\n\r\n return linkedClient;\r\n }\r\n\r\n private async getAesGcmKeyForLinkedClient(\r\n externalClientSourceId: TTypeAndId,\r\n ): Promise<CryptoKey> {\r\n const linkedClient = this.getLinkedClient(externalClientSourceId);\r\n\r\n if (linkedClient.exchange?.sharedEncryptKey != null) {\r\n return linkedClient.exchange.sharedEncryptKey;\r\n }\r\n\r\n if (linkedClient.exchange?.publicKey == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: No public exchange key set for ${externalClientSourceId}`,\r\n );\r\n }\r\n\r\n const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n\r\n let infoString = linkedClient.exchange.infoString;\r\n\r\n if (linkedClient.exchange.bindVerifyKeysIntoDerivation === true) {\r\n const linkedVerifyPublicKey = linkedClient.verify?.publicKeySerialized;\r\n\r\n if (linkedVerifyPublicKey == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: Link for ${externalClientSourceId} binds verify keys into the derivation, but no verify public key is set`,\r\n );\r\n }\r\n\r\n infoString = buildVerifyKeyBoundInfoString({\r\n infoString: linkedClient.exchange.infoString,\r\n verifyPublicKeys: [await this.getLocalVerifyPublicKey(), linkedVerifyPublicKey],\r\n });\r\n }\r\n\r\n const sharedEncryptKey = await createAesGcmKeyFromX25519Keys({\r\n internalX25519PrivateKey: localExchangeKeyPair.privateKey,\r\n externalX25519PublicKey: linkedClient.exchange.publicKey,\r\n saltString: linkedClient.exchange.saltString,\r\n infoString,\r\n });\r\n\r\n this.linkedClientKeys.set(externalClientSourceId, {\r\n ...linkedClient,\r\n exchange: {\r\n ...linkedClient.exchange,\r\n sharedEncryptKey,\r\n },\r\n });\r\n\r\n return sharedEncryptKey;\r\n }\r\n\r\n async encryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: IEncryptDataForLinkedClient): Promise<TEncryptedAesGcmPayload> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await encryptTextDataWithAesGcmKey({\r\n dataToEncrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n async decryptDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n }: IDecryptDataFromLinkedClient): Promise<string> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await decryptTextDataWithAesGcmKey({\r\n dataToDecrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n /**\r\n * Bytes counterpart of {@link encryptDataForLinkedClient} — encrypts raw bytes with the shared\r\n * AES-GCM key, returning a binary nonce + ciphertext. Use it for binary channels (e.g. msgpack\r\n * WebSocket frames) to avoid base64 inflation.\r\n */\r\n async encryptBytesForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: {\r\n dataToEncrypt: Uint8Array;\r\n linkedClientId: TTypeAndId;\r\n }): Promise<TEncryptedAesGcmBytes> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await encryptBytesWithAesGcmKey({\r\n dataToEncrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n /** Bytes counterpart of {@link decryptDataFromLinkedClient}. */\r\n async decryptBytesFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n }: {\r\n dataToDecrypt: TEncryptedAesGcmBytes;\r\n linkedClientId: TTypeAndId;\r\n }): Promise<Uint8Array> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await decryptBytesWithAesGcmKey({\r\n dataToDecrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n async signAndEncryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: IEncryptDataForLinkedClient): Promise<{\r\n encryptedData: TEncryptedAesGcmPayload;\r\n signatureBase64: string;\r\n }> {\r\n const { signatureBase64 } = await this.signChallenge([dataToEncrypt]);\r\n const encryptedData = await this.encryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n });\r\n\r\n return {\r\n encryptedData,\r\n signatureBase64,\r\n };\r\n }\r\n\r\n /**\r\n * Decrypts a payload from a linked client and verifies that the decrypted plaintext was signed\r\n * by that client. Counterpart to {@link signAndEncryptDataForLinkedClient}.\r\n *\r\n * Returns the decrypted `data` alongside `isValid` — the caller decides how to handle an invalid\r\n * signature. (A tampered ciphertext fails earlier at AES-GCM decryption.)\r\n */\r\n async decryptAndVerifyDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n signatureBase64,\r\n }: IDecryptAndVerifyDataFromLinkedClient): Promise<{ data: string; isValid: boolean }> {\r\n const data = await this.decryptDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n });\r\n\r\n const isValid = await this.verifyChallengeFromLinkedClient({\r\n linkedClientId,\r\n challenge: data,\r\n signatureBase64,\r\n });\r\n\r\n return { data, isValid };\r\n }\r\n\r\n async signChallenge(challenge: [string, ...string[]]): Promise<{\r\n signatureBase64: string;\r\n }> {\r\n if (challenge.length === 0) {\r\n throw new Error(\"Challenge must contain at least one string\");\r\n }\r\n\r\n const localVerifyKeyPair = await this.ensureLocalVerifyKeyPair();\r\n\r\n const signature =\r\n challenge.length > 1\r\n ? await signCombinedTextDataWithKeyEd25519(challenge, localVerifyKeyPair.privateKey)\r\n : await signTextDataWithKeyEd25519(challenge[0], localVerifyKeyPair.privateKey);\r\n\r\n return {\r\n signatureBase64: base64.encode(signature),\r\n };\r\n }\r\n\r\n /**\r\n * Verifies a signature over `challenge` against the linked client's verify (Ed25519) public key.\r\n */\r\n async verifyChallengeFromLinkedClient({\r\n linkedClientId,\r\n challenge,\r\n signatureBase64,\r\n }: IVerifyChallengeFromLinkedClient): Promise<boolean> {\r\n const linkedClient = this.getLinkedClient(linkedClientId);\r\n\r\n if (linkedClient.verify?.publicKey == null) {\r\n throw new Error(`ClientCryptoKeyLink: No verify public key set for ${linkedClientId}`);\r\n }\r\n\r\n return await verifyWithKeyEd25519({\r\n challenge,\r\n signatureBase64,\r\n publicKey: linkedClient.verify.publicKey,\r\n });\r\n }\r\n}\r\n","// import type { StringKeys } from \"../typescript/special_typescript_types\";\n\nexport enum EStorageAdapterType {\n string = \"string\",\n json = \"json\",\n}\n\nexport interface IStorageAdapterMethods_String {\n type: EStorageAdapterType.string;\n setItem: (key: string, value: string) => Promise<void>;\n getItem: (key: string) => Promise<string | null | undefined>;\n removeItem: (key: string) => Promise<void>;\n}\n\nexport interface IStorageAdapterMethods_Json {\n type: EStorageAdapterType.json;\n setItem: <T>(key: string, value: T) => Promise<void>;\n getItem: <T>(key: string) => Promise<T | null | undefined>;\n removeItem: (key: string) => Promise<void>;\n}\n\nexport type TStorageAdapterMethods = IStorageAdapterMethods_String | IStorageAdapterMethods_Json;\n\nexport interface IStorageKeyGetterAndSetter<T> {\n get: () => Promise<T | undefined>;\n set: (value: T) => Promise<void>;\n}\n\n// export interface IStorageAdapter {}\n","import {\n EStorageAdapterType,\n type IStorageKeyGetterAndSetter,\n type TStorageAdapterMethods,\n} from \"./storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"./typed_storage/createTypedStorage\";\n\nexport interface IStorageAdapterConstructor {\n methods: TStorageAdapterMethods;\n trackKeysForClearing?: boolean;\n keyPrefix?: string;\n}\n\ninterface IStorageAdapterTypedStorage {\n __usedKeys__: string[];\n}\n\nexport class StorageAdapter {\n private implementation: TStorageAdapterMethods;\n readonly keyPrefix: string;\n private readonly adapterStorage?: ITypedStorage<IStorageAdapterTypedStorage>;\n\n constructor({ methods, keyPrefix, trackKeysForClearing: trackKeys }: IStorageAdapterConstructor) {\n this.implementation = methods;\n this.keyPrefix = keyPrefix ?? \"\";\n const _trackKeys = trackKeys ?? true;\n // Only create keyStorage when tracking is enabled; the inner adapter has trackKeys:false so\n // its constructor skips this branch, breaking the infinite-recursion cycle.\n this.adapterStorage = _trackKeys\n ? createTypedStorage({\n storageAdapter: new StorageAdapter({ methods, keyPrefix, trackKeysForClearing: false }),\n })\n : undefined;\n }\n\n private getPrefixedKey(rawKey: string): string {\n return `${this.keyPrefix}${rawKey}`;\n }\n\n /**\n * Derive a new adapter over the *same* backing store with an extra key-prefix segment appended.\n * Lets an independent namespace (e.g. a second crypto identity) share one underlying storage without\n * key collisions; the derived adapter tracks its own keys for `clearAll`, scoped to the new prefix.\n */\n withKeyPrefix(extraPrefix: string): StorageAdapter {\n return new StorageAdapter({\n methods: this.implementation,\n keyPrefix: `${this.keyPrefix}${extraPrefix}`,\n });\n }\n\n private async trackUsedKey(rawKey: string): Promise<void> {\n if (!this.adapterStorage) return;\n await this.adapterStorage.updateJsonWithDef(\"__usedKeys__\", [], (currentKeys) => {\n if (!currentKeys.includes(rawKey)) {\n return [...currentKeys, rawKey];\n }\n return currentKeys;\n });\n }\n\n private async untrackUsedKey(rawKey: string): Promise<void> {\n if (!this.adapterStorage) return;\n await this.adapterStorage.updateJsonWithDef(\"__usedKeys__\", [], (currentKeys) => {\n return currentKeys.filter((k) => k !== rawKey);\n });\n }\n\n async clearAll(): Promise<void> {\n if (!this.adapterStorage) return;\n const allKeys = (await this.adapterStorage.getJsonOrDef(\"__usedKeys__\", [])) ?? [];\n\n await Promise.all(\n allKeys.map(async (key) => {\n await this.removeItem(key);\n }),\n );\n\n await this.adapterStorage.setJson(\"__usedKeys__\", []);\n }\n\n async removeItem(rawKey: string): Promise<void> {\n await this.implementation.removeItem(this.getPrefixedKey(rawKey));\n await this.untrackUsedKey(rawKey);\n }\n\n async setJson(rawKey: string, value: any) {\n const key = this.getPrefixedKey(rawKey);\n\n if (this.implementation.type === EStorageAdapterType.string) {\n await this.implementation.setItem(key, JSON.stringify(value));\n } else {\n await this.implementation.setItem(key, value);\n }\n\n await this.trackUsedKey(rawKey);\n }\n\n async getJson<T>(rawKey: string): Promise<T | undefined> {\n const key = this.getPrefixedKey(rawKey);\n\n if (this.implementation.type === EStorageAdapterType.string) {\n const val = await this.implementation.getItem(key);\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return undefined;\n }\n\n return JSON.parse(val);\n } else {\n const val = await this.implementation.getItem<T>(key);\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return undefined;\n }\n\n return val;\n }\n }\n\n async getJsonOrDef<T>(rawKey: string, defVal: T): Promise<T> {\n if (this.implementation.type === EStorageAdapterType.string) {\n const val = await this.implementation.getItem(this.getPrefixedKey(rawKey));\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return defVal;\n }\n\n return JSON.parse(val);\n }\n\n const val = await this.implementation.getItem<T>(this.getPrefixedKey(rawKey));\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return defVal;\n }\n\n return val;\n }\n\n async updateJson<T>(rawKey: string, updater: (currentVal: T | undefined) => T): Promise<T> {\n const currentVal = await this.getJson<T>(rawKey);\n const newVal = updater(currentVal);\n await this.setJson(rawKey, newVal);\n return newVal;\n }\n\n async updateJsonOrDef<T>(rawKey: string, defVal: T, updater: (currentVal: T) => T): Promise<T> {\n const currentVal = await this.getJsonOrDef<T>(rawKey, defVal);\n const newVal = updater(currentVal);\n await this.setJson(rawKey, newVal);\n return newVal;\n }\n\n createJsonGetterSetter<T>(rawKey: string): IStorageKeyGetterAndSetter<T> {\n return {\n get: () => this.getJson(rawKey),\n set: (value: T) => this.setJson(rawKey, value),\n };\n }\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_String,\n} from \"../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../typed_storage/createTypedStorage\";\n\n/**\n *\n * Web Storage [LOCAL STORAGE]\n *\n */\n\ntype TCreateWebLocalStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n localStorage: typeof localStorage;\n};\n\nexport function createWebLocalStorageMethods(\n _localStorage: typeof localStorage,\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => _localStorage.getItem(key),\n setItem: async (key, value) => {\n _localStorage.setItem(key, value);\n },\n removeItem: async (key) => {\n _localStorage.removeItem(key);\n },\n };\n}\n\nexport const createWebLocalStorageAdapter = ({\n localStorage: _localStorage,\n ...options\n}: TCreateWebLocalStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createWebLocalStorageMethods(_localStorage),\n ...options,\n });\n};\n\nexport function createTypedWebLocalStorage<T extends Record<string, any>>(\n options: TCreateWebLocalStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createWebLocalStorageAdapter(options),\n });\n}\n\n/**\n *\n * Web Storage [SESSION STORAGE]\n *\n */\n\ntype TCreateWebSessionStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n sessionStorage: typeof sessionStorage;\n};\n\nexport function createWebSessionStorageMethods(\n _sessionStorage: typeof sessionStorage,\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => _sessionStorage.getItem(key),\n setItem: async (key, value) => {\n _sessionStorage.setItem(key, value);\n },\n removeItem: async (key) => {\n _sessionStorage.removeItem(key);\n },\n };\n}\n\nexport const createWebSessionStorageAdapter = ({\n sessionStorage: _sessionStorage,\n ...options\n}: TCreateWebSessionStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createWebSessionStorageMethods(_sessionStorage),\n ...options,\n });\n};\n\nexport function createTypedWebSessionStorage<T extends Record<string, any>>(\n options: TCreateWebSessionStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createWebSessionStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_Json,\n} from \"../../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../../typed_storage/createTypedStorage\";\nimport type { IDurableObjectStorage } from \"./durable_object_storage.types\";\n\nexport function createDurableObjectStorageMethods(\n durableObjectStorage: IDurableObjectStorage,\n): IStorageAdapterMethods_Json {\n return {\n type: EStorageAdapterType.json,\n getItem: (key) => durableObjectStorage.get(key),\n setItem: (key, value) => durableObjectStorage.put(key, value),\n removeItem: async (key) => {\n await durableObjectStorage.delete(key);\n },\n };\n}\n\nexport type TCreateDurableObjectStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n durableObjectStorage: IDurableObjectStorage;\n};\n\n/**\n * Wraps a Durable Object's storage in the generic StorageAdapter interface, e.g. for handing to a\n * ClientCryptoKeyLink so it can persist its keys inside the DO's own storage.\n */\nexport const createDurableObjectStorageAdapter = ({\n durableObjectStorage,\n ...options\n}: TCreateDurableObjectStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createDurableObjectStorageMethods(durableObjectStorage),\n ...options,\n });\n};\n\nexport function createDurableObjectTypedStorage<T extends Record<string, any>>(\n options: TCreateDurableObjectStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createDurableObjectStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_String,\n} from \"../../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../../typed_storage/createTypedStorage\";\nimport type { IKVNamespace, IKVNamespacePutOptions } from \"./kv_storage.types\";\n\nexport interface ICreateKVStorageMethodsOptions {\n /** The `KVNamespace` binding, e.g. accessed off `env.MY_KV` inside a worker. */\n kvNamespace: IKVNamespace;\n /** Default options applied to every `put`, e.g. `{ expirationTtl }` for TTL-based eviction. */\n defaultPutOptions?: IKVNamespacePutOptions;\n}\n\nexport function createKVStorageMethods({\n kvNamespace,\n defaultPutOptions,\n}: ICreateKVStorageMethodsOptions): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: (key) => kvNamespace.get(key),\n setItem: (key, value) => kvNamespace.put(key, value, defaultPutOptions),\n removeItem: (key) => kvNamespace.delete(key),\n };\n}\n\nexport type TCreateKVStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> &\n ICreateKVStorageMethodsOptions;\n\n/**\n * Wraps a Cloudflare KV namespace binding in the generic StorageAdapter interface, e.g. for handing\n * to a ClientCryptoKeyLink so it can persist its keys inside KV.\n */\nexport const createKVStorageAdapter = ({\n kvNamespace,\n defaultPutOptions,\n ...options\n}: TCreateKVStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createKVStorageMethods({ kvNamespace, defaultPutOptions }),\n ...options,\n });\n};\n\nexport function createKVTypedStorage<T extends Record<string, any>>(\n options: TCreateKVStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createKVStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_Json,\n type IStorageAdapterMethods_String,\n} from \"../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../typed_storage/createTypedStorage\";\n\nexport type TMemoryStorage_string = Map<string, string>;\nexport type TMemoryStorage_json = Map<string, any>;\n\n/**\n *\n * Memory Storage [STRING]\n *\n */\n\ntype TCreateMemoryStorageOptions_string = Omit<IStorageAdapterConstructor, \"methods\"> & {\n memoryStorageMap?: TMemoryStorage_string;\n};\n\nexport function createMemoryStorageMethods_string(\n memoryStorageMap: TMemoryStorage_string = new Map(),\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => memoryStorageMap.get(key) ?? null,\n setItem: async (key, value) => {\n memoryStorageMap.set(key, value);\n },\n removeItem: async (key) => {\n memoryStorageMap.delete(key);\n },\n };\n}\n\nexport const createMemoryStorageAdapter_string = (\n options?: TCreateMemoryStorageOptions_string,\n): StorageAdapter => {\n return new StorageAdapter({\n methods: createMemoryStorageMethods_string(options?.memoryStorageMap),\n ...options,\n });\n};\n\nexport function createTypedMemoryStorage_string<T extends Record<string, any>>(\n options?: TCreateMemoryStorageOptions_string,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createMemoryStorageAdapter_string(options),\n });\n}\n\n/**\n *\n * Memory Storage [JSON]\n *\n */\n\ntype TCreateMemoryStorageOptions_json = Omit<IStorageAdapterConstructor, \"methods\"> & {\n memoryStorageMap?: TMemoryStorage_json;\n};\n\nexport function createMemoryStorageMethods_json(\n memoryStorageMap: TMemoryStorage_json = new Map(),\n): IStorageAdapterMethods_Json {\n return {\n type: EStorageAdapterType.json,\n getItem: async (key) => memoryStorageMap.get(key),\n setItem: async (key, value) => {\n memoryStorageMap.set(key, value);\n },\n removeItem: async (key) => {\n memoryStorageMap.delete(key);\n },\n };\n}\n\nexport const createMemoryStorageAdapter_json = (\n options?: TCreateMemoryStorageOptions_json,\n): StorageAdapter => {\n return new StorageAdapter({\n methods: createMemoryStorageMethods_json(options?.memoryStorageMap),\n ...options,\n });\n};\n\nexport function createTypedMemoryStorage_json<T extends Record<string, any>>(\n options?: TCreateMemoryStorageOptions_json,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createMemoryStorageAdapter_json(options),\n });\n}\n"],"mappings":";;;AAAA,MAAa,gBAAgB,QAAkD;CAC7E,OAAO,OAAO,QAAQ,IAAI,SAAS;AACrC;;;ACFA,MAAa,6BAA6B,OAAO,EAC/C,YACA,gBAIyB;CACzB,OAAO,IAAI,WACT,MAAM,OAAO,OAAO,WAAW;EAAE,MAAM;EAAU,QAAQ;CAAU,GAAG,YAAY,GAAG,CACvF;AACF;;;ACPA,MAAM,sBAAsB;AAE5B,MAAa,gCAAgC,OAAO,EAClD,yBACA,0BACA,YACA,iBAMwB;CACxB,MAAM,aAAa,MAAM,2BAA2B;EAClD,YAAY;EACZ,WAAW;CACb,CAAC;CAGD,MAAM,MAAM,MAAM,OAAO,OAAO,UAAU,OAAO,IAAI,WAAW,UAAU,GAAG,QAAQ,OAAO,CAC1F,WACF,CAAC;CAED,MAAM,OAAO,aAAa,UAAU,IAAI,IAAI,YAAY,CAAC,CAAC,OAAO,UAAU,IAAI,IAAI,WAAW;CAC9F,MAAM,OAAO,IAAI,YAAY,CAAC,CAAC,OAC7B,aAAa,UAAU,IAAI,aAAa,mBAC1C;CAGA,OAAO,MAAM,OAAO,OAAO,UACzB;EACE,MAAM;EACN,MAAM;EACN;EACA;CACF,GACA,KACA;EAAE,MAAM;EAAW,QAAQ;CAAI,GAC/B,OACA,CAAC,WAAW,SAAS,CACvB;AACF;;;;;;;ACtCA,MAAa,4BAA4B,OAAO,EAC9C,WACA,oBAIyB;CACzB,MAAM,gBAAgB,MAAM,OAAO,OAAO,QAGxC;EAAE,MAAM;EAAW,IAAI,IAAI,WAAW,cAAc,KAAK;CAAE,GAC3D,WACA,IAAI,WAAW,cAAc,UAAU,CACzC;CAEA,OAAO,IAAI,WAAW,aAAa;AACrC;;;ACnBA,MAAa,+BAA+B,OAAO,EACjD,WACA,oBAIqB;CACrB,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EACE,MAAM;EACN,IAAI,IAAI,WAAW,OAAO,OAAO,cAAc,KAAK,CAAC;CACvD,GACA,WACA,IAAI,WAAW,OAAO,OAAO,cAAc,UAAU,CAAC,CACxD;CAEA,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,aAAa;AAC/C;;;;;;;;ACbA,MAAa,4BAA4B,OAAO,EAC9C,WACA,oBAIoC;CACpC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;CAEvD,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EAAE,MAAM;EAAW,IAAI;CAAM,GAC7B,WAGA,IAAI,WAAW,aAAa,CAC9B;CAEA,OAAO;EAAE;EAAO,YAAY,IAAI,WAAW,aAAa;CAAE;AAC5D;;;ACtBA,MAAa,+BAA+B,OAAO,EACjD,WACA,oBAIsC;CACtC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;CAEvD,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EACE,MAAM;EACN,IAAI;CACN,GACA,WACA,IAAI,YAAY,CAAC,CAAC,OAAO,aAAa,CACxC;CAEA,OAAO;EACL,OAAO,OAAO,OAAO,KAAK;EAC1B,YAAY,OAAO,OAAO,IAAI,WAAW,aAAa,CAAC;CACzD;AACF;;;ACzBA,MAAa,6BAA6B,OACxC,MACA,cACwB;CACxB,MAAM,aAAa,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI;CAChD,MAAM,YAAY,MAAM,OAAO,OAAO,KACpC,EACE,MAAM,UACR,GACA,WACA,UACF;CAEA,OAAO,IAAI,WAAW,SAAS;AACjC;;;ACZA,MAAa,uCAAuC;AAEpD,MAAa,qCAAqC,OAChD,MACA,WACA,YAAA,SACwB;CACxB,OAAO,MAAM,2BAA2B,KAAK,KAAK,SAAS,GAAG,SAAS;AACzE;;;;;;;;;;;;;;;;ACWA,MAAa,iCAAiC,EAC5C,YACA,uBACkD;CAClD,MAAM,aAAa,CAAC,GAAG,gBAAgB,CAAC,CAAC,KAAK;CAE9C,OAAO,CAAC,GAAI,cAAc,OAAO,CAAC,UAAU,IAAI,CAAC,GAAI,GAAG,UAAU,CAAC,CAAC,KAAA,IAEpE;AACF;;;ACNA,SAAgB,mBAAkD,EAChE,kBAC+C;CAC/C,MAAM,UAAU,OAAgC,QAAsC;EACpF,OAAO,eAAe,QAAc,GAAG;CACzC;CAEA,MAAM,eAAe,OAAgC,KAAQ,WAAgC;EAC3F,OAAQ,MAAM,eAAe,QAAc,GAAG,KAAM;CACtD;CAEA,MAAM,UAAU,OAAgC,KAAQ,QAA6B;EACnF,OAAO,eAAe,QAAQ,KAAK,GAAG;CACxC;CAEA,MAAM,aAAa,OAAgC,QAA0B;EAC3E,MAAM,eAAe,WAAW,GAAG;CACrC;CAEA,MAAM,aAAa,OACjB,KACA,YACkB;EAClB,MAAM,eAAe,WAAW,KAAK,OAAO;CAC9C;CAEA,MAAM,oBAAoB,OACxB,KACA,YACA,YACkB;EAClB,MAAM,eAAe,gBAAgB,KAAK,YAAY,OAAO;CAC/D;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,YAAY;GACpB,MAAM,eAAe,SAAS;EAChC;CACF;AACF;;;ACrEA,MAAa,yBAAyB,YAAoC;CAMxE,OAAO,MALgB,OAAO,OAAO,YAAY,EAAE,MAAM,UAAU,GAAG,MAAM,CAC1E,QACA,QACF,CAAC;AAGH;;;ACAA,MAAa,4CACgD,EACzD,0BAA0B,CAAC,GAC3B,gBAAgB,UAC6B,CAAC,OAE9C,oBAC8E;CAC9E,MAAM,CAAC,MAAM,QAAQ,cAAc,gBAAgB,MAAM,IAAI;CAK7D,IAAI,aAAgB;CAEpB,IAAI,iBAAiB,wBAAwB,SAAS,MAAM,GAC1D,IAAI;EACF,aAAa,KAAK,MAAM,UAAU;CACpC,SAAS,OAAO;EACd,MAAM,sBAAM,IAAI,MACd,8DAA8D,gBAAgB,wDAAwD,KAAK,IAAI,OAAO,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACvN;EAEA,IAAI,QAAQ;EACZ,MAAM;CACR;CAGF,OAAO;EACL,iBAAiB;EACX;EACE;EACR,MAAM;CACR;AACF;;;ACtCF,MAAa,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AA4BpD,MAAa,iDAAqF,EAChG,MACA,QACA,UACA,iBAE+C;CAC/C,MAAM,YAAY,YAAY;CAC9B,MAAM,cAAc,cAAc;CAElC,OAAO,EAAE,KACP,EAAE,QAAiC,UAAU;EAC3C,IAAI,OAAO,UAAU,UAAU,OAAO;EAEtC,MAAM,CAAC,UAAU,YAAY,YAAY,MAAM,MAAM,IAAI;EAEzD,OAAO,aAAa,QAAQ,eAAe,UAAU,OAAO,aAAa;CAC3E,GAAG,8BAA8B,UAAU,MAAM,YAAY,qBAAqB,UAAU,QAAQ,KAAK,MAAM,YAAY,QAAQ,OAAO,mDAAmD,CAC/L;AACF;;;AC5CA,IAAY,iBAAL,yBAAA,gBAAA;CACL,eAAA,aAAA;CACA,eAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,mBAAL,yBAAA,kBAAA;CACL,iBAAA,gBAAA;CACA,iBAAA,SAAA;;AACF,EAAA,CAAA,CAAA;AAEA,MAAa,sCAAsC,8CAGjD;CACA,QAAA;CACA,MAAA;CACA,UAAU;AACZ,CAAC;AAED,MAAa,sCAAsC,8CAGjD;CACA,QAAA;CACA,MAAA;CACA,UAAU;CACV,eAAe;AACjB,CAAC;AAwBD,MAAa,qCAAqC,8CAGhD;CACA,QAAA;CACA,MAAA;CACA,UAAU;AACZ,CAAC;AAED,MAAa,qCAAqC,8CAGhD;CACA,QAAA;CACA,MAAA;CACA,UAAU;CACV,eAAe;AACjB,CAAC;AAED,MAAa,2BAA2B,EAAE,OAAO;CAC/C,WAAW;CACX,YAAY;AACd,CAAC;AAID,MAAa,4BAA4B,EAAE,OAAO;CAChD,WAAW;CACX,YAAY;AACd,CAAC;AA0BD,MAAa,sCAAsC,EAAE,OAAO;CAC1D,WAAW,EAAE,OAAO;CACpB,iBAAiB;AACnB,CAAC;AAED,MAAa,gDAAgD,EAAE,UAAU,CACvE,qCACA,EAAE,OAAO,EACP,gBAAgB,EAAE,SAAS,EAAE,QAAQ,CAAC,EACxC,CAAC,CACH,CAAC;AAUD,MAAa,0BAA0B,EAAE,OAAO;CAC9C,OAAO;CACP,YAAY;AACd,CAAC;;;;;;;;AC/GD,MAAa,sCAAsC,yCAGjD;AAEF,MAAa,sCAAsC,yCAIjD,EAAE,eAAe,KAAK,CAAC;AAEzB,MAAa,wCAAwC,yCAGnD,EACA,yBAAyB,CAAA,KAAqB,EAChD,CAAC;AAED,MAAa,kDACX,UACmC;CAGnC,OAAO;EACL,UAAU;EACV,aAJkB,oCAAoC,KAI5C;CACZ;AACF;AAEA,MAAa,kDACX,UACmC;CAGnC,OAAO;EACL,UAAU;EACV,aAJkB,oCAAoC,KAI5C;CACZ;AACF;AAEA,MAAa,oDAMX,UACM;CACN,OAAO,sCAAsC,KAAK;AACpD;;;;;;AAQA,MAAa,qCAAqC,yCAGhD;AAEF,MAAa,qCAAqC,yCAIhD,EAAE,eAAe,KAAK,CAAC;AAEzB,MAAa,uCAAuC,yCAGlD,EACA,yBAAyB,CAAA,KAAqB,EAChD,CAAC;AAED,MAAa,iDACX,UACkC;CAGlC,OAAO;EACL,UAAU;EACV,aAJkB,mCAAmC,KAI3C;CACZ;AACF;AAEA,MAAa,iDACX,UACkC;CAGlC,OAAO;EACL,UAAU;EACV,aAJkB,mCAAmC,KAI3C;CACZ;AACF;AAEA,MAAa,mDAMX,UACM;CACN,OAAO,qCAAqC,KAAK;AACnD;;;ACxHA,MAAMA,eAAa,OACjB,YACA,UACA,gBACuB;CACvB,MAAM,YAAY,WAAW,KAAK,OAAO,OAAO,UAAU,CAAC;CAE3D,OAAO,MAAM,OAAO,OAAO,UACzB,OACA,WACA,EAAE,MAAM,UAAU,GAClB,aACA,QACF;AACF;AAEA,MAAMC,YAAU,OACd,KACA,UACA,cAAc,SACS;CACvB,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,KAAK,EAAE,MAAM,UAAU,GAAG,aAAa,QAAQ;AAC7F;AAEA,MAAMC,yBAAuB,OAO3B,YACA,UACA,cAAc,SACS;CACvB,IAAI,WAAW,WAAA,OACb,OAAO,MAAMD,UAAQ,WAAW,MAAM,UAAU,WAAW;CAG7D,OAAO,MAAMD,aAAW,WAAW,MAAM,UAAU,WAAW;AAChE;AAEA,MAAMG,wBAAsB,OAK1B,YACA,UACA,cAAc,SACS;CAEvB,OAAO,MAAMD,uBADO,iDAAiD,UACzB,GAAG,UAAU,WAAW;AACtE;AAEA,MAAME,iCACJ,UACA,UAEC;CACC,cAAc,UAAa,KAAK,OAAO,UAAU,IAAI;CACrD,iBAAiB,UAAa,KAAK,OAAO,UAAU,KAAK;AAC3D;AAEF,MAAa,mBAAmB;CAC9B,SAAS;EACP,qBAAqBA,8BACnB,CAAC,MAAM,GACPD,qBACF;EACA,sBAAsBC,8BACpB,CAAC,MAAM,GACPF,sBACF;EACA,SAASE,8BAA4B,CAAC,MAAM,GAAGH,SAAO;CACxD;CACA,QAAQ;EACN,YAAYG,8BAA4B,CAAC,QAAQ,GAAGJ,YAAU;EAC9D,qBAAqBI,8BACnB,CAAC,QAAQ,GACTD,qBAGF;EACA,sBAAsBC,8BACpB,CAAC,QAAQ,GACTF,sBAIF;EACA,SAASE,8BAA4B,CAAC,QAAQ,GAAGH,SAAO;CAC1D;AACF;;;AChGA,MAAa,0BAA0B,OACrC,QAC4C;CAC5C,MAAM,SAAS,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAEvD,MAAM,WACJ,iBAAuD,KAAK,UAAU,MAAM;CAS9E,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACfA,MAAa,0BAA0B,OACrC,cAC4C;CAC5C,MAAM,kBAAkB,MAAM,OAAO,OAAO,UAAU,OAAO,SAAS;CACtE,MAAM,kBAAkB,OAAO,OAAO,IAAI,WAAW,eAAe,CAAC;CAErE,MAAM,WACJ,wBAA8D;CAShE,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACvBA,MAAa,uBAAuB,OAAO,EACzC,WACA,iBACA,gBAKsB;CACtB,MAAM,kBAAkB,WAAW,KAAK,OAAO,OAAO,eAAe,CAAC;CACtE,MAAM,kBAAkB,IAAI,YAAY,CAAC,CAAC,OAAO,SAAS;CAE1D,OAAO,MAAM,OAAO,OAAO,OACzB,EACE,MAAM,UACR,GACA,WACA,iBACA,eACF;AACF;;;ACtBA,MAAa,wBAAwB,YAAoC;CAMvE,OAAO,MALgB,OAAO,OAAO,YAAY,EAAE,MAAM,SAAS,GAAG,MAAM,CACzE,aACA,YACF,CAAC;AAGH;;;ACGA,MAAM,aAAa,OACjB,YACA,UACA,gBACuB;CACvB,MAAM,YAAY,WAAW,KAAK,OAAO,OAAO,UAAU,CAAC;CAE3D,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,WAAW,EAAE,MAAM,SAAS,GAAG,aAAa,QAAQ;AAClG;AAEA,MAAM,UAAU,OACd,KACA,UACA,cAAc,SACS;CACvB,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,KAAK,EAAE,MAAM,SAAS,GAAG,aAAa,QAAQ;AAC5F;AAEA,MAAM,uBAAuB,OAO3B,YACA,UACA,cAAc,SACS;CACvB,IAAI,WAAW,WAAA,OACb,OAAO,MAAM,QAAQ,WAAW,MAAM,UAAU,WAAW;CAG7D,OAAO,MAAM,WAAW,WAAW,MAAM,UAAU,WAAW;AAChE;AAEA,MAAM,sBAAsB,OAK1B,YACA,UACA,cAAc,SACS;CAEvB,OAAO,MAAM,qBADO,gDAAgD,UACxB,GAAG,UAAU,WAAW;AACtE;AAEA,MAAM,+BACJ,UACA,UAEC;CACC,cAAc,UAAa,KAAK,OAAO,UAAU,IAAI;CACrD,iBAAiB,UAAa,KAAK,OAAO,UAAU,KAAK;AAC3D;AAEF,MAAa,kBAAkB;CAC7B,SAAS;EACP,qBAAqB,4BACnB,CAAC,aAAa,YAAY,GAC1B,mBACF;EACA,sBAAsB,4BACpB,CAAC,aAAa,YAAY,GAC1B,oBACF;EACA,SAAS,4BAA4B,CAAC,aAAa,YAAY,GAAG,OAAO;CAC3E;CACA,QAAQ;EACN,YAAY,4BAA4B,CAAC,GAAG,UAAU;EACtD,qBAAqB,4BACnB,CAAC,GACD,mBAGF;EACA,sBAAsB,4BACpB,CAAC,GACD,oBAIF;EACA,SAAS,4BAA4B,CAAC,GAAG,OAAO;CAClD;AACF;;;AC1FA,MAAa,yBAAyB,OACpC,QAC2C;CAC3C,MAAM,eAAe,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAE7D,MAAM,WACJ,gBAAsD,KAAK,UAAU,YAAY;CASnF,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACfA,MAAa,yBAAyB,OACpC,QAC2C;CAC3C,MAAM,kBAAkB,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAChE,MAAM,kBAAkB,OAAO,OAAO,IAAI,WAAW,eAAe,CAAC;CAErE,MAAM,WACJ,uBAA6D;CAS/D,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;AC0FA,IAAa,sBAAb,MAAiC;CAC/B;CACA;CACA,mCAA2B,IAAI,IAA2C;CAC1E;CACA,cAAsB;CACtB;CACA;CACA;CAEA,YAAY,EAAE,mBAAqD,CAAC,GAAG;EACrE,IAAI,kBAAkB,MACpB,KAAK,UAAU,mBAAmB,EAAE,eAAe,CAAC;CAExD;;;;;;;CAQA,MAAM,aAA4B;EAChC,IAAI,KAAK,aACP;EAKF,KAAK,sBAAsB,KAAK,cAAc;EAE9C,IAAI;GACF,MAAM,KAAK;EACb,UAAU;GACR,KAAK,oBAAoB,KAAA;EAC3B;CACF;CAEA,MAAc,gBAA+B;EAC3C,MAAM,KAAK,oBAAoB;EAC/B,MAAM,KAAK,kBAAkB;EAE7B,KAAK,cAAc;CACrB;;;;;;;CAQA,MAAc,sBAAqC;EACjD,MAAM,iBAAiB,MAAM,KAAK,SAAS,QAAQ,sBAAsB;EACzE,IAAI,kBAAkB,MACpB,KAAK,uBAAuB;GAC1B,YAAY,MAAM,gBAAgB,QAAQ,oBAAoB,YAC5D,eAAe,UACjB;GACA,WAAW,MAAM,gBAAgB,OAAO,oBAAoB,YAC1D,eAAe,SACjB;EACF;EAGF,MAAM,eAAe,MAAM,KAAK,SAAS,QAAQ,oBAAoB;EACrE,IAAI,gBAAgB,MAClB,KAAK,qBAAqB;GACxB,YAAY,MAAM,iBAAiB,QAAQ,oBAAoB,YAC7D,aAAa,UACf;GACA,WAAW,MAAM,iBAAiB,OAAO,oBAAoB,YAC3D,aAAa,SACf;EACF;CAEJ;;;;;CAMA,MAAc,6BAAqD;EACjE,IAAI,KAAK,wBAAwB,MAC/B,OAAO,KAAK;EAGd,KAAK,iCAAiC,YAAY;GAChD,MAAM,UAAU,MAAM,sBAAsB;GAC5C,KAAK,uBAAuB;GAC5B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QACjB,wBACA,MAAM,KAAK,yBAAyB,OAAO,CAC7C;GAEF,OAAO;EACT,EAAA,CAAG;EAEH,IAAI;GACF,OAAO,MAAM,KAAK;EACpB,UAAU;GACR,KAAK,8BAA8B,KAAA;EACrC;CACF;;;;;CAMA,MAAc,2BAAmD;EAC/D,IAAI,KAAK,sBAAsB,MAC7B,OAAO,KAAK;EAGd,KAAK,+BAA+B,YAAY;GAC9C,MAAM,UAAU,MAAM,uBAAuB;GAC7C,KAAK,qBAAqB;GAC1B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QACjB,sBACA,MAAM,KAAK,uBAAuB,OAAO,CAC3C;GAEF,OAAO;EACT,EAAA,CAAG;EAEH,IAAI;GACF,OAAO,MAAM,KAAK;EACpB,UAAU;GACR,KAAK,4BAA4B,KAAA;EACnC;CACF;CAEA,MAAc,oBAAmC;EAC/C,MAAM,sBAAsB,MAAM,KAAK,SAAS,QAAQ,wBAAwB;EAEhF,IAAI,uBAAuB,MACzB;EAGF,KAAK,MAAM,CAAC,gBAAgB,eAAe,OAAO,QAAQ,mBAAmB,GAI3E,MAAM,KAAK,WAAW;GACpB;GACA,iBAAiB,WAAW;GAC5B,mBAAmB,WAAW;GAC9B,YAAY,WAAW;GACvB,YAAY,WAAW;GACvB,8BAA8B,WAAW;EAC3C,CAAC;CAEL;CAEA,MAAc,yBACZ,SAC6C;EAC7C,OAAO;GACL,YAAY,MAAM,uBAAuB,QAAQ,SAAS,EAAA,CAAG;GAC7D,aAAa,MAAM,uBAAuB,QAAQ,UAAU,EAAA,CAAG;EACjE;CACF;CAEA,MAAc,uBACZ,SAC8C;EAC9C,OAAO;GACL,YAAY,MAAM,wBAAwB,QAAQ,SAAS,EAAA,CAAG;GAC9D,aAAa,MAAM,wBAAwB,QAAQ,UAAU,EAAA,CAAG;EAClE;CACF;;;;;;CAOA,MAAM,qBAAgD;EACpD,OAAO;GACL,iBAAiB,MAAM,KAAK,wBAAwB;GACpD,mBAAmB,MAAM,KAAK,0BAA0B;EAC1D;CACF;;;;;;CAOA,MAAM,4BAA0E;EAE9E,QAAQ,MAAM,wBAAuB,MADP,KAAK,2BAA2B,EAAA,CACT,SAAS,EAAA,CAAG;CACnE;;;;;CAMA,MAAM,0BAAyE;EAE7E,QAAQ,MAAM,yBAAwB,MADV,KAAK,yBAAyB,EAAA,CACN,SAAS,EAAA,CAAG;CAClE;;;;;;;;;CAUA,MAAM,WAAW,EACf,gBACA,iBACA,mBACA,YACA,YACA,gCACiC;EACjC,MAAM,WAAW,KAAK,iBAAiB,IAAI,cAAc;EAEzD,MAAM,SACJ,mBAAmB,OACf;GACE,WACE,MAAM,iBAAiB,OAAO,oBAAoB,YAAY,eAAe;GAC/E,qBAAqB;EACvB,IACA,UAAU;EAEhB,MAAM,mBACJ,mBAAmB,QAAQ,oBAAoB,UAAU,QAAQ;EAEnE,IAAI,WAAW,UAAU;EASzB,IALE,qBAAqB,QACrB,eAAe,KAAA,KACf,eAAe,KAAA,KACf,iCAAiC,KAAA,GAEP;GAC1B,MAAM,0BAA0B,qBAAqB,UAAU,UAAU;GAEzE,IAAI,2BAA2B,MAC7B,MAAM,IAAI,MACR,iDAAiD,eAAe,gCAClE;GAGF,MAAM,WAAW,eAAe,KAAA,IAAY,aAAa,UAAU,UAAU;GAC7E,MAAM,WAAW,eAAe,KAAA,IAAY,aAAa,UAAU,UAAU;GAC7E,MAAM,WACJ,iCAAiC,KAAA,IAC7B,+BACA,UAAU,UAAU;GAgB1B,WAAW;IACT,WAdA,qBAAqB,OACjB,MAAM,gBAAgB,OAAO,oBAAoB,YAAY,iBAAiB,IAE9E,SAAU,SAAU;IAYxB,qBAAqB;IACrB,YAAY;IACZ,YAAY;IACZ,8BAA8B;IAE9B,kBAdA,4BAA4B,UAAU,UAAU,uBAChD,aAAa,UAAU,UAAU,cACjC,aAAa,UAAU,UAAU,cACjC,aAAa,UAAU,UAAU,gCAEjC,EAAE,aAAa,QAAQ,oBASO,UAAU,UAAU,mBAAmB,KAAA;GACvE;EACF,OAAO,IACL,UAAU,iCAAiC,QAC3C,oBACA,SAAS,oBAAoB,MAG7B,WAAW;GAAE,GAAG;GAAU,kBAAkB,KAAA;EAAU;EAGxD,KAAK,iBAAiB,IAAI,gBAAgB;GAAE;GAAQ;EAAS,CAAC;CAChE;;;;;;;;CASA,MAAM,mBAAmB,OAAuC;EAC9D,MAAM,KAAK,WAAW,KAAK;EAE3B,IAAI,KAAK,WAAW,MAClB;EAGF,MAAM,EACJ,gBACA,iBACA,mBACA,YACA,YACA,iCACE;EAEJ,MAAM,KAAK,QAAQ,kBAAkB,0BAA0B,CAAC,IAAI,aAAa;GAC/E,GAAG;IACF,iBAAiB;IAChB,GAAG,QAAQ;IACX,GAAI,mBAAmB,OAAO,EAAE,gBAAgB,IAAI,CAAC;IACrD,GAAI,qBAAqB,OAAO,EAAE,kBAAkB,IAAI,CAAC;IACzD,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;IACjD,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;IACjD,GAAI,iCAAiC,KAAA,IAAY,EAAE,6BAA6B,IAAI,CAAC;GACvF;EACF,EAAE;CACJ;;;;CAKA,gBAAgB,gBAAqC;EACnD,OAAO,KAAK,iBAAiB,IAAI,cAAc;CACjD;;;;;;CAOA,0BAA0B,gBAAiE;EACzF,MAAM,eAAe,KAAK,iBAAiB,IAAI,cAAc;EAE7D,IAAI,gBAAgB,MAClB;EAGF,OAAO;GACL,iBAAiB,aAAa,QAAQ;GACtC,mBAAmB,aAAa,UAAU;EAC5C;CACF;;;;;CAMA,MAAM,aAAa,gBAA2C;EAC5D,KAAK,iBAAiB,OAAO,cAAc;EAE3C,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,WAAW,2BAA2B,YAAY;GACnE,IAAI,WAAW,MACb,OAAO,CAAC;GAGV,MAAM,GAAG,iBAAiB,UAAU,GAAG,SAAS;GAChD,OAAO;EACT,CAAC;CAEL;;;;;CAMA,MAAM,mBAAkC;EACtC,KAAK,iBAAiB,MAAM;EAE5B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QAAQ,0BAA0B,CAAC,CAAC;CAE3D;;;;;;;;;CAUA,MAAM,QAAuB;EAC3B,KAAK,iBAAiB,MAAM;EAC5B,KAAK,uBAAuB,KAAA;EAC5B,KAAK,qBAAqB,KAAA;EAC1B,KAAK,cAAc;EAEnB,IAAI,KAAK,WAAW,MAAM;GACxB,MAAM,KAAK,QAAQ,WAAW,wBAAwB;GACtD,MAAM,KAAK,QAAQ,WAAW,sBAAsB;GACpD,MAAM,KAAK,QAAQ,WAAW,oBAAoB;EACpD;CACF;CAEA,gBAAwB,gBAAuD;EAC7E,MAAM,eAAe,KAAK,iBAAiB,IAAI,cAAc;EAE7D,IAAI,gBAAgB,MAClB,MAAM,IAAI,MAAM,6CAA6C,gBAAgB;EAG/E,OAAO;CACT;CAEA,MAAc,4BACZ,wBACoB;EACpB,MAAM,eAAe,KAAK,gBAAgB,sBAAsB;EAEhE,IAAI,aAAa,UAAU,oBAAoB,MAC7C,OAAO,aAAa,SAAS;EAG/B,IAAI,aAAa,UAAU,aAAa,MACtC,MAAM,IAAI,MACR,uDAAuD,wBACzD;EAGF,MAAM,uBAAuB,MAAM,KAAK,2BAA2B;EAEnE,IAAI,aAAa,aAAa,SAAS;EAEvC,IAAI,aAAa,SAAS,iCAAiC,MAAM;GAC/D,MAAM,wBAAwB,aAAa,QAAQ;GAEnD,IAAI,yBAAyB,MAC3B,MAAM,IAAI,MACR,iCAAiC,uBAAuB,wEAC1D;GAGF,aAAa,8BAA8B;IACzC,YAAY,aAAa,SAAS;IAClC,kBAAkB,CAAC,MAAM,KAAK,wBAAwB,GAAG,qBAAqB;GAChF,CAAC;EACH;EAEA,MAAM,mBAAmB,MAAM,8BAA8B;GAC3D,0BAA0B,qBAAqB;GAC/C,yBAAyB,aAAa,SAAS;GAC/C,YAAY,aAAa,SAAS;GAClC;EACF,CAAC;EAED,KAAK,iBAAiB,IAAI,wBAAwB;GAChD,GAAG;GACH,UAAU;IACR,GAAG,aAAa;IAChB;GACF;EACF,CAAC;EAED,OAAO;CACT;CAEA,MAAM,2BAA2B,EAC/B,eACA,kBACgE;EAGhE,OAAO,MAAM,6BAA6B;GACxC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;CAEA,MAAM,4BAA4B,EAChC,eACA,kBACgD;EAGhD,OAAO,MAAM,6BAA6B;GACxC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;;;;;;CAOA,MAAM,4BAA4B,EAChC,eACA,kBAIiC;EAGjC,OAAO,MAAM,0BAA0B;GACrC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;;CAGA,MAAM,6BAA6B,EACjC,eACA,kBAIsB;EAGtB,OAAO,MAAM,0BAA0B;GACrC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;CAEA,MAAM,kCAAkC,EACtC,eACA,kBAIC;EACD,MAAM,EAAE,oBAAoB,MAAM,KAAK,cAAc,CAAC,aAAa,CAAC;EAMpE,OAAO;GACL,eAAA,MAN0B,KAAK,2BAA2B;IAC1D;IACA;GACF,CAAC;GAIC;EACF;CACF;;;;;;;;CASA,MAAM,qCAAqC,EACzC,eACA,gBACA,mBACqF;EACrF,MAAM,OAAO,MAAM,KAAK,4BAA4B;GAClD;GACA;EACF,CAAC;EAQD,OAAO;GAAE;GAAM,SAAA,MANO,KAAK,gCAAgC;IACzD;IACA,WAAW;IACX;GACF,CAAC;EAEsB;CACzB;CAEA,MAAM,cAAc,WAEjB;EACD,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,qBAAqB,MAAM,KAAK,yBAAyB;EAE/D,MAAM,YACJ,UAAU,SAAS,IACf,MAAM,mCAAmC,WAAW,mBAAmB,UAAU,IACjF,MAAM,2BAA2B,UAAU,IAAI,mBAAmB,UAAU;EAElF,OAAO,EACL,iBAAiB,OAAO,OAAO,SAAS,EAC1C;CACF;;;;CAKA,MAAM,gCAAgC,EACpC,gBACA,WACA,mBACqD;EACrD,MAAM,eAAe,KAAK,gBAAgB,cAAc;EAExD,IAAI,aAAa,QAAQ,aAAa,MACpC,MAAM,IAAI,MAAM,qDAAqD,gBAAgB;EAGvF,OAAO,MAAM,qBAAqB;GAChC;GACA;GACA,WAAW,aAAa,OAAO;EACjC,CAAC;CACH;AACF;;;ACttBA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,YAAA;CACA,oBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;;;ACYA,IAAa,iBAAb,MAAa,eAAe;CAC1B;CACA;CACA;CAEA,YAAY,EAAE,SAAS,WAAW,sBAAsB,aAAyC;EAC/F,KAAK,iBAAiB;EACtB,KAAK,YAAY,aAAa;EAC9B,MAAM,aAAa,aAAa;EAGhC,KAAK,iBAAiB,aAClB,mBAAmB,EACjB,gBAAgB,IAAI,eAAe;GAAE;GAAS;GAAW,sBAAsB;EAAM,CAAC,EACxF,CAAC,IACD,KAAA;CACN;CAEA,eAAuB,QAAwB;EAC7C,OAAO,GAAG,KAAK,YAAY;CAC7B;;;;;;CAOA,cAAc,aAAqC;EACjD,OAAO,IAAI,eAAe;GACxB,SAAS,KAAK;GACd,WAAW,GAAG,KAAK,YAAY;EACjC,CAAC;CACH;CAEA,MAAc,aAAa,QAA+B;EACxD,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,KAAK,eAAe,kBAAkB,gBAAgB,CAAC,IAAI,gBAAgB;GAC/E,IAAI,CAAC,YAAY,SAAS,MAAM,GAC9B,OAAO,CAAC,GAAG,aAAa,MAAM;GAEhC,OAAO;EACT,CAAC;CACH;CAEA,MAAc,eAAe,QAA+B;EAC1D,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,KAAK,eAAe,kBAAkB,gBAAgB,CAAC,IAAI,gBAAgB;GAC/E,OAAO,YAAY,QAAQ,MAAM,MAAM,MAAM;EAC/C,CAAC;CACH;CAEA,MAAM,WAA0B;EAC9B,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,UAAW,MAAM,KAAK,eAAe,aAAa,gBAAgB,CAAC,CAAC,KAAM,CAAC;EAEjF,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,QAAQ;GACzB,MAAM,KAAK,WAAW,GAAG;EAC3B,CAAC,CACH;EAEA,MAAM,KAAK,eAAe,QAAQ,gBAAgB,CAAC,CAAC;CACtD;CAEA,MAAM,WAAW,QAA+B;EAC9C,MAAM,KAAK,eAAe,WAAW,KAAK,eAAe,MAAM,CAAC;EAChE,MAAM,KAAK,eAAe,MAAM;CAClC;CAEA,MAAM,QAAQ,QAAgB,OAAY;EACxC,MAAM,MAAM,KAAK,eAAe,MAAM;EAEtC,IAAI,KAAK,eAAe,SAAA,UACtB,MAAM,KAAK,eAAe,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;OAE5D,MAAM,KAAK,eAAe,QAAQ,KAAK,KAAK;EAG9C,MAAM,KAAK,aAAa,MAAM;CAChC;CAEA,MAAM,QAAW,QAAwC;EACvD,MAAM,MAAM,KAAK,eAAe,MAAM;EAEtC,IAAI,KAAK,eAAe,SAAA,UAAqC;GAC3D,MAAM,MAAM,MAAM,KAAK,eAAe,QAAQ,GAAG;GAEjD,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD;GAGF,OAAO,KAAK,MAAM,GAAG;EACvB,OAAO;GACL,MAAM,MAAM,MAAM,KAAK,eAAe,QAAW,GAAG;GAEpD,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD;GAGF,OAAO;EACT;CACF;CAEA,MAAM,aAAgB,QAAgB,QAAuB;EAC3D,IAAI,KAAK,eAAe,SAAA,UAAqC;GAC3D,MAAM,MAAM,MAAM,KAAK,eAAe,QAAQ,KAAK,eAAe,MAAM,CAAC;GAEzE,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD,OAAO;GAGT,OAAO,KAAK,MAAM,GAAG;EACvB;EAEA,MAAM,MAAM,MAAM,KAAK,eAAe,QAAW,KAAK,eAAe,MAAM,CAAC;EAE5E,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD,OAAO;EAGT,OAAO;CACT;CAEA,MAAM,WAAc,QAAgB,SAAuD;EAEzF,MAAM,SAAS,QAAQ,MADE,KAAK,QAAW,MAAM,CACd;EACjC,MAAM,KAAK,QAAQ,QAAQ,MAAM;EACjC,OAAO;CACT;CAEA,MAAM,gBAAmB,QAAgB,QAAW,SAA2C;EAE7F,MAAM,SAAS,QAAQ,MADE,KAAK,aAAgB,QAAQ,MAAM,CAC3B;EACjC,MAAM,KAAK,QAAQ,QAAQ,MAAM;EACjC,OAAO;CACT;CAEA,uBAA0B,QAA+C;EACvE,OAAO;GACL,WAAW,KAAK,QAAQ,MAAM;GAC9B,MAAM,UAAa,KAAK,QAAQ,QAAQ,KAAK;EAC/C;CACF;AACF;;;AC/IA,SAAgB,6BACd,eAC+B;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,cAAc,QAAQ,GAAG;EACjD,SAAS,OAAO,KAAK,UAAU;GAC7B,cAAc,QAAQ,KAAK,KAAK;EAClC;EACA,YAAY,OAAO,QAAQ;GACzB,cAAc,WAAW,GAAG;EAC9B;CACF;AACF;AAEA,MAAa,gCAAgC,EAC3C,cAAc,eACd,GAAG,cACgD;CACnD,OAAO,IAAI,eAAe;EACxB,SAAS,6BAA6B,aAAa;EACnD,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,2BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,6BAA6B,OAAO,EACtD,CAAC;AACH;AAYA,SAAgB,+BACd,iBAC+B;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,gBAAgB,QAAQ,GAAG;EACnD,SAAS,OAAO,KAAK,UAAU;GAC7B,gBAAgB,QAAQ,KAAK,KAAK;EACpC;EACA,YAAY,OAAO,QAAQ;GACzB,gBAAgB,WAAW,GAAG;EAChC;CACF;AACF;AAEA,MAAa,kCAAkC,EAC7C,gBAAgB,iBAChB,GAAG,cACkD;CACrD,OAAO,IAAI,eAAe;EACxB,SAAS,+BAA+B,eAAe;EACvD,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,6BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,+BAA+B,OAAO,EACxD,CAAC;AACH;;;ACnFA,SAAgB,kCACd,sBAC6B;CAC7B,OAAO;EACL,MAAA;EACA,UAAU,QAAQ,qBAAqB,IAAI,GAAG;EAC9C,UAAU,KAAK,UAAU,qBAAqB,IAAI,KAAK,KAAK;EAC5D,YAAY,OAAO,QAAQ;GACzB,MAAM,qBAAqB,OAAO,GAAG;EACvC;CACF;AACF;;;;;AAUA,MAAa,qCAAqC,EAChD,sBACA,GAAG,cACqD;CACxD,OAAO,IAAI,eAAe;EACxB,SAAS,kCAAkC,oBAAoB;EAC/D,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,gCACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,kCAAkC,OAAO,EAC3D,CAAC;AACH;;;AC9BA,SAAgB,uBAAuB,EACrC,aACA,qBACgE;CAChE,OAAO;EACL,MAAA;EACA,UAAU,QAAQ,YAAY,IAAI,GAAG;EACrC,UAAU,KAAK,UAAU,YAAY,IAAI,KAAK,OAAO,iBAAiB;EACtE,aAAa,QAAQ,YAAY,OAAO,GAAG;CAC7C;AACF;;;;;AASA,MAAa,0BAA0B,EACrC,aACA,mBACA,GAAG,cAC0C;CAC7C,OAAO,IAAI,eAAe;EACxB,SAAS,uBAAuB;GAAE;GAAa;EAAkB,CAAC;EAClE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,qBACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,uBAAuB,OAAO,EAChD,CAAC;AACH;;;AC9BA,SAAgB,kCACd,mCAA0C,IAAI,IAAI,GACnB;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,iBAAiB,IAAI,GAAG,KAAK;EACrD,SAAS,OAAO,KAAK,UAAU;GAC7B,iBAAiB,IAAI,KAAK,KAAK;EACjC;EACA,YAAY,OAAO,QAAQ;GACzB,iBAAiB,OAAO,GAAG;EAC7B;CACF;AACF;AAEA,MAAa,qCACX,YACmB;CACnB,OAAO,IAAI,eAAe;EACxB,SAAS,kCAAkC,SAAS,gBAAgB;EACpE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,gCACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,kCAAkC,OAAO,EAC3D,CAAC;AACH;AAYA,SAAgB,gCACd,mCAAwC,IAAI,IAAI,GACnB;CAC7B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,iBAAiB,IAAI,GAAG;EAChD,SAAS,OAAO,KAAK,UAAU;GAC7B,iBAAiB,IAAI,KAAK,KAAK;EACjC;EACA,YAAY,OAAO,QAAQ;GACzB,iBAAiB,OAAO,GAAG;EAC7B;CACF;AACF;AAEA,MAAa,mCACX,YACmB;CACnB,OAAO,IAAI,eAAe;EACxB,SAAS,gCAAgC,SAAS,gBAAgB;EAClE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,8BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,gCAAgC,OAAO,EACzD,CAAC;AACH"}
1
+ {"version":3,"file":"index.mjs","names":["fromBase64","fromJwk","fromSerializedObject","fromFormattedString","extractableOrNonExtractable"],"sources":["../src/data_type/string/nullEmpty.ts","../src/crypto/x25519/createSharedBitsFromX25519.ts","../src/crypto/aes_gcm/createAesGcmKeyFromX25519Keys.ts","../src/crypto/aes_gcm/decryptBytesWithAesGcmKey.ts","../src/crypto/aes_gcm/decryptTextDataWithAesGcmKey.ts","../src/crypto/aes_gcm/encryptBytesWithAesGcmKey.ts","../src/crypto/aes_gcm/encryptTextDataWithAesGcmKey.ts","../src/crypto/ed25519/signTextDataWithKeyEd25519.ts","../src/crypto/ed25519/signCombinedTextDataWithKeyEd25519.ts","../src/crypto/client_key_link/buildVerifyKeyBoundInfoString.ts","../src/storage_adapter/typed_storage/createTypedStorage.ts","../src/crypto/ed25519/generateEd25519KeyPair.ts","../src/core/createDataStringConverter_stringToObject.ts","../src/core/core_valibot_schemas.ts","../src/crypto/crypto.schema.ts","../src/crypto/crypto.converters.ts","../src/crypto/ed25519/importEd25519Key.ts","../src/crypto/ed25519/serializeEd25519Key_Jwk.ts","../src/crypto/ed25519/serializeEd25519Key_Raw.ts","../src/crypto/ed25519/verifyWithKeyEd25519.ts","../src/crypto/x25519/generateX25519KeyPair.ts","../src/crypto/x25519/importX25519Key.ts","../src/crypto/x25519/serializeX25519Key_Jwk.ts","../src/crypto/x25519/serializeX25519Key_Raw.ts","../src/crypto/client_key_link/ClientCryptoKeyLink.ts","../src/storage_adapter/storage_adapter.types.ts","../src/storage_adapter/StorageAdapter.ts","../src/storage_adapter/specific/browser/browser_storage.ts","../src/storage_adapter/specific/cloudflare/durable_object/durable_object_storage.ts","../src/storage_adapter/specific/cloudflare/kv/kv_storage.ts","../src/storage_adapter/specific/memory/memory_storage.ts"],"sourcesContent":["export const notNullEmpty = (str: string | null | undefined): str is string => {\n return str != null && str.length > 0;\n};\n\nexport const nullEmpty = (str: string | null | undefined): str is null | undefined | \"\" => {\n return !notNullEmpty(str);\n};\n\nexport const firstNotNullEmpty = (\n ...strItems: (string | null | undefined)[]\n): string | undefined => {\n for (const item of strItems) {\n if (notNullEmpty(item)) {\n return item;\n }\n }\n\n return undefined;\n};\n","export const createSharedBitsFromX25519 = async ({\n privateKey,\n publicKey,\n}: {\n privateKey: CryptoKey;\n publicKey: CryptoKey;\n}): Promise<Uint8Array> => {\n return new Uint8Array(\n await crypto.subtle.deriveBits({ name: \"X25519\", public: publicKey }, privateKey, 256),\n );\n};\n","import { notNullEmpty } from \"../../data_type/string/nullEmpty\";\nimport { createSharedBitsFromX25519 } from \"../x25519/createSharedBitsFromX25519\";\n\nconst DEFAULT_INFO_STRING = \"METEOR_BRIDGE_DEFAULT_INFO_STRING\";\n\nexport const createAesGcmKeyFromX25519Keys = async ({\n externalX25519PublicKey,\n internalX25519PrivateKey,\n infoString,\n saltString,\n}: {\n internalX25519PrivateKey: CryptoKey;\n externalX25519PublicKey: CryptoKey;\n saltString?: string;\n infoString?: string;\n}): Promise<CryptoKey> => {\n const sharedBits = await createSharedBitsFromX25519({\n privateKey: internalX25519PrivateKey,\n publicKey: externalX25519PublicKey,\n });\n\n // Initial Key Material\n const ikm = await crypto.subtle.importKey(\"raw\", new Uint8Array(sharedBits), \"HKDF\", false, [\n \"deriveKey\",\n ]);\n\n const salt = notNullEmpty(saltString) ? new TextEncoder().encode(saltString) : new Uint8Array();\n const info = new TextEncoder().encode(\n notNullEmpty(infoString) ? infoString : DEFAULT_INFO_STRING,\n );\n\n // Run HKDF to get your final usable key (e.g., AES-GCM)\n return await crypto.subtle.deriveKey(\n {\n name: \"HKDF\",\n hash: \"SHA-256\",\n salt, // Salt\n info, // Context string\n },\n ikm,\n { name: \"AES-GCM\", length: 256 },\n false, // The final AES key shouldn't be exportable\n [\"encrypt\", \"decrypt\"],\n );\n};\n","import type { TEncryptedAesGcmBytes } from \"../crypto.schema\";\r\n\r\n/**\r\n * Decrypts a raw-bytes AES-GCM payload (binary nonce + ciphertext) back to bytes. The counterpart of\r\n * {@link decryptTextDataWithAesGcmKey}. AES-GCM verifies integrity, so a tampered ciphertext throws.\r\n */\r\nexport const decryptBytesWithAesGcmKey = async ({\r\n aesGcmKey,\r\n dataToDecrypt,\r\n}: {\r\n aesGcmKey: CryptoKey;\r\n dataToDecrypt: TEncryptedAesGcmBytes;\r\n}): Promise<Uint8Array> => {\r\n const decryptedData = await crypto.subtle.decrypt(\r\n // Re-view nonce + ciphertext over plain ArrayBuffers so WebCrypto's `BufferSource` is satisfied\r\n // regardless of the source's backing buffer (msgpack output may be pooled / SharedArrayBuffer-typed).\r\n { name: \"AES-GCM\", iv: new Uint8Array(dataToDecrypt.nonce) },\r\n aesGcmKey,\r\n new Uint8Array(dataToDecrypt.ciphertext),\r\n );\r\n\r\n return new Uint8Array(decryptedData);\r\n};\r\n","import { base64 } from \"@scure/base\";\nimport type { TEncryptedAesGcmPayload } from \"../crypto.schema\";\n\nexport const decryptTextDataWithAesGcmKey = async ({\n aesGcmKey,\n dataToDecrypt,\n}: {\n aesGcmKey: CryptoKey;\n dataToDecrypt: TEncryptedAesGcmPayload;\n}): Promise<string> => {\n const decryptedData = await crypto.subtle.decrypt(\n {\n name: \"AES-GCM\",\n iv: new Uint8Array(base64.decode(dataToDecrypt.nonce)),\n },\n aesGcmKey,\n new Uint8Array(base64.decode(dataToDecrypt.ciphertext)),\n );\n\n return new TextDecoder().decode(decryptedData);\n};\n","import type { TEncryptedAesGcmBytes } from \"../crypto.schema\";\r\n\r\n/**\r\n * Encrypts raw bytes with an AES-GCM key, returning the binary nonce + ciphertext. The bytes\r\n * counterpart of {@link encryptTextDataWithAesGcmKey} — use it for binary channels (msgpack frames)\r\n * to avoid base64 inflation. A fresh 12-byte nonce is generated per call (never reuse a nonce).\r\n */\r\nexport const encryptBytesWithAesGcmKey = async ({\r\n aesGcmKey,\r\n dataToEncrypt,\r\n}: {\r\n aesGcmKey: CryptoKey;\r\n dataToEncrypt: Uint8Array;\r\n}): Promise<TEncryptedAesGcmBytes> => {\r\n const nonce = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n const encryptedData = await crypto.subtle.encrypt(\r\n { name: \"AES-GCM\", iv: nonce },\r\n aesGcmKey,\r\n // Re-view over a plain ArrayBuffer so WebCrypto's `BufferSource` is satisfied regardless of the\r\n // source's backing buffer (msgpack output may be pooled / SharedArrayBuffer-typed).\r\n new Uint8Array(dataToEncrypt),\r\n );\r\n\r\n return { nonce, ciphertext: new Uint8Array(encryptedData) };\r\n};\r\n","import { base64 } from \"@scure/base\";\nimport type { TEncryptedAesGcmPayload } from \"../crypto.schema\";\n\nexport const encryptTextDataWithAesGcmKey = async ({\n aesGcmKey,\n dataToEncrypt,\n}: {\n aesGcmKey: CryptoKey;\n dataToEncrypt: string;\n}): Promise<TEncryptedAesGcmPayload> => {\n const nonce = crypto.getRandomValues(new Uint8Array(12));\n\n const encryptedData = await crypto.subtle.encrypt(\n {\n name: \"AES-GCM\",\n iv: nonce,\n },\n aesGcmKey,\n new TextEncoder().encode(dataToEncrypt),\n );\n\n return {\n nonce: base64.encode(nonce),\n ciphertext: base64.encode(new Uint8Array(encryptedData)),\n };\n};\n","export const signTextDataWithKeyEd25519 = async (\n data: string,\n cryptoKey: CryptoKey,\n): Promise<Uint8Array> => {\n const dataBuffer = new TextEncoder().encode(data);\n const signature = await crypto.subtle.sign(\n {\n name: \"ED25519\",\n },\n cryptoKey,\n dataBuffer,\n );\n\n return new Uint8Array(signature);\n};\n","import { signTextDataWithKeyEd25519 } from \"./signTextDataWithKeyEd25519\";\n\nexport const DEFAULT_COMBINED_TEXT_DATA_SEPARATOR = \"::\";\n\nexport const signCombinedTextDataWithKeyEd25519 = async (\n data: string[],\n cryptoKey: CryptoKey,\n separator = DEFAULT_COMBINED_TEXT_DATA_SEPARATOR,\n): Promise<Uint8Array> => {\n return await signTextDataWithKeyEd25519(data.join(separator), cryptoKey);\n};\n","import type { TSerializedCryptoKeyData_Ed25519_Raw } from \"../crypto.schema\";\nimport { DEFAULT_COMBINED_TEXT_DATA_SEPARATOR } from \"../ed25519/signCombinedTextDataWithKeyEd25519\";\n\ninterface IBuildVerifyKeyBoundInfoString_Input {\n infoString?: string;\n verifyPublicKeys: [TSerializedCryptoKeyData_Ed25519_Raw, TSerializedCryptoKeyData_Ed25519_Raw];\n}\n\n/**\n * The canonical HKDF `info` for a client-to-client shared key that binds both sides' verify\n * public keys into the derivation.\n *\n * When the two keys are relayed through an intermediary, a tampered key produces mismatched AES\n * keys on the two sides — the very first decryption fails, so key substitution is detected without\n * any extra signature ceremony.\n *\n * The keys are sorted lexicographically so the result is independent of which side is \"local\" —\n * both ends of a link compute the identical string without coordinating an order. Used internally\n * by ClientCryptoKeyLink (`bindVerifyKeysIntoDerivation`); exported for code that derives the same\n * key outside the link.\n */\nexport const buildVerifyKeyBoundInfoString = ({\n infoString,\n verifyPublicKeys,\n}: IBuildVerifyKeyBoundInfoString_Input): string => {\n const sortedKeys = [...verifyPublicKeys].sort();\n\n return [...(infoString != null ? [infoString] : []), ...sortedKeys].join(\n DEFAULT_COMBINED_TEXT_DATA_SEPARATOR,\n );\n};\n","import type { StringKeys } from \"../../typescript/special_typescript_types\";\nimport type { StorageAdapter } from \"../StorageAdapter\";\n\nexport interface ITypedStorage<T extends Record<string, any>> {\n getJson<K extends StringKeys<T>>(key: K): Promise<T[K] | undefined>;\n getJsonOrDef<K extends StringKeys<T>>(key: K, defVal: T[K]): Promise<T[K]>;\n setJson<K extends StringKeys<T>>(key: K, val: T[K]): Promise<void>;\n removeItem<K extends StringKeys<T>>(key: K): Promise<void>;\n updateJson<K extends StringKeys<T>>(\n key: K,\n updater: (currentVal: T[K] | undefined) => T[K],\n ): Promise<void>;\n updateJsonWithDef<K extends StringKeys<T>>(\n key: K,\n defaultVal: T[K],\n updater: (currentVal: T[K]) => T[K],\n ): Promise<void>;\n clearAll(): Promise<void>;\n}\n\ninterface ITypedStorage_Create_Input {\n storageAdapter: StorageAdapter;\n}\n\nexport function createTypedStorage<T extends Record<string, any>>({\n storageAdapter,\n}: ITypedStorage_Create_Input): ITypedStorage<T> {\n const getJson = async <K extends StringKeys<T>>(key: K): Promise<T[K] | undefined> => {\n return storageAdapter.getJson<T[K]>(key);\n };\n\n const getJsonOrDef = async <K extends StringKeys<T>>(key: K, defVal: T[K]): Promise<T[K]> => {\n return (await storageAdapter.getJson<T[K]>(key)) ?? defVal;\n };\n\n const setJson = async <K extends StringKeys<T>>(key: K, val: T[K]): Promise<void> => {\n return storageAdapter.setJson(key, val);\n };\n\n const removeItem = async <K extends StringKeys<T>>(key: K): Promise<void> => {\n await storageAdapter.removeItem(key);\n };\n\n const updateJson = async <K extends StringKeys<T>>(\n key: K,\n updater: (currentVal: T[K] | undefined) => T[K],\n ): Promise<void> => {\n await storageAdapter.updateJson(key, updater);\n };\n\n const updateJsonWithDef = async <K extends StringKeys<T>>(\n key: K,\n defaultVal: T[K],\n updater: (currentVal: T[K]) => T[K],\n ): Promise<void> => {\n await storageAdapter.updateJsonOrDef(key, defaultVal, updater);\n };\n\n return {\n getJson,\n getJsonOrDef,\n setJson,\n removeItem,\n updateJson,\n updateJsonWithDef,\n clearAll: async () => {\n await storageAdapter.clearAll();\n },\n };\n}\n","export const generateEd25519KeyPair = async (): Promise<CryptoKeyPair> => {\n const keyPair = (await crypto.subtle.generateKey({ name: \"Ed25519\" }, true, [\n \"sign\",\n \"verify\",\n ])) as CryptoKeyPair;\n\n return keyPair;\n};\n","import type { ECryptoKeyFormat } from \"../crypto/crypto.schema\";\n\ninterface ICreateDataStringConverter_StringToObject {\n transformJsonForFormats?: ECryptoKeyFormat[];\n transformJson?: boolean;\n}\n\nexport const createDataStringConverter_stringToObject =\n <T extends string, F extends ECryptoKeyFormat, D = string>({\n transformJsonForFormats = [],\n transformJson = false,\n }: ICreateDataStringConverter_StringToObject = {}) =>\n (\n inputDataString: `${T}::${F}::${string}`,\n ): { formattedString: `${T}::${F}::${string}`; type: T; format: F; data: D } => {\n const [type, format, dataString] = inputDataString.split(\"::\") as [\n string,\n ECryptoKeyFormat,\n string,\n ];\n let parsedData: D = dataString as D;\n\n if (transformJson || transformJsonForFormats.includes(format)) {\n try {\n parsedData = JSON.parse(dataString) as D;\n } catch (error) {\n const err = new Error(\n `Failed to parse type and format data string. Given input: \"${inputDataString}\", expected JSON parsable \"data\" value in the format \"${type}::${format}::data\" ${error instanceof Error ? error.message : String(error)}`,\n );\n\n err.cause = error;\n throw err;\n }\n }\n\n return {\n formattedString: inputDataString,\n type: type as T,\n format: format as F,\n data: parsedData,\n };\n };\n","import * as v from \"valibot\";\n\n// export const vBase64HashSha256 = v.pipe(v.string(), v.base64());\nexport const vBase64 = v.pipe(v.string(), v.base64());\n\nexport const vCreateSchema_TypePrefixedDataString = <P extends string>(\n typeValues: P[],\n typeKind: string,\n) => {\n const _typeKind = typeKind ?? \"data_type\";\n\n return v.pipe(\n v.custom<`${P}::${string}`>(\n (input) => {\n return (\n typeof input === \"string\" && typeValues.some((prefix) => input.startsWith(`${prefix}::`))\n );\n },\n `Invalid format, expected '<${_typeKind}>::<value>' where \"${_typeKind}\" is one of [${typeValues.join(\", \")}] and \"value\" is a string of base64-encoded data of that type`,\n ),\n );\n};\n\nexport interface ICreateTypePrefixedDataStringResult<T extends string, F extends string> {\n type: T;\n format: F;\n typeKind: string;\n formatKind?: string;\n transformJson?: boolean;\n}\n\nexport const vCreateSchema_TypeAndFormatPrefixedDataString = <T extends string, F extends string>({\n type,\n format,\n typeKind,\n formatKind,\n // transformJson = false,\n}: ICreateTypePrefixedDataStringResult<T, F>) => {\n const _typeKind = typeKind ?? \"data_type\";\n const _formatKind = formatKind ?? \"data_format\";\n\n return v.pipe(\n v.custom<`${T}::${F}::${string}`>((input) => {\n if (typeof input !== \"string\") return false;\n\n const [typePart, formatPart, dataPart] = input.split(\"::\") as [string, string, string];\n\n return typePart === type && formatPart === format && typeof dataPart === \"string\";\n }, `Invalid format, expected '<${_typeKind}>::<${_formatKind}>::<value>' where \"${_typeKind}\" is \"${type}\", \"${_formatKind}\" is \"${format}\", and \"value\" is a string in the specified format`),\n );\n};\n\nexport const vCreateSchema_TypeAndId = <S extends string>(dataType: S | S[]) =>\n v.pipe(\n v.custom<`${S}::${string}`>((input) => {\n if (typeof input !== \"string\") {\n return false;\n }\n\n let checkDataTypes: string[];\n\n if (typeof dataType === \"string\") {\n checkDataTypes = [dataType];\n } else if (Array.isArray(dataType)) {\n checkDataTypes = dataType;\n } else {\n throw new Error(\n \"Create Schema for TypeAndId: dataType must be a string or an array of strings\",\n );\n }\n\n if (checkDataTypes.length > 0) {\n return true;\n }\n\n for (const dataTypeCheck in checkDataTypes) {\n if (input.startsWith(`${dataTypeCheck}::`)) return true;\n }\n\n return false;\n }, `Invalid Type and ID formatted string, expected '<data_type>::<id>'`),\n );\n\nexport type TTypeAndId<S extends string = string> = `${S}::${string}`;\n","import * as v from \"valibot\";\r\nimport {\r\n vBase64,\r\n vCreateSchema_TypeAndFormatPrefixedDataString,\r\n} from \"../core/core_valibot_schemas\";\r\n\r\nexport enum ECryptoKeyAlgo {\r\n ed25519 = \"ed25519\",\r\n x25519 = \"x25519\",\r\n}\r\n\r\nexport enum ECryptoKeyFormat {\r\n raw_base64 = \"raw_base64\",\r\n jwk = \"jwk\",\r\n}\r\n\r\nexport const vSerializedCryptoKeyDataEd25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.ed25519,\r\n ECryptoKeyFormat.raw_base64\r\n>({\r\n format: ECryptoKeyFormat.raw_base64,\r\n type: ECryptoKeyAlgo.ed25519,\r\n typeKind: \"algo\",\r\n});\r\n\r\nexport const vSerializedCryptoKeyDataEd25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.ed25519,\r\n ECryptoKeyFormat.jwk\r\n>({\r\n format: ECryptoKeyFormat.jwk,\r\n type: ECryptoKeyAlgo.ed25519,\r\n typeKind: \"algo\",\r\n transformJson: true,\r\n});\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Raw = v.InferInput<\r\n typeof vSerializedCryptoKeyDataEd25519_Raw\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Raw_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.raw_base64}::${string}`;\r\n type: ECryptoKeyAlgo.ed25519;\r\n format: ECryptoKeyFormat.raw_base64;\r\n data: string;\r\n};\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Jwk = v.InferInput<\r\n typeof vSerializedCryptoKeyDataEd25519_Jwk\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.jwk}::${string}`;\r\n type: ECryptoKeyAlgo.ed25519;\r\n format: ECryptoKeyFormat.jwk;\r\n data: JsonWebKey;\r\n};\r\n\r\nexport const vSerializedCryptoKeyDataX25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.x25519,\r\n ECryptoKeyFormat.raw_base64\r\n>({\r\n format: ECryptoKeyFormat.raw_base64,\r\n type: ECryptoKeyAlgo.x25519,\r\n typeKind: \"algo\",\r\n});\r\n\r\nexport const vSerializedCryptoKeyDataX25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString<\r\n ECryptoKeyAlgo.x25519,\r\n ECryptoKeyFormat.jwk\r\n>({\r\n format: ECryptoKeyFormat.jwk,\r\n type: ECryptoKeyAlgo.x25519,\r\n typeKind: \"algo\",\r\n transformJson: true,\r\n});\r\n\r\nexport const vCryptoKeyPairDataX25519 = v.object({\r\n publicKey: vSerializedCryptoKeyDataX25519_Raw,\r\n privateKey: vSerializedCryptoKeyDataX25519_Jwk,\r\n});\r\n\r\nexport type TSerializedCryptoKeyPairDataX25519 = v.InferInput<typeof vCryptoKeyPairDataX25519>;\r\n\r\nexport const vCryptoKeyPairDataEd25519 = v.object({\r\n publicKey: vSerializedCryptoKeyDataEd25519_Raw,\r\n privateKey: vSerializedCryptoKeyDataEd25519_Jwk,\r\n});\r\n\r\nexport type TSerializedCryptoKeyPairDataEd25519 = v.InferInput<typeof vCryptoKeyPairDataEd25519>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Raw = v.InferInput<\r\n typeof vSerializedCryptoKeyDataX25519_Raw\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Raw_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.raw_base64}::${string}`;\r\n type: ECryptoKeyAlgo.x25519;\r\n format: ECryptoKeyFormat.raw_base64;\r\n data: string;\r\n};\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Jwk = v.InferInput<\r\n typeof vSerializedCryptoKeyDataX25519_Jwk\r\n>;\r\n\r\nexport type TSerializedCryptoKeyData_X25519_Jwk_Transformed = {\r\n formattedString: `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.jwk}::${string}`;\r\n type: ECryptoKeyAlgo.x25519;\r\n format: ECryptoKeyFormat.jwk;\r\n data: JsonWebKey;\r\n};\r\n\r\nexport const vVerifyChallengeWithSignature_Input = v.object({\r\n challenge: v.string(),\r\n signatureBase64: vBase64,\r\n});\r\n\r\nexport const vVerifyChallengeWithSignature_WithThrow_Input = v.intersect([\r\n vVerifyChallengeWithSignature_Input,\r\n v.object({\r\n throwOnInvalid: v.optional(v.boolean()),\r\n }),\r\n]);\r\n\r\nexport type TVerifyChallengeWithSignature_Input = v.InferInput<\r\n typeof vVerifyChallengeWithSignature_Input\r\n>;\r\n\r\nexport type TVerifyChallengeWithSignature_WithThrow_Input = v.InferInput<\r\n typeof vVerifyChallengeWithSignature_WithThrow_Input\r\n>;\r\n\r\nexport const vEncryptedAesGcmPayload = v.object({\r\n nonce: vBase64,\r\n ciphertext: vBase64,\r\n});\r\n\r\nexport type TEncryptedAesGcmPayload = v.InferInput<typeof vEncryptedAesGcmPayload>;\r\nexport type TEncryptedAesGcmPayload_Transformed = v.InferOutput<typeof vEncryptedAesGcmPayload>;\r\n\r\n/**\r\n * Raw-bytes counterpart of {@link TEncryptedAesGcmPayload} — keeps `nonce`/`ciphertext` as binary\r\n * instead of base64 strings. For binary channels (e.g. msgpack WebSocket frames) this avoids the\r\n * ~33% base64 inflation the text payload incurs.\r\n */\r\nexport type TEncryptedAesGcmBytes = {\r\n nonce: Uint8Array;\r\n ciphertext: Uint8Array;\r\n};\r\n\r\ninterface ISerializedKeyData<T, P> {\r\n transformed: T;\r\n prefixed: P;\r\n}\r\n\r\nexport interface ISerializedKeyData_Ed25519_Raw\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\r\n TSerializedCryptoKeyData_Ed25519_Raw\r\n > {}\r\n\r\nexport interface ISerializedKeyData_Ed25519_Jwk\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\r\n TSerializedCryptoKeyData_Ed25519_Jwk\r\n > {}\r\n\r\nexport interface ISerializedKeyData_X25519_Raw\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_X25519_Raw_Transformed,\r\n TSerializedCryptoKeyData_X25519_Raw\r\n > {}\r\n\r\nexport interface ISerializedKeyData_X25519_Jwk\r\n extends ISerializedKeyData<\r\n TSerializedCryptoKeyData_X25519_Jwk_Transformed,\r\n TSerializedCryptoKeyData_X25519_Jwk\r\n > {}\r\n\r\nexport type TSerializedKeyData =\r\n | ISerializedKeyData_Ed25519_Raw\r\n | ISerializedKeyData_Ed25519_Jwk\r\n | ISerializedKeyData_X25519_Raw\r\n | ISerializedKeyData_X25519_Jwk;\r\n","import { createDataStringConverter_stringToObject } from \"../core/createDataStringConverter_stringToObject\";\nimport {\n type ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Jwk,\n type ISerializedKeyData_Ed25519_Raw,\n type ISerializedKeyData_X25519_Jwk,\n type ISerializedKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n type TSerializedCryptoKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"./crypto.schema\";\n\n/**\n *\n * [CRYPTO ALGO] ED25519\n *\n */\n\nexport const convertEd25519RawDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.raw_base64\n>();\n\nexport const convertEd25519JwkDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.jwk,\n JsonWebKey\n>({ transformJson: true });\n\nexport const convertEd25519FormattedStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.ed25519,\n ECryptoKeyFormat.raw_base64 | ECryptoKeyFormat.jwk\n>({\n transformJsonForFormats: [ECryptoKeyFormat.jwk],\n});\n\nexport const convertEd25519RawDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_Ed25519_Raw,\n): ISerializedKeyData_Ed25519_Raw => {\n const transformed = convertEd25519RawDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertEd25519JwkDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_Ed25519_Jwk,\n): ISerializedKeyData_Ed25519_Jwk => {\n const transformed = convertEd25519JwkDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertEd25519FormattedStringToSerializedKeyData = <\n I extends TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk,\n O extends I extends TSerializedCryptoKeyData_Ed25519_Raw\n ? TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n : TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n>(\n input: I,\n): O => {\n return convertEd25519FormattedStringToObject(input) as O;\n};\n\n/**\n *\n * [CRYPTO ALGO] X25519\n *\n */\n\nexport const convertX25519RawDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.raw_base64\n>();\n\nexport const convertX25519JwkDataStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.jwk,\n JsonWebKey\n>({ transformJson: true });\n\nexport const convertX25519FormattedStringToObject = createDataStringConverter_stringToObject<\n ECryptoKeyAlgo.x25519,\n ECryptoKeyFormat.raw_base64 | ECryptoKeyFormat.jwk\n>({\n transformJsonForFormats: [ECryptoKeyFormat.jwk],\n});\n\nexport const convertX25519RawDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_X25519_Raw,\n): ISerializedKeyData_X25519_Raw => {\n const transformed = convertX25519RawDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertX25519JwkDataStringToSerializedKeyData = (\n input: TSerializedCryptoKeyData_X25519_Jwk,\n): ISerializedKeyData_X25519_Jwk => {\n const transformed = convertX25519JwkDataStringToObject(input);\n\n return {\n prefixed: input,\n transformed,\n };\n};\n\nexport const convertX25519FormattedStringToSerializedKeyData = <\n I extends TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk,\n O extends I extends TSerializedCryptoKeyData_X25519_Raw\n ? TSerializedCryptoKeyData_X25519_Raw_Transformed\n : TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n>(\n input: I,\n): O => {\n return convertX25519FormattedStringToObject(input) as O;\n};\n","import { base64 } from \"@scure/base\";\nimport { convertEd25519FormattedStringToSerializedKeyData } from \"../crypto.converters\";\nimport {\n ECryptoKeyFormat,\n type TSerializedCryptoKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nconst fromBase64 = async (\n dataBase64: string,\n keyUsage: KeyUsage[],\n extractable: boolean,\n): Promise<CryptoKey> => {\n const keyBuffer = Uint8Array.from(base64.decode(dataBase64));\n\n return await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"Ed25519\" },\n extractable,\n keyUsage,\n );\n};\n\nconst fromJwk = async (\n jwk: JsonWebKey,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n return await crypto.subtle.importKey(\"jwk\", jwk, { name: \"Ed25519\" }, extractable, keyUsage);\n};\n\nconst fromSerializedObject = async <\n D extends\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed =\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n>(\n serialized: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n if (serialized.format === ECryptoKeyFormat.jwk) {\n return await fromJwk(serialized.data, keyUsage, extractable);\n }\n\n return await fromBase64(serialized.data, keyUsage, extractable);\n};\n\nconst fromFormattedString = async <\n D extends TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk =\n | TSerializedCryptoKeyData_Ed25519_Raw\n | TSerializedCryptoKeyData_Ed25519_Jwk,\n>(\n dataString: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n const transformed = convertEd25519FormattedStringToSerializedKeyData(dataString);\n return await fromSerializedObject(transformed, keyUsage, extractable);\n};\n\nconst extractableOrNonExtractable = <I>(\n keyUsage: KeyUsage[],\n func: (input: I, keyUsage: KeyUsage[], extractable: boolean) => Promise<CryptoKey>,\n) =>\n ({\n extractable: (input: I) => func(input, keyUsage, true),\n nonExtractable: (input: I) => func(input, keyUsage, false),\n }) as const;\n\nexport const importEd25519Key = {\n private: {\n fromFormattedString: extractableOrNonExtractable(\n [\"sign\"],\n fromFormattedString<TSerializedCryptoKeyData_Ed25519_Jwk>,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"sign\"],\n fromSerializedObject<TSerializedCryptoKeyData_Ed25519_Jwk_Transformed>,\n ),\n fromJwk: extractableOrNonExtractable([\"sign\"], fromJwk),\n },\n public: {\n fromBase64: extractableOrNonExtractable([\"verify\"], fromBase64),\n fromFormattedString: extractableOrNonExtractable(\n [\"verify\"],\n fromFormattedString<\n TSerializedCryptoKeyData_Ed25519_Raw | TSerializedCryptoKeyData_Ed25519_Jwk\n >,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"verify\"],\n fromSerializedObject<\n | TSerializedCryptoKeyData_Ed25519_Raw_Transformed\n | TSerializedCryptoKeyData_Ed25519_Jwk_Transformed\n >,\n ),\n fromJwk: extractableOrNonExtractable([\"verify\"], fromJwk),\n },\n};\n","import {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Jwk,\n type TSerializedCryptoKeyData_Ed25519_Jwk_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeEd25519Key_Jwk = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_Ed25519_Jwk> => {\n const keyJwk = await crypto.subtle.exportKey(\"jwk\", key);\n\n const prefixed =\n `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.jwk}::${JSON.stringify(keyJwk)}` as const;\n\n const transformed: TSerializedCryptoKeyData_Ed25519_Jwk_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.ed25519,\n data: keyJwk,\n format: ECryptoKeyFormat.jwk,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\nimport {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_Ed25519_Raw,\n type TSerializedCryptoKeyData_Ed25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeEd25519Key_Raw = async (\n publicKey: CryptoKey,\n): Promise<ISerializedKeyData_Ed25519_Raw> => {\n const publicKeyBuffer = await crypto.subtle.exportKey(\"raw\", publicKey);\n const publicKeyBase64 = base64.encode(new Uint8Array(publicKeyBuffer));\n\n const prefixed =\n `${ECryptoKeyAlgo.ed25519}::${ECryptoKeyFormat.raw_base64}::${publicKeyBase64}` as const;\n\n const transformed: TSerializedCryptoKeyData_Ed25519_Raw_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.ed25519,\n data: publicKeyBase64,\n format: ECryptoKeyFormat.raw_base64,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\n\nexport const verifyWithKeyEd25519 = async ({\n challenge,\n signatureBase64,\n publicKey,\n}: {\n challenge: string;\n signatureBase64: string;\n publicKey: CryptoKey;\n}): Promise<boolean> => {\n const signatureBuffer = Uint8Array.from(base64.decode(signatureBase64));\n const challengeBuffer = new TextEncoder().encode(challenge);\n\n return await crypto.subtle.verify(\n {\n name: \"ED25519\",\n },\n publicKey,\n signatureBuffer,\n challengeBuffer,\n );\n};\n","export const generateX25519KeyPair = async (): Promise<CryptoKeyPair> => {\n const keyPair = (await crypto.subtle.generateKey({ name: \"X25519\" }, true, [\n \"deriveKey\",\n \"deriveBits\",\n ])) as CryptoKeyPair;\n\n return keyPair;\n};\n","import { base64 } from \"@scure/base\";\nimport { convertX25519FormattedStringToSerializedKeyData } from \"../crypto.converters\";\nimport {\n ECryptoKeyFormat,\n type TSerializedCryptoKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n type TSerializedCryptoKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nconst fromBase64 = async (\n dataBase64: string,\n keyUsage: KeyUsage[],\n extractable: boolean,\n): Promise<CryptoKey> => {\n const keyBuffer = Uint8Array.from(base64.decode(dataBase64));\n\n return await crypto.subtle.importKey(\"raw\", keyBuffer, { name: \"X25519\" }, extractable, keyUsage);\n};\n\nconst fromJwk = async (\n jwk: JsonWebKey,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n return await crypto.subtle.importKey(\"jwk\", jwk, { name: \"X25519\" }, extractable, keyUsage);\n};\n\nconst fromSerializedObject = async <\n D extends\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed =\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n>(\n serialized: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n if (serialized.format === ECryptoKeyFormat.jwk) {\n return await fromJwk(serialized.data, keyUsage, extractable);\n }\n\n return await fromBase64(serialized.data, keyUsage, extractable);\n};\n\nconst fromFormattedString = async <\n D extends TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk =\n | TSerializedCryptoKeyData_X25519_Raw\n | TSerializedCryptoKeyData_X25519_Jwk,\n>(\n dataString: D,\n keyUsage: KeyUsage[],\n extractable = true,\n): Promise<CryptoKey> => {\n const transformed = convertX25519FormattedStringToSerializedKeyData(dataString);\n return await fromSerializedObject(transformed, keyUsage, extractable);\n};\n\nconst extractableOrNonExtractable = <I>(\n keyUsage: KeyUsage[],\n func: (input: I, keyUsage: KeyUsage[], extractable: boolean) => Promise<CryptoKey>,\n) =>\n ({\n extractable: (input: I) => func(input, keyUsage, true),\n nonExtractable: (input: I) => func(input, keyUsage, false),\n }) as const;\n\nexport const importX25519Key = {\n private: {\n fromFormattedString: extractableOrNonExtractable(\n [\"deriveKey\", \"deriveBits\"],\n fromFormattedString<TSerializedCryptoKeyData_X25519_Jwk>,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [\"deriveKey\", \"deriveBits\"],\n fromSerializedObject<TSerializedCryptoKeyData_X25519_Jwk_Transformed>,\n ),\n fromJwk: extractableOrNonExtractable([\"deriveKey\", \"deriveBits\"], fromJwk),\n },\n public: {\n fromBase64: extractableOrNonExtractable([], fromBase64),\n fromFormattedString: extractableOrNonExtractable(\n [],\n fromFormattedString<\n TSerializedCryptoKeyData_X25519_Raw | TSerializedCryptoKeyData_X25519_Jwk\n >,\n ),\n fromSerializedObject: extractableOrNonExtractable(\n [],\n fromSerializedObject<\n | TSerializedCryptoKeyData_X25519_Raw_Transformed\n | TSerializedCryptoKeyData_X25519_Jwk_Transformed\n >,\n ),\n fromJwk: extractableOrNonExtractable([], fromJwk),\n },\n};\n","import {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_X25519_Jwk,\n type TSerializedCryptoKeyData_X25519_Jwk_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeX25519Key_Jwk = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_X25519_Jwk> => {\n const publicKeyJwk = await crypto.subtle.exportKey(\"jwk\", key);\n\n const prefixed =\n `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.jwk}::${JSON.stringify(publicKeyJwk)}` as const;\n\n const transformed: TSerializedCryptoKeyData_X25519_Jwk_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.x25519,\n data: publicKeyJwk,\n format: ECryptoKeyFormat.jwk,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\nimport {\n ECryptoKeyAlgo,\n ECryptoKeyFormat,\n type ISerializedKeyData_X25519_Raw,\n type TSerializedCryptoKeyData_X25519_Raw_Transformed,\n} from \"../crypto.schema\";\n\nexport const serializeX25519Key_Raw = async (\n key: CryptoKey,\n): Promise<ISerializedKeyData_X25519_Raw> => {\n const publicKeyBuffer = await crypto.subtle.exportKey(\"raw\", key);\n const publicKeyBase64 = base64.encode(new Uint8Array(publicKeyBuffer));\n\n const prefixed =\n `${ECryptoKeyAlgo.x25519}::${ECryptoKeyFormat.raw_base64}::${publicKeyBase64}` as const;\n\n const transformed: TSerializedCryptoKeyData_X25519_Raw_Transformed = {\n formattedString: prefixed,\n type: ECryptoKeyAlgo.x25519,\n data: publicKeyBase64,\n format: ECryptoKeyFormat.raw_base64,\n };\n\n return { transformed, prefixed };\n};\n","import { base64 } from \"@scure/base\";\r\nimport type { TTypeAndId } from \"../../core/core_valibot_schemas\";\r\nimport type { StorageAdapter } from \"../../storage_adapter/StorageAdapter\";\r\nimport {\r\n createTypedStorage,\r\n type ITypedStorage,\r\n} from \"../../storage_adapter/typed_storage/createTypedStorage\";\r\nimport { createAesGcmKeyFromX25519Keys } from \"../aes_gcm/createAesGcmKeyFromX25519Keys\";\r\nimport { decryptBytesWithAesGcmKey } from \"../aes_gcm/decryptBytesWithAesGcmKey\";\r\nimport { decryptTextDataWithAesGcmKey } from \"../aes_gcm/decryptTextDataWithAesGcmKey\";\r\nimport { encryptBytesWithAesGcmKey } from \"../aes_gcm/encryptBytesWithAesGcmKey\";\r\nimport { encryptTextDataWithAesGcmKey } from \"../aes_gcm/encryptTextDataWithAesGcmKey\";\r\nimport type {\r\n TEncryptedAesGcmBytes,\r\n TEncryptedAesGcmPayload,\r\n TSerializedCryptoKeyData_Ed25519_Raw,\r\n TSerializedCryptoKeyData_X25519_Raw,\r\n TSerializedCryptoKeyPairDataEd25519,\r\n TSerializedCryptoKeyPairDataX25519,\r\n} from \"../crypto.schema\";\r\nimport { generateEd25519KeyPair } from \"../ed25519/generateEd25519KeyPair\";\r\nimport { importEd25519Key } from \"../ed25519/importEd25519Key\";\r\nimport { serializeEd25519Key_Jwk } from \"../ed25519/serializeEd25519Key_Jwk\";\r\nimport { serializeEd25519Key_Raw } from \"../ed25519/serializeEd25519Key_Raw\";\r\nimport { signCombinedTextDataWithKeyEd25519 } from \"../ed25519/signCombinedTextDataWithKeyEd25519\";\r\nimport { signTextDataWithKeyEd25519 } from \"../ed25519/signTextDataWithKeyEd25519\";\r\nimport { verifyWithKeyEd25519 } from \"../ed25519/verifyWithKeyEd25519\";\r\nimport { generateX25519KeyPair } from \"../x25519/generateX25519KeyPair\";\r\nimport { importX25519Key } from \"../x25519/importX25519Key\";\r\nimport { serializeX25519Key_Jwk } from \"../x25519/serializeX25519Key_Jwk\";\r\nimport { serializeX25519Key_Raw } from \"../x25519/serializeX25519Key_Raw\";\r\nimport { buildVerifyKeyBoundInfoString } from \"./buildVerifyKeyBoundInfoString\";\r\n\r\n/**\r\n * How the local identity (the exchange + verify key pairs) is allowed to come into being:\r\n *\r\n * - `\"lazy\"` (default): generate + persist the identity on first use. Correct for frontend / ephemeral\r\n * peers, and safe on a *strongly-consistent* store (a read miss genuinely means \"never written\").\r\n * - `\"required\"`: never auto-mint. `ensureLocal*` throws {@link IdentityNotProvisionedError} if no\r\n * identity was loaded from storage; the only way to mint is the explicit one-shot\r\n * {@link ClientCryptoKeyLink.provisionIdentity}. Use this for a shared backend identity that must\r\n * stay stable across isolates: on an *eventually-consistent* store (e.g. Cloudflare KV) a transient\r\n * read miss must NOT be allowed to silently fork a second identity — that would change the server's\r\n * verify key and get it permanently rejected by every trust-on-first-use-pinned client.\r\n */\r\nexport type TIdentityMode = \"lazy\" | \"required\";\r\n\r\n/**\r\n * Thrown by the local-key getters when the link is in {@link TIdentityMode} `\"required\"` and no\r\n * identity has been provisioned. Surfacing this (instead of silently minting a fresh identity on a\r\n * storage miss) is what keeps a shared backend identity from forking across isolates.\r\n */\r\nexport class IdentityNotProvisionedError extends Error {\r\n constructor(\r\n message = \"ClientCryptoKeyLink: identity not provisioned (identityMode 'required'). Call provisionIdentity() once, out-of-band, before serving.\",\r\n ) {\r\n super(message);\r\n this.name = \"IdentityNotProvisionedError\";\r\n }\r\n}\r\n\r\ninterface IClientCryptoKeyLink_Constructor {\r\n storageAdapter?: StorageAdapter;\r\n /**\r\n * Controls whether the local identity may be minted on first use. Defaults to `\"lazy\"` (unchanged\r\n * behavior). Pass `\"required\"` for a stable shared backend identity — see {@link TIdentityMode}.\r\n */\r\n identityMode?: TIdentityMode;\r\n}\r\n\r\ninterface ITypedStorage_ClientCryptoKeyLink {\r\n localExchangeKeyPair?: TSerializedCryptoKeyPairDataX25519;\r\n localVerifyKeyPair?: TSerializedCryptoKeyPairDataEd25519;\r\n linkedClientPublicKeys: {\r\n [key: TTypeAndId<string>]: {\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n // HKDF inputs for the shared-key derivation. Persisted only via linkClientAndStore — these\r\n // are typically session secrets, so prefer the in-memory linkClient for ephemeral links.\r\n saltString?: string;\r\n infoString?: string;\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n };\r\n };\r\n}\r\n\r\ninterface IExternalClientCryptoKeys {\r\n verify?: {\r\n publicKey: CryptoKey;\r\n publicKeySerialized: TSerializedCryptoKeyData_Ed25519_Raw;\r\n };\r\n exchange?: {\r\n publicKey: CryptoKey;\r\n // Serialized form retained so re-linking can detect a changed key and invalidate the cache.\r\n publicKeySerialized: TSerializedCryptoKeyData_X25519_Raw;\r\n saltString?: string;\r\n infoString?: string;\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n sharedEncryptKey?: CryptoKey;\r\n };\r\n}\r\n\r\ninterface ILinkedClientPublicKeys {\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n}\r\n\r\ninterface ILocalPublicKeys {\r\n verifyPublicKey: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey: TSerializedCryptoKeyData_X25519_Raw;\r\n}\r\n\r\ninterface ILinkClientKeys {\r\n linkedClientId: TTypeAndId;\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n exchangePublicKey?: TSerializedCryptoKeyData_X25519_Raw;\r\n // HKDF salt/info bound into the shared AES-GCM key derivation with this client. Passing either\r\n // (or a new exchange public key) invalidates a previously cached shared key for the link.\r\n saltString?: string;\r\n infoString?: string;\r\n // When true, both sides' verify public keys (local + linked, sorted so both ends agree without\r\n // coordinating an order) are folded into the HKDF info alongside `infoString`. If either relayed\r\n // verify key was tampered with in transit, the two sides derive mismatched keys and the first\r\n // decryption fails — authenticating the keys without extra signatures. Requires the linked\r\n // client's verify key to be set. Both ends of the link must use the same setting.\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n}\r\n\r\ninterface IEncryptDataForLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n dataToEncrypt: string;\r\n}\r\n\r\ninterface IDecryptDataFromLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n dataToDecrypt: TEncryptedAesGcmPayload;\r\n}\r\n\r\ninterface IDecryptAndVerifyDataFromLinkedClient extends IDecryptDataFromLinkedClient {\r\n signatureBase64: string;\r\n}\r\n\r\ninterface IVerifyChallengeFromLinkedClient {\r\n linkedClientId: TTypeAndId;\r\n challenge: string;\r\n signatureBase64: string;\r\n}\r\n\r\nexport class ClientCryptoKeyLink {\r\n private localExchangeKeyPair: CryptoKeyPair | undefined;\r\n private localVerifyKeyPair: CryptoKeyPair | undefined;\r\n private linkedClientKeys = new Map<TTypeAndId, IExternalClientCryptoKeys>();\r\n private storage: ITypedStorage<ITypedStorage_ClientCryptoKeyLink> | undefined;\r\n private readonly identityMode: TIdentityMode;\r\n private initialized = false;\r\n private initializePromise: Promise<void> | undefined;\r\n private localExchangeKeyPairPromise: Promise<CryptoKeyPair> | undefined;\r\n private localVerifyKeyPairPromise: Promise<CryptoKeyPair> | undefined;\r\n\r\n constructor({ storageAdapter, identityMode }: IClientCryptoKeyLink_Constructor = {}) {\r\n if (storageAdapter != null) {\r\n this.storage = createTypedStorage({ storageAdapter });\r\n }\r\n this.identityMode = identityMode ?? \"lazy\";\r\n }\r\n\r\n /**\r\n * Loads the local key pairs and any linked client public keys from storage (when a storage\r\n * adapter was provided), generating and persisting fresh local key pairs if none exist yet.\r\n *\r\n * Must be called (and awaited) before any sign/verify/encrypt/decrypt operation.\r\n */\r\n async initialize(): Promise<void> {\r\n if (this.initialized) {\r\n return;\r\n }\r\n\r\n // Guard against concurrent initialize() calls (e.g. parallel callers on the frontend, where\r\n // there is no blockConcurrencyWhile) generating and persisting duplicate local key pairs.\r\n this.initializePromise ??= this.runInitialize();\r\n\r\n try {\r\n await this.initializePromise;\r\n } finally {\r\n this.initializePromise = undefined;\r\n }\r\n }\r\n\r\n private async runInitialize(): Promise<void> {\r\n await this.loadStoredLocalKeys();\r\n await this.loadLinkedClients();\r\n\r\n this.initialized = true;\r\n }\r\n\r\n /**\r\n * Provision the local identity once: load any persisted identity, then mint + persist the exchange\r\n * and verify key pairs only if absent. Idempotent — a no-op when an identity already exists.\r\n *\r\n * This is the *only* way to mint when {@link TIdentityMode} is `\"required\"`. Run it from a single\r\n * coordinated writer (a deploy hook, a first-boot path, a locked admin route) — **never on the hot\r\n * request path** — because concurrent provisioning over an eventually-consistent store could read\r\n * \"absent\" on two isolates at once and fork divergent identities. The serving path uses `\"required\"`,\r\n * which never mints, so a transient storage miss fails that one request loudly instead of forking.\r\n *\r\n * A genuine storage *read error* propagates here (it is never coerced to \"absent\"), so an outage\r\n * surfaces rather than silently minting a replacement identity.\r\n */\r\n async provisionIdentity(): Promise<void> {\r\n await this.initialize();\r\n await this.mintLocalExchangeKeyPair();\r\n await this.mintLocalVerifyKeyPair();\r\n }\r\n\r\n /**\r\n * Loads the local key pairs from storage if they were previously persisted. Does NOT generate\r\n * fresh keys — local identity is created lazily on first use (see {@link ensureLocalExchangeKeyPair}\r\n * / {@link ensureLocalVerifyKeyPair}), so a verify-only or otherwise key-less consumer never\r\n * generates or stores keys it does not need.\r\n */\r\n private async loadStoredLocalKeys(): Promise<void> {\r\n const storedExchange = await this.storage?.getJson(\"localExchangeKeyPair\");\r\n if (storedExchange != null) {\r\n this.localExchangeKeyPair = {\r\n privateKey: await importX25519Key.private.fromFormattedString.extractable(\r\n storedExchange.privateKey,\r\n ),\r\n publicKey: await importX25519Key.public.fromFormattedString.extractable(\r\n storedExchange.publicKey,\r\n ),\r\n };\r\n }\r\n\r\n const storedVerify = await this.storage?.getJson(\"localVerifyKeyPair\");\r\n if (storedVerify != null) {\r\n this.localVerifyKeyPair = {\r\n privateKey: await importEd25519Key.private.fromFormattedString.extractable(\r\n storedVerify.privateKey,\r\n ),\r\n publicKey: await importEd25519Key.public.fromFormattedString.extractable(\r\n storedVerify.publicKey,\r\n ),\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Returns the local exchange (X25519) key pair. In `\"lazy\"` mode it generates + persists it on first\r\n * use; in `\"required\"` mode it throws {@link IdentityNotProvisionedError} when none was loaded (mint\r\n * only via {@link provisionIdentity}). The read path of every encrypt/derive operation.\r\n */\r\n private async ensureLocalExchangeKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localExchangeKeyPair != null) {\r\n return this.localExchangeKeyPair;\r\n }\r\n if (this.identityMode === \"required\") {\r\n throw new IdentityNotProvisionedError();\r\n }\r\n return this.mintLocalExchangeKeyPair();\r\n }\r\n\r\n /**\r\n * Generates + persists the local exchange key pair if absent, returning an already-loaded pair\r\n * untouched (so provisioning is idempotent). Bypasses the `\"required\"` guard by design — it is the\r\n * sole minting path. Concurrent callers share a single generation.\r\n */\r\n private async mintLocalExchangeKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localExchangeKeyPair != null) {\r\n return this.localExchangeKeyPair;\r\n }\r\n\r\n this.localExchangeKeyPairPromise ??= (async () => {\r\n const keyPair = await generateX25519KeyPair();\r\n this.localExchangeKeyPair = keyPair;\r\n if (this.storage != null) {\r\n await this.storage.setJson(\r\n \"localExchangeKeyPair\",\r\n await this.serializeExchangeKeyPair(keyPair),\r\n );\r\n }\r\n return keyPair;\r\n })();\r\n\r\n try {\r\n return await this.localExchangeKeyPairPromise;\r\n } finally {\r\n this.localExchangeKeyPairPromise = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the local verify (Ed25519) key pair. In `\"lazy\"` mode it generates + persists it on first\r\n * use; in `\"required\"` mode it throws {@link IdentityNotProvisionedError} when none was loaded (mint\r\n * only via {@link provisionIdentity}). The read path of every sign operation.\r\n */\r\n private async ensureLocalVerifyKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localVerifyKeyPair != null) {\r\n return this.localVerifyKeyPair;\r\n }\r\n if (this.identityMode === \"required\") {\r\n throw new IdentityNotProvisionedError();\r\n }\r\n return this.mintLocalVerifyKeyPair();\r\n }\r\n\r\n /**\r\n * Generates + persists the local verify key pair if absent, returning an already-loaded pair\r\n * untouched (so provisioning is idempotent). Bypasses the `\"required\"` guard by design — it is the\r\n * sole minting path. Concurrent callers share a single generation.\r\n */\r\n private async mintLocalVerifyKeyPair(): Promise<CryptoKeyPair> {\r\n if (this.localVerifyKeyPair != null) {\r\n return this.localVerifyKeyPair;\r\n }\r\n\r\n this.localVerifyKeyPairPromise ??= (async () => {\r\n const keyPair = await generateEd25519KeyPair();\r\n this.localVerifyKeyPair = keyPair;\r\n if (this.storage != null) {\r\n await this.storage.setJson(\r\n \"localVerifyKeyPair\",\r\n await this.serializeVerifyKeyPair(keyPair),\r\n );\r\n }\r\n return keyPair;\r\n })();\r\n\r\n try {\r\n return await this.localVerifyKeyPairPromise;\r\n } finally {\r\n this.localVerifyKeyPairPromise = undefined;\r\n }\r\n }\r\n\r\n private async loadLinkedClients(): Promise<void> {\r\n const storedLinkedClients = await this.storage?.getJson(\"linkedClientPublicKeys\");\r\n\r\n if (storedLinkedClients == null) {\r\n return;\r\n }\r\n\r\n for (const [linkedClientId, publicKeys] of Object.entries(storedLinkedClients) as [\r\n TTypeAndId,\r\n ITypedStorage_ClientCryptoKeyLink[\"linkedClientPublicKeys\"][TTypeAndId],\r\n ][]) {\r\n await this.linkClient({\r\n linkedClientId,\r\n verifyPublicKey: publicKeys.verifyPublicKey,\r\n exchangePublicKey: publicKeys.exchangePublicKey,\r\n saltString: publicKeys.saltString,\r\n infoString: publicKeys.infoString,\r\n bindVerifyKeysIntoDerivation: publicKeys.bindVerifyKeysIntoDerivation,\r\n });\r\n }\r\n }\r\n\r\n private async serializeExchangeKeyPair(\r\n keyPair: CryptoKeyPair,\r\n ): Promise<TSerializedCryptoKeyPairDataX25519> {\r\n return {\r\n publicKey: (await serializeX25519Key_Raw(keyPair.publicKey)).prefixed,\r\n privateKey: (await serializeX25519Key_Jwk(keyPair.privateKey)).prefixed,\r\n };\r\n }\r\n\r\n private async serializeVerifyKeyPair(\r\n keyPair: CryptoKeyPair,\r\n ): Promise<TSerializedCryptoKeyPairDataEd25519> {\r\n return {\r\n publicKey: (await serializeEd25519Key_Raw(keyPair.publicKey)).prefixed,\r\n privateKey: (await serializeEd25519Key_Jwk(keyPair.privateKey)).prefixed,\r\n };\r\n }\r\n\r\n /**\r\n * The local public keys that should be shared with a linked client so that it can verify this\r\n * client's signatures and derive a shared encryption key. Generates the local identity on first\r\n * use.\r\n */\r\n async getLocalPublicKeys(): Promise<ILocalPublicKeys> {\r\n return {\r\n verifyPublicKey: await this.getLocalVerifyPublicKey(),\r\n exchangePublicKey: await this.getLocalExchangePublicKey(),\r\n };\r\n }\r\n\r\n /**\r\n * The local exchange (X25519) public key, generating the exchange key pair on first use. Does not\r\n * touch the verify key pair — useful for an exchange-only consumer (e.g. a bridge) that never\r\n * signs.\r\n */\r\n async getLocalExchangePublicKey(): Promise<TSerializedCryptoKeyData_X25519_Raw> {\r\n const exchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n return (await serializeX25519Key_Raw(exchangeKeyPair.publicKey)).prefixed;\r\n }\r\n\r\n /**\r\n * The local verify (Ed25519) public key, generating the verify key pair on first use. Does not\r\n * touch the exchange key pair.\r\n */\r\n async getLocalVerifyPublicKey(): Promise<TSerializedCryptoKeyData_Ed25519_Raw> {\r\n const verifyKeyPair = await this.ensureLocalVerifyKeyPair();\r\n return (await serializeEd25519Key_Raw(verifyKeyPair.publicKey)).prefixed;\r\n }\r\n\r\n /**\r\n * Registers (or updates) the public keys of a linked client in memory only — nothing is written\r\n * to storage. Use this for ephemeral links (e.g. a per-session bridge or end-to-end peer keyed by\r\n * a session salt/info), so the derived shared key never outlives the process.\r\n *\r\n * Re-linking with a new exchange public key, salt, or info invalidates any previously cached\r\n * shared key for the link.\r\n */\r\n async linkClient({\r\n linkedClientId,\r\n verifyPublicKey,\r\n exchangePublicKey,\r\n saltString,\r\n infoString,\r\n bindVerifyKeysIntoDerivation,\r\n }: ILinkClientKeys): Promise<void> {\r\n const existing = this.linkedClientKeys.get(linkedClientId);\r\n\r\n const verify =\r\n verifyPublicKey != null\r\n ? {\r\n publicKey:\r\n await importEd25519Key.public.fromFormattedString.extractable(verifyPublicKey),\r\n publicKeySerialized: verifyPublicKey,\r\n }\r\n : existing?.verify;\r\n\r\n const verifyKeyChanged =\r\n verifyPublicKey != null && verifyPublicKey !== existing?.verify?.publicKeySerialized;\r\n\r\n let exchange = existing?.exchange;\r\n\r\n // `undefined` means \"leave as-is\"; only fields actually passed override the existing link.\r\n const exchangeParamsProvided =\r\n exchangePublicKey != null ||\r\n saltString !== undefined ||\r\n infoString !== undefined ||\r\n bindVerifyKeysIntoDerivation !== undefined;\r\n\r\n if (exchangeParamsProvided) {\r\n const nextPublicKeySerialized = exchangePublicKey ?? existing?.exchange?.publicKeySerialized;\r\n\r\n if (nextPublicKeySerialized == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: Cannot set salt/info for ${linkedClientId} without an exchange public key`,\r\n );\r\n }\r\n\r\n const nextSalt = saltString !== undefined ? saltString : existing?.exchange?.saltString;\r\n const nextInfo = infoString !== undefined ? infoString : existing?.exchange?.infoString;\r\n const nextBind =\r\n bindVerifyKeysIntoDerivation !== undefined\r\n ? bindVerifyKeysIntoDerivation\r\n : existing?.exchange?.bindVerifyKeysIntoDerivation;\r\n\r\n const publicKey =\r\n exchangePublicKey != null\r\n ? await importX25519Key.public.fromFormattedString.extractable(exchangePublicKey)\r\n : // Safe: nextPublicKeySerialized fell back to the existing key, so it exists.\r\n existing!.exchange!.publicKey;\r\n\r\n const unchanged =\r\n nextPublicKeySerialized === existing?.exchange?.publicKeySerialized &&\r\n nextSalt === existing?.exchange?.saltString &&\r\n nextInfo === existing?.exchange?.infoString &&\r\n nextBind === existing?.exchange?.bindVerifyKeysIntoDerivation &&\r\n // With verify keys bound into the derivation, a new verify key changes the derived key.\r\n !(nextBind === true && verifyKeyChanged);\r\n\r\n exchange = {\r\n publicKey,\r\n publicKeySerialized: nextPublicKeySerialized,\r\n saltString: nextSalt,\r\n infoString: nextInfo,\r\n bindVerifyKeysIntoDerivation: nextBind,\r\n // Keep the cached shared key only when no derivation input changed.\r\n sharedEncryptKey: unchanged ? existing?.exchange?.sharedEncryptKey : undefined,\r\n };\r\n } else if (\r\n exchange?.bindVerifyKeysIntoDerivation === true &&\r\n verifyKeyChanged &&\r\n exchange.sharedEncryptKey != null\r\n ) {\r\n // Verify-only re-link, but the verify key participates in this link's derivation.\r\n exchange = { ...exchange, sharedEncryptKey: undefined };\r\n }\r\n\r\n this.linkedClientKeys.set(linkedClientId, { verify, exchange });\r\n }\r\n\r\n /**\r\n * Like {@link linkClient}, but also persists the linked client's public keys (and salt/info) to\r\n * storage so the link survives a reload.\r\n *\r\n * NOTE: salt/info are written in plaintext. When they are session secrets (e.g. a partner secret\r\n * or bridge salt), prefer {@link linkClient} and re-establish the link per session instead.\r\n */\r\n async linkClientAndStore(input: ILinkClientKeys): Promise<void> {\r\n await this.linkClient(input);\r\n\r\n if (this.storage == null) {\r\n return;\r\n }\r\n\r\n const {\r\n linkedClientId,\r\n verifyPublicKey,\r\n exchangePublicKey,\r\n saltString,\r\n infoString,\r\n bindVerifyKeysIntoDerivation,\r\n } = input;\r\n\r\n await this.storage.updateJsonWithDef(\"linkedClientPublicKeys\", {}, (current) => ({\r\n ...current,\r\n [linkedClientId]: {\r\n ...current[linkedClientId],\r\n ...(verifyPublicKey != null ? { verifyPublicKey } : {}),\r\n ...(exchangePublicKey != null ? { exchangePublicKey } : {}),\r\n ...(saltString !== undefined ? { saltString } : {}),\r\n ...(infoString !== undefined ? { infoString } : {}),\r\n ...(bindVerifyKeysIntoDerivation !== undefined ? { bindVerifyKeysIntoDerivation } : {}),\r\n },\r\n }));\r\n }\r\n\r\n /**\r\n * Whether a linked client is currently registered (in memory) under this id.\r\n */\r\n hasLinkedClient(linkedClientId: TTypeAndId): boolean {\r\n return this.linkedClientKeys.has(linkedClientId);\r\n }\r\n\r\n /**\r\n * The serialized public keys registered for a linked client, or undefined when the client is not\r\n * linked. Useful when a holder needs to relay a linked client's keys onward (e.g. a backend\r\n * relaying a wallet's verify key to a partner).\r\n */\r\n getLinkedClientPublicKeys(linkedClientId: TTypeAndId): ILinkedClientPublicKeys | undefined {\r\n const linkedClient = this.linkedClientKeys.get(linkedClientId);\r\n\r\n if (linkedClient == null) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n verifyPublicKey: linkedClient.verify?.publicKeySerialized,\r\n exchangePublicKey: linkedClient.exchange?.publicKeySerialized,\r\n };\r\n }\r\n\r\n /**\r\n * Removes a single linked client from memory and, when storage is available, from persisted\r\n * state. Any cached shared key for the link is dropped with it.\r\n */\r\n async unlinkClient(linkedClientId: TTypeAndId): Promise<void> {\r\n this.linkedClientKeys.delete(linkedClientId);\r\n\r\n if (this.storage != null) {\r\n await this.storage.updateJson(\"linkedClientPublicKeys\", (current) => {\r\n if (current == null) {\r\n return {};\r\n }\r\n\r\n const { [linkedClientId]: _removed, ...rest } = current;\r\n return rest;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Removes all linked clients from memory and persisted state, while keeping the local identity\r\n * key pairs intact.\r\n */\r\n async unlinkAllClients(): Promise<void> {\r\n this.linkedClientKeys.clear();\r\n\r\n if (this.storage != null) {\r\n await this.storage.setJson(\"linkedClientPublicKeys\", {});\r\n }\r\n }\r\n\r\n /**\r\n * Wipes everything this instance owns — local identity key pairs and all linked clients, in\r\n * memory and in storage. After a reset, {@link initialize} must be called again before use (it\r\n * will generate a fresh local identity).\r\n *\r\n * Only the keys owned by this util are removed, so a shared storage adapter's other data is left\r\n * untouched.\r\n */\r\n async reset(): Promise<void> {\r\n this.linkedClientKeys.clear();\r\n this.localExchangeKeyPair = undefined;\r\n this.localVerifyKeyPair = undefined;\r\n this.initialized = false;\r\n\r\n if (this.storage != null) {\r\n await this.storage.removeItem(\"linkedClientPublicKeys\");\r\n await this.storage.removeItem(\"localExchangeKeyPair\");\r\n await this.storage.removeItem(\"localVerifyKeyPair\");\r\n }\r\n }\r\n\r\n private getLinkedClient(linkedClientId: TTypeAndId): IExternalClientCryptoKeys {\r\n const linkedClient = this.linkedClientKeys.get(linkedClientId);\r\n\r\n if (linkedClient == null) {\r\n throw new Error(`ClientCryptoKeyLink: No linked client for ${linkedClientId}`);\r\n }\r\n\r\n return linkedClient;\r\n }\r\n\r\n private async getAesGcmKeyForLinkedClient(\r\n externalClientSourceId: TTypeAndId,\r\n ): Promise<CryptoKey> {\r\n const linkedClient = this.getLinkedClient(externalClientSourceId);\r\n\r\n if (linkedClient.exchange?.sharedEncryptKey != null) {\r\n return linkedClient.exchange.sharedEncryptKey;\r\n }\r\n\r\n if (linkedClient.exchange?.publicKey == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: No public exchange key set for ${externalClientSourceId}`,\r\n );\r\n }\r\n\r\n const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n\r\n let infoString = linkedClient.exchange.infoString;\r\n\r\n if (linkedClient.exchange.bindVerifyKeysIntoDerivation === true) {\r\n const linkedVerifyPublicKey = linkedClient.verify?.publicKeySerialized;\r\n\r\n if (linkedVerifyPublicKey == null) {\r\n throw new Error(\r\n `ClientCryptoKeyLink: Link for ${externalClientSourceId} binds verify keys into the derivation, but no verify public key is set`,\r\n );\r\n }\r\n\r\n infoString = buildVerifyKeyBoundInfoString({\r\n infoString: linkedClient.exchange.infoString,\r\n verifyPublicKeys: [await this.getLocalVerifyPublicKey(), linkedVerifyPublicKey],\r\n });\r\n }\r\n\r\n const sharedEncryptKey = await createAesGcmKeyFromX25519Keys({\r\n internalX25519PrivateKey: localExchangeKeyPair.privateKey,\r\n externalX25519PublicKey: linkedClient.exchange.publicKey,\r\n saltString: linkedClient.exchange.saltString,\r\n infoString,\r\n });\r\n\r\n this.linkedClientKeys.set(externalClientSourceId, {\r\n ...linkedClient,\r\n exchange: {\r\n ...linkedClient.exchange,\r\n sharedEncryptKey,\r\n },\r\n });\r\n\r\n return sharedEncryptKey;\r\n }\r\n\r\n /**\r\n * Derive the shared AES-GCM key from *explicit* key material + this link's local exchange private\r\n * key, returning a standalone key that is **not** stored in (or read from) the per-`linkedClientId`\r\n * cache. Use it to give a single session its own immutable key: two sessions that share one\r\n * `linkedClientId` (e.g. a secure WebSocket and a secure HTTP exchange to the same peer) would\r\n * otherwise clobber each other's cached shared key — the second handshake's re-link drops the\r\n * first's key, so frames on the other transport fail to decrypt. Mirrors the derivation in\r\n * {@link getAesGcmKeyForLinkedClient} exactly, so the resulting key matches the peer's.\r\n *\r\n * Requires the local identity to be loaded — call {@link initialize} first when resuming a link\r\n * cold (the handshake paths have already initialized by the time they hold key material).\r\n */\r\n async deriveSharedAesGcmKey({\r\n exchangePublicKey,\r\n saltString,\r\n infoString,\r\n bindVerifyKeysIntoDerivation,\r\n verifyPublicKey,\r\n }: {\r\n exchangePublicKey: TSerializedCryptoKeyData_X25519_Raw;\r\n saltString?: string;\r\n infoString?: string;\r\n bindVerifyKeysIntoDerivation?: boolean;\r\n /** The peer's verify public key — required when `bindVerifyKeysIntoDerivation` is true. */\r\n verifyPublicKey?: TSerializedCryptoKeyData_Ed25519_Raw;\r\n }): Promise<CryptoKey> {\r\n const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n const externalX25519PublicKey =\r\n await importX25519Key.public.fromFormattedString.extractable(exchangePublicKey);\r\n\r\n let derivedInfoString = infoString;\r\n if (bindVerifyKeysIntoDerivation === true) {\r\n if (verifyPublicKey == null) {\r\n throw new Error(\r\n \"ClientCryptoKeyLink.deriveSharedAesGcmKey: a verify public key is required when binding verify keys into the derivation\",\r\n );\r\n }\r\n derivedInfoString = buildVerifyKeyBoundInfoString({\r\n infoString,\r\n verifyPublicKeys: [await this.getLocalVerifyPublicKey(), verifyPublicKey],\r\n });\r\n }\r\n\r\n return await createAesGcmKeyFromX25519Keys({\r\n internalX25519PrivateKey: localExchangeKeyPair.privateKey,\r\n externalX25519PublicKey,\r\n saltString,\r\n infoString: derivedInfoString,\r\n });\r\n }\r\n\r\n /**\r\n * Derive a symmetric AES-GCM key bound to **this link's own identity** — for sealing data the server\r\n * hands a client and reads back later (e.g. a stateless secure-exchange session ticket), where only\r\n * this server (any isolate that loaded the same persisted identity) can open it.\r\n *\r\n * Deterministic: an X25519 ECDH of the local exchange private key against its own public key, fed\r\n * through the same vetted HKDF as peer key derivation, with a fixed versioned info label. So every\r\n * isolate sharing the persisted identity derives the identical key, and no raw private-key bytes are\r\n * exposed. The {@link version} is part of the label, so a future rotation can run two keys during a\r\n * grace window (old tickets opened with `v1` while new ones issue under `v2`).\r\n *\r\n * Requires the local identity (call {@link initialize} / {@link provisionIdentity} first); in\r\n * `\"required\"` mode an unprovisioned link throws {@link IdentityNotProvisionedError}.\r\n */\r\n async deriveLocalSealKey(options?: { version?: string }): Promise<CryptoKey> {\r\n const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();\r\n return await createAesGcmKeyFromX25519Keys({\r\n internalX25519PrivateKey: localExchangeKeyPair.privateKey,\r\n externalX25519PublicKey: localExchangeKeyPair.publicKey,\r\n infoString: `exchange-ticket-seal/${options?.version ?? \"v1\"}`,\r\n });\r\n }\r\n\r\n async encryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: IEncryptDataForLinkedClient): Promise<TEncryptedAesGcmPayload> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await encryptTextDataWithAesGcmKey({\r\n dataToEncrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n async decryptDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n }: IDecryptDataFromLinkedClient): Promise<string> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await decryptTextDataWithAesGcmKey({\r\n dataToDecrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n /**\r\n * Bytes counterpart of {@link encryptDataForLinkedClient} — encrypts raw bytes with the shared\r\n * AES-GCM key, returning a binary nonce + ciphertext. Use it for binary channels (e.g. msgpack\r\n * WebSocket frames) to avoid base64 inflation.\r\n */\r\n async encryptBytesForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: {\r\n dataToEncrypt: Uint8Array;\r\n linkedClientId: TTypeAndId;\r\n }): Promise<TEncryptedAesGcmBytes> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await encryptBytesWithAesGcmKey({\r\n dataToEncrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n /** Bytes counterpart of {@link decryptDataFromLinkedClient}. */\r\n async decryptBytesFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n }: {\r\n dataToDecrypt: TEncryptedAesGcmBytes;\r\n linkedClientId: TTypeAndId;\r\n }): Promise<Uint8Array> {\r\n const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);\r\n\r\n return await decryptBytesWithAesGcmKey({\r\n dataToDecrypt,\r\n aesGcmKey: key,\r\n });\r\n }\r\n\r\n async signAndEncryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n }: IEncryptDataForLinkedClient): Promise<{\r\n encryptedData: TEncryptedAesGcmPayload;\r\n signatureBase64: string;\r\n }> {\r\n const { signatureBase64 } = await this.signChallenge([dataToEncrypt]);\r\n const encryptedData = await this.encryptDataForLinkedClient({\r\n dataToEncrypt,\r\n linkedClientId,\r\n });\r\n\r\n return {\r\n encryptedData,\r\n signatureBase64,\r\n };\r\n }\r\n\r\n /**\r\n * Decrypts a payload from a linked client and verifies that the decrypted plaintext was signed\r\n * by that client. Counterpart to {@link signAndEncryptDataForLinkedClient}.\r\n *\r\n * Returns the decrypted `data` alongside `isValid` — the caller decides how to handle an invalid\r\n * signature. (A tampered ciphertext fails earlier at AES-GCM decryption.)\r\n */\r\n async decryptAndVerifyDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n signatureBase64,\r\n }: IDecryptAndVerifyDataFromLinkedClient): Promise<{ data: string; isValid: boolean }> {\r\n const data = await this.decryptDataFromLinkedClient({\r\n dataToDecrypt,\r\n linkedClientId,\r\n });\r\n\r\n const isValid = await this.verifyChallengeFromLinkedClient({\r\n linkedClientId,\r\n challenge: data,\r\n signatureBase64,\r\n });\r\n\r\n return { data, isValid };\r\n }\r\n\r\n async signChallenge(challenge: [string, ...string[]]): Promise<{\r\n signatureBase64: string;\r\n }> {\r\n if (challenge.length === 0) {\r\n throw new Error(\"Challenge must contain at least one string\");\r\n }\r\n\r\n const localVerifyKeyPair = await this.ensureLocalVerifyKeyPair();\r\n\r\n const signature =\r\n challenge.length > 1\r\n ? await signCombinedTextDataWithKeyEd25519(challenge, localVerifyKeyPair.privateKey)\r\n : await signTextDataWithKeyEd25519(challenge[0], localVerifyKeyPair.privateKey);\r\n\r\n return {\r\n signatureBase64: base64.encode(signature),\r\n };\r\n }\r\n\r\n /**\r\n * Verifies a signature over `challenge` against the linked client's verify (Ed25519) public key.\r\n */\r\n async verifyChallengeFromLinkedClient({\r\n linkedClientId,\r\n challenge,\r\n signatureBase64,\r\n }: IVerifyChallengeFromLinkedClient): Promise<boolean> {\r\n const linkedClient = this.getLinkedClient(linkedClientId);\r\n\r\n if (linkedClient.verify?.publicKey == null) {\r\n throw new Error(`ClientCryptoKeyLink: No verify public key set for ${linkedClientId}`);\r\n }\r\n\r\n return await verifyWithKeyEd25519({\r\n challenge,\r\n signatureBase64,\r\n publicKey: linkedClient.verify.publicKey,\r\n });\r\n }\r\n}\r\n","// import type { StringKeys } from \"../typescript/special_typescript_types\";\n\nexport enum EStorageAdapterType {\n string = \"string\",\n json = \"json\",\n}\n\nexport interface IStorageAdapterMethods_String {\n type: EStorageAdapterType.string;\n setItem: (key: string, value: string) => Promise<void>;\n getItem: (key: string) => Promise<string | null | undefined>;\n removeItem: (key: string) => Promise<void>;\n}\n\nexport interface IStorageAdapterMethods_Json {\n type: EStorageAdapterType.json;\n setItem: <T>(key: string, value: T) => Promise<void>;\n getItem: <T>(key: string) => Promise<T | null | undefined>;\n removeItem: (key: string) => Promise<void>;\n}\n\nexport type TStorageAdapterMethods = IStorageAdapterMethods_String | IStorageAdapterMethods_Json;\n\nexport interface IStorageKeyGetterAndSetter<T> {\n get: () => Promise<T | undefined>;\n set: (value: T) => Promise<void>;\n}\n\n// export interface IStorageAdapter {}\n","import {\n EStorageAdapterType,\n type IStorageKeyGetterAndSetter,\n type TStorageAdapterMethods,\n} from \"./storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"./typed_storage/createTypedStorage\";\n\nexport interface IStorageAdapterConstructor {\n methods: TStorageAdapterMethods;\n trackKeysForClearing?: boolean;\n keyPrefix?: string;\n}\n\ninterface IStorageAdapterTypedStorage {\n __usedKeys__: string[];\n}\n\nexport class StorageAdapter {\n private implementation: TStorageAdapterMethods;\n readonly keyPrefix: string;\n private readonly adapterStorage?: ITypedStorage<IStorageAdapterTypedStorage>;\n\n constructor({ methods, keyPrefix, trackKeysForClearing: trackKeys }: IStorageAdapterConstructor) {\n this.implementation = methods;\n this.keyPrefix = keyPrefix ?? \"\";\n const _trackKeys = trackKeys ?? true;\n // Only create keyStorage when tracking is enabled; the inner adapter has trackKeys:false so\n // its constructor skips this branch, breaking the infinite-recursion cycle.\n this.adapterStorage = _trackKeys\n ? createTypedStorage({\n storageAdapter: new StorageAdapter({ methods, keyPrefix, trackKeysForClearing: false }),\n })\n : undefined;\n }\n\n private getPrefixedKey(rawKey: string): string {\n return `${this.keyPrefix}${rawKey}`;\n }\n\n /**\n * Derive a new adapter over the *same* backing store with an extra key-prefix segment appended.\n * Lets an independent namespace (e.g. a second crypto identity) share one underlying storage without\n * key collisions; the derived adapter tracks its own keys for `clearAll`, scoped to the new prefix.\n */\n withKeyPrefix(extraPrefix: string): StorageAdapter {\n return new StorageAdapter({\n methods: this.implementation,\n keyPrefix: `${this.keyPrefix}${extraPrefix}`,\n });\n }\n\n private async trackUsedKey(rawKey: string): Promise<void> {\n if (!this.adapterStorage) return;\n await this.adapterStorage.updateJsonWithDef(\"__usedKeys__\", [], (currentKeys) => {\n if (!currentKeys.includes(rawKey)) {\n return [...currentKeys, rawKey];\n }\n return currentKeys;\n });\n }\n\n private async untrackUsedKey(rawKey: string): Promise<void> {\n if (!this.adapterStorage) return;\n await this.adapterStorage.updateJsonWithDef(\"__usedKeys__\", [], (currentKeys) => {\n return currentKeys.filter((k) => k !== rawKey);\n });\n }\n\n async clearAll(): Promise<void> {\n if (!this.adapterStorage) return;\n const allKeys = (await this.adapterStorage.getJsonOrDef(\"__usedKeys__\", [])) ?? [];\n\n await Promise.all(\n allKeys.map(async (key) => {\n await this.removeItem(key);\n }),\n );\n\n await this.adapterStorage.setJson(\"__usedKeys__\", []);\n }\n\n async removeItem(rawKey: string): Promise<void> {\n await this.implementation.removeItem(this.getPrefixedKey(rawKey));\n await this.untrackUsedKey(rawKey);\n }\n\n async setJson(rawKey: string, value: any) {\n const key = this.getPrefixedKey(rawKey);\n\n if (this.implementation.type === EStorageAdapterType.string) {\n await this.implementation.setItem(key, JSON.stringify(value));\n } else {\n await this.implementation.setItem(key, value);\n }\n\n await this.trackUsedKey(rawKey);\n }\n\n async getJson<T>(rawKey: string): Promise<T | undefined> {\n const key = this.getPrefixedKey(rawKey);\n\n if (this.implementation.type === EStorageAdapterType.string) {\n const val = await this.implementation.getItem(key);\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return undefined;\n }\n\n return JSON.parse(val);\n } else {\n const val = await this.implementation.getItem<T>(key);\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return undefined;\n }\n\n return val;\n }\n }\n\n async getJsonOrDef<T>(rawKey: string, defVal: T): Promise<T> {\n if (this.implementation.type === EStorageAdapterType.string) {\n const val = await this.implementation.getItem(this.getPrefixedKey(rawKey));\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return defVal;\n }\n\n return JSON.parse(val);\n }\n\n const val = await this.implementation.getItem<T>(this.getPrefixedKey(rawKey));\n\n if (val == null || val === \"undefined\" || val === \"null\") {\n return defVal;\n }\n\n return val;\n }\n\n async updateJson<T>(rawKey: string, updater: (currentVal: T | undefined) => T): Promise<T> {\n const currentVal = await this.getJson<T>(rawKey);\n const newVal = updater(currentVal);\n await this.setJson(rawKey, newVal);\n return newVal;\n }\n\n async updateJsonOrDef<T>(rawKey: string, defVal: T, updater: (currentVal: T) => T): Promise<T> {\n const currentVal = await this.getJsonOrDef<T>(rawKey, defVal);\n const newVal = updater(currentVal);\n await this.setJson(rawKey, newVal);\n return newVal;\n }\n\n createJsonGetterSetter<T>(rawKey: string): IStorageKeyGetterAndSetter<T> {\n return {\n get: () => this.getJson(rawKey),\n set: (value: T) => this.setJson(rawKey, value),\n };\n }\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_String,\n} from \"../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../typed_storage/createTypedStorage\";\n\n/**\n *\n * Web Storage [LOCAL STORAGE]\n *\n */\n\ntype TCreateWebLocalStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n localStorage: typeof localStorage;\n};\n\nexport function createWebLocalStorageMethods(\n _localStorage: typeof localStorage,\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => _localStorage.getItem(key),\n setItem: async (key, value) => {\n _localStorage.setItem(key, value);\n },\n removeItem: async (key) => {\n _localStorage.removeItem(key);\n },\n };\n}\n\nexport const createWebLocalStorageAdapter = ({\n localStorage: _localStorage,\n ...options\n}: TCreateWebLocalStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createWebLocalStorageMethods(_localStorage),\n ...options,\n });\n};\n\nexport function createTypedWebLocalStorage<T extends Record<string, any>>(\n options: TCreateWebLocalStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createWebLocalStorageAdapter(options),\n });\n}\n\n/**\n *\n * Web Storage [SESSION STORAGE]\n *\n */\n\ntype TCreateWebSessionStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n sessionStorage: typeof sessionStorage;\n};\n\nexport function createWebSessionStorageMethods(\n _sessionStorage: typeof sessionStorage,\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => _sessionStorage.getItem(key),\n setItem: async (key, value) => {\n _sessionStorage.setItem(key, value);\n },\n removeItem: async (key) => {\n _sessionStorage.removeItem(key);\n },\n };\n}\n\nexport const createWebSessionStorageAdapter = ({\n sessionStorage: _sessionStorage,\n ...options\n}: TCreateWebSessionStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createWebSessionStorageMethods(_sessionStorage),\n ...options,\n });\n};\n\nexport function createTypedWebSessionStorage<T extends Record<string, any>>(\n options: TCreateWebSessionStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createWebSessionStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_Json,\n} from \"../../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../../typed_storage/createTypedStorage\";\nimport type { IDurableObjectStorage } from \"./durable_object_storage.types\";\n\nexport function createDurableObjectStorageMethods(\n durableObjectStorage: IDurableObjectStorage,\n): IStorageAdapterMethods_Json {\n return {\n type: EStorageAdapterType.json,\n getItem: (key) => durableObjectStorage.get(key),\n setItem: (key, value) => durableObjectStorage.put(key, value),\n removeItem: async (key) => {\n await durableObjectStorage.delete(key);\n },\n };\n}\n\nexport type TCreateDurableObjectStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> & {\n durableObjectStorage: IDurableObjectStorage;\n};\n\n/**\n * Wraps a Durable Object's storage in the generic StorageAdapter interface, e.g. for handing to a\n * ClientCryptoKeyLink so it can persist its keys inside the DO's own storage.\n */\nexport const createDurableObjectStorageAdapter = ({\n durableObjectStorage,\n ...options\n}: TCreateDurableObjectStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createDurableObjectStorageMethods(durableObjectStorage),\n ...options,\n });\n};\n\nexport function createDurableObjectTypedStorage<T extends Record<string, any>>(\n options: TCreateDurableObjectStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createDurableObjectStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_String,\n} from \"../../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../../typed_storage/createTypedStorage\";\nimport type { IKVNamespace, IKVNamespacePutOptions } from \"./kv_storage.types\";\n\nexport interface ICreateKVStorageMethodsOptions {\n /** The `KVNamespace` binding, e.g. accessed off `env.MY_KV` inside a worker. */\n kvNamespace: IKVNamespace;\n /** Default options applied to every `put`, e.g. `{ expirationTtl }` for TTL-based eviction. */\n defaultPutOptions?: IKVNamespacePutOptions;\n}\n\nexport function createKVStorageMethods({\n kvNamespace,\n defaultPutOptions,\n}: ICreateKVStorageMethodsOptions): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: (key) => kvNamespace.get(key),\n setItem: (key, value) => kvNamespace.put(key, value, defaultPutOptions),\n removeItem: (key) => kvNamespace.delete(key),\n };\n}\n\nexport type TCreateKVStorageOptions = Omit<IStorageAdapterConstructor, \"methods\"> &\n ICreateKVStorageMethodsOptions;\n\n/**\n * Wraps a Cloudflare KV namespace binding in the generic StorageAdapter interface, e.g. for handing\n * to a ClientCryptoKeyLink so it can persist its keys inside KV.\n */\nexport const createKVStorageAdapter = ({\n kvNamespace,\n defaultPutOptions,\n ...options\n}: TCreateKVStorageOptions): StorageAdapter => {\n return new StorageAdapter({\n methods: createKVStorageMethods({ kvNamespace, defaultPutOptions }),\n ...options,\n });\n};\n\nexport function createKVTypedStorage<T extends Record<string, any>>(\n options: TCreateKVStorageOptions,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createKVStorageAdapter(options),\n });\n}\n","import { type IStorageAdapterConstructor, StorageAdapter } from \"../../StorageAdapter\";\nimport {\n EStorageAdapterType,\n type IStorageAdapterMethods_Json,\n type IStorageAdapterMethods_String,\n} from \"../../storage_adapter.types\";\nimport { createTypedStorage, type ITypedStorage } from \"../../typed_storage/createTypedStorage\";\n\nexport type TMemoryStorage_string = Map<string, string>;\nexport type TMemoryStorage_json = Map<string, any>;\n\n/**\n *\n * Memory Storage [STRING]\n *\n */\n\ntype TCreateMemoryStorageOptions_string = Omit<IStorageAdapterConstructor, \"methods\"> & {\n memoryStorageMap?: TMemoryStorage_string;\n};\n\nexport function createMemoryStorageMethods_string(\n memoryStorageMap: TMemoryStorage_string = new Map(),\n): IStorageAdapterMethods_String {\n return {\n type: EStorageAdapterType.string,\n getItem: async (key) => memoryStorageMap.get(key) ?? null,\n setItem: async (key, value) => {\n memoryStorageMap.set(key, value);\n },\n removeItem: async (key) => {\n memoryStorageMap.delete(key);\n },\n };\n}\n\nexport const createMemoryStorageAdapter_string = (\n options?: TCreateMemoryStorageOptions_string,\n): StorageAdapter => {\n return new StorageAdapter({\n methods: createMemoryStorageMethods_string(options?.memoryStorageMap),\n ...options,\n });\n};\n\nexport function createTypedMemoryStorage_string<T extends Record<string, any>>(\n options?: TCreateMemoryStorageOptions_string,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createMemoryStorageAdapter_string(options),\n });\n}\n\n/**\n *\n * Memory Storage [JSON]\n *\n */\n\ntype TCreateMemoryStorageOptions_json = Omit<IStorageAdapterConstructor, \"methods\"> & {\n memoryStorageMap?: TMemoryStorage_json;\n};\n\nexport function createMemoryStorageMethods_json(\n memoryStorageMap: TMemoryStorage_json = new Map(),\n): IStorageAdapterMethods_Json {\n return {\n type: EStorageAdapterType.json,\n getItem: async (key) => memoryStorageMap.get(key),\n setItem: async (key, value) => {\n memoryStorageMap.set(key, value);\n },\n removeItem: async (key) => {\n memoryStorageMap.delete(key);\n },\n };\n}\n\nexport const createMemoryStorageAdapter_json = (\n options?: TCreateMemoryStorageOptions_json,\n): StorageAdapter => {\n return new StorageAdapter({\n methods: createMemoryStorageMethods_json(options?.memoryStorageMap),\n ...options,\n });\n};\n\nexport function createTypedMemoryStorage_json<T extends Record<string, any>>(\n options?: TCreateMemoryStorageOptions_json,\n): ITypedStorage<T> {\n return createTypedStorage<T>({\n storageAdapter: createMemoryStorageAdapter_json(options),\n });\n}\n"],"mappings":";;;AAAA,MAAa,gBAAgB,QAAkD;CAC7E,OAAO,OAAO,QAAQ,IAAI,SAAS;AACrC;;;ACFA,MAAa,6BAA6B,OAAO,EAC/C,YACA,gBAIyB;CACzB,OAAO,IAAI,WACT,MAAM,OAAO,OAAO,WAAW;EAAE,MAAM;EAAU,QAAQ;CAAU,GAAG,YAAY,GAAG,CACvF;AACF;;;ACPA,MAAM,sBAAsB;AAE5B,MAAa,gCAAgC,OAAO,EAClD,yBACA,0BACA,YACA,iBAMwB;CACxB,MAAM,aAAa,MAAM,2BAA2B;EAClD,YAAY;EACZ,WAAW;CACb,CAAC;CAGD,MAAM,MAAM,MAAM,OAAO,OAAO,UAAU,OAAO,IAAI,WAAW,UAAU,GAAG,QAAQ,OAAO,CAC1F,WACF,CAAC;CAED,MAAM,OAAO,aAAa,UAAU,IAAI,IAAI,YAAY,CAAC,CAAC,OAAO,UAAU,IAAI,IAAI,WAAW;CAC9F,MAAM,OAAO,IAAI,YAAY,CAAC,CAAC,OAC7B,aAAa,UAAU,IAAI,aAAa,mBAC1C;CAGA,OAAO,MAAM,OAAO,OAAO,UACzB;EACE,MAAM;EACN,MAAM;EACN;EACA;CACF,GACA,KACA;EAAE,MAAM;EAAW,QAAQ;CAAI,GAC/B,OACA,CAAC,WAAW,SAAS,CACvB;AACF;;;;;;;ACtCA,MAAa,4BAA4B,OAAO,EAC9C,WACA,oBAIyB;CACzB,MAAM,gBAAgB,MAAM,OAAO,OAAO,QAGxC;EAAE,MAAM;EAAW,IAAI,IAAI,WAAW,cAAc,KAAK;CAAE,GAC3D,WACA,IAAI,WAAW,cAAc,UAAU,CACzC;CAEA,OAAO,IAAI,WAAW,aAAa;AACrC;;;ACnBA,MAAa,+BAA+B,OAAO,EACjD,WACA,oBAIqB;CACrB,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EACE,MAAM;EACN,IAAI,IAAI,WAAW,OAAO,OAAO,cAAc,KAAK,CAAC;CACvD,GACA,WACA,IAAI,WAAW,OAAO,OAAO,cAAc,UAAU,CAAC,CACxD;CAEA,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,aAAa;AAC/C;;;;;;;;ACbA,MAAa,4BAA4B,OAAO,EAC9C,WACA,oBAIoC;CACpC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;CAEvD,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EAAE,MAAM;EAAW,IAAI;CAAM,GAC7B,WAGA,IAAI,WAAW,aAAa,CAC9B;CAEA,OAAO;EAAE;EAAO,YAAY,IAAI,WAAW,aAAa;CAAE;AAC5D;;;ACtBA,MAAa,+BAA+B,OAAO,EACjD,WACA,oBAIsC;CACtC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;CAEvD,MAAM,gBAAgB,MAAM,OAAO,OAAO,QACxC;EACE,MAAM;EACN,IAAI;CACN,GACA,WACA,IAAI,YAAY,CAAC,CAAC,OAAO,aAAa,CACxC;CAEA,OAAO;EACL,OAAO,OAAO,OAAO,KAAK;EAC1B,YAAY,OAAO,OAAO,IAAI,WAAW,aAAa,CAAC;CACzD;AACF;;;ACzBA,MAAa,6BAA6B,OACxC,MACA,cACwB;CACxB,MAAM,aAAa,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI;CAChD,MAAM,YAAY,MAAM,OAAO,OAAO,KACpC,EACE,MAAM,UACR,GACA,WACA,UACF;CAEA,OAAO,IAAI,WAAW,SAAS;AACjC;;;ACZA,MAAa,uCAAuC;AAEpD,MAAa,qCAAqC,OAChD,MACA,WACA,YAAA,SACwB;CACxB,OAAO,MAAM,2BAA2B,KAAK,KAAK,SAAS,GAAG,SAAS;AACzE;;;;;;;;;;;;;;;;ACWA,MAAa,iCAAiC,EAC5C,YACA,uBACkD;CAClD,MAAM,aAAa,CAAC,GAAG,gBAAgB,CAAC,CAAC,KAAK;CAE9C,OAAO,CAAC,GAAI,cAAc,OAAO,CAAC,UAAU,IAAI,CAAC,GAAI,GAAG,UAAU,CAAC,CAAC,KAAA,IAEpE;AACF;;;ACNA,SAAgB,mBAAkD,EAChE,kBAC+C;CAC/C,MAAM,UAAU,OAAgC,QAAsC;EACpF,OAAO,eAAe,QAAc,GAAG;CACzC;CAEA,MAAM,eAAe,OAAgC,KAAQ,WAAgC;EAC3F,OAAQ,MAAM,eAAe,QAAc,GAAG,KAAM;CACtD;CAEA,MAAM,UAAU,OAAgC,KAAQ,QAA6B;EACnF,OAAO,eAAe,QAAQ,KAAK,GAAG;CACxC;CAEA,MAAM,aAAa,OAAgC,QAA0B;EAC3E,MAAM,eAAe,WAAW,GAAG;CACrC;CAEA,MAAM,aAAa,OACjB,KACA,YACkB;EAClB,MAAM,eAAe,WAAW,KAAK,OAAO;CAC9C;CAEA,MAAM,oBAAoB,OACxB,KACA,YACA,YACkB;EAClB,MAAM,eAAe,gBAAgB,KAAK,YAAY,OAAO;CAC/D;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,YAAY;GACpB,MAAM,eAAe,SAAS;EAChC;CACF;AACF;;;ACrEA,MAAa,yBAAyB,YAAoC;CAMxE,OAAO,MALgB,OAAO,OAAO,YAAY,EAAE,MAAM,UAAU,GAAG,MAAM,CAC1E,QACA,QACF,CAAC;AAGH;;;ACAA,MAAa,4CACgD,EACzD,0BAA0B,CAAC,GAC3B,gBAAgB,UAC6B,CAAC,OAE9C,oBAC8E;CAC9E,MAAM,CAAC,MAAM,QAAQ,cAAc,gBAAgB,MAAM,IAAI;CAK7D,IAAI,aAAgB;CAEpB,IAAI,iBAAiB,wBAAwB,SAAS,MAAM,GAC1D,IAAI;EACF,aAAa,KAAK,MAAM,UAAU;CACpC,SAAS,OAAO;EACd,MAAM,sBAAM,IAAI,MACd,8DAA8D,gBAAgB,wDAAwD,KAAK,IAAI,OAAO,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACvN;EAEA,IAAI,QAAQ;EACZ,MAAM;CACR;CAGF,OAAO;EACL,iBAAiB;EACX;EACE;EACR,MAAM;CACR;AACF;;;ACtCF,MAAa,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AA4BpD,MAAa,iDAAqF,EAChG,MACA,QACA,UACA,iBAE+C;CAC/C,MAAM,YAAY,YAAY;CAC9B,MAAM,cAAc,cAAc;CAElC,OAAO,EAAE,KACP,EAAE,QAAiC,UAAU;EAC3C,IAAI,OAAO,UAAU,UAAU,OAAO;EAEtC,MAAM,CAAC,UAAU,YAAY,YAAY,MAAM,MAAM,IAAI;EAEzD,OAAO,aAAa,QAAQ,eAAe,UAAU,OAAO,aAAa;CAC3E,GAAG,8BAA8B,UAAU,MAAM,YAAY,qBAAqB,UAAU,QAAQ,KAAK,MAAM,YAAY,QAAQ,OAAO,mDAAmD,CAC/L;AACF;;;AC5CA,IAAY,iBAAL,yBAAA,gBAAA;CACL,eAAA,aAAA;CACA,eAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,mBAAL,yBAAA,kBAAA;CACL,iBAAA,gBAAA;CACA,iBAAA,SAAA;;AACF,EAAA,CAAA,CAAA;AAEA,MAAa,sCAAsC,8CAGjD;CACA,QAAA;CACA,MAAA;CACA,UAAU;AACZ,CAAC;AAED,MAAa,sCAAsC,8CAGjD;CACA,QAAA;CACA,MAAA;CACA,UAAU;CACV,eAAe;AACjB,CAAC;AAwBD,MAAa,qCAAqC,8CAGhD;CACA,QAAA;CACA,MAAA;CACA,UAAU;AACZ,CAAC;AAED,MAAa,qCAAqC,8CAGhD;CACA,QAAA;CACA,MAAA;CACA,UAAU;CACV,eAAe;AACjB,CAAC;AAED,MAAa,2BAA2B,EAAE,OAAO;CAC/C,WAAW;CACX,YAAY;AACd,CAAC;AAID,MAAa,4BAA4B,EAAE,OAAO;CAChD,WAAW;CACX,YAAY;AACd,CAAC;AA0BD,MAAa,sCAAsC,EAAE,OAAO;CAC1D,WAAW,EAAE,OAAO;CACpB,iBAAiB;AACnB,CAAC;AAED,MAAa,gDAAgD,EAAE,UAAU,CACvE,qCACA,EAAE,OAAO,EACP,gBAAgB,EAAE,SAAS,EAAE,QAAQ,CAAC,EACxC,CAAC,CACH,CAAC;AAUD,MAAa,0BAA0B,EAAE,OAAO;CAC9C,OAAO;CACP,YAAY;AACd,CAAC;;;;;;;;AC/GD,MAAa,sCAAsC,yCAGjD;AAEF,MAAa,sCAAsC,yCAIjD,EAAE,eAAe,KAAK,CAAC;AAEzB,MAAa,wCAAwC,yCAGnD,EACA,yBAAyB,CAAA,KAAqB,EAChD,CAAC;AAED,MAAa,kDACX,UACmC;CAGnC,OAAO;EACL,UAAU;EACV,aAJkB,oCAAoC,KAI5C;CACZ;AACF;AAEA,MAAa,kDACX,UACmC;CAGnC,OAAO;EACL,UAAU;EACV,aAJkB,oCAAoC,KAI5C;CACZ;AACF;AAEA,MAAa,oDAMX,UACM;CACN,OAAO,sCAAsC,KAAK;AACpD;;;;;;AAQA,MAAa,qCAAqC,yCAGhD;AAEF,MAAa,qCAAqC,yCAIhD,EAAE,eAAe,KAAK,CAAC;AAEzB,MAAa,uCAAuC,yCAGlD,EACA,yBAAyB,CAAA,KAAqB,EAChD,CAAC;AAED,MAAa,iDACX,UACkC;CAGlC,OAAO;EACL,UAAU;EACV,aAJkB,mCAAmC,KAI3C;CACZ;AACF;AAEA,MAAa,iDACX,UACkC;CAGlC,OAAO;EACL,UAAU;EACV,aAJkB,mCAAmC,KAI3C;CACZ;AACF;AAEA,MAAa,mDAMX,UACM;CACN,OAAO,qCAAqC,KAAK;AACnD;;;ACxHA,MAAMA,eAAa,OACjB,YACA,UACA,gBACuB;CACvB,MAAM,YAAY,WAAW,KAAK,OAAO,OAAO,UAAU,CAAC;CAE3D,OAAO,MAAM,OAAO,OAAO,UACzB,OACA,WACA,EAAE,MAAM,UAAU,GAClB,aACA,QACF;AACF;AAEA,MAAMC,YAAU,OACd,KACA,UACA,cAAc,SACS;CACvB,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,KAAK,EAAE,MAAM,UAAU,GAAG,aAAa,QAAQ;AAC7F;AAEA,MAAMC,yBAAuB,OAO3B,YACA,UACA,cAAc,SACS;CACvB,IAAI,WAAW,WAAA,OACb,OAAO,MAAMD,UAAQ,WAAW,MAAM,UAAU,WAAW;CAG7D,OAAO,MAAMD,aAAW,WAAW,MAAM,UAAU,WAAW;AAChE;AAEA,MAAMG,wBAAsB,OAK1B,YACA,UACA,cAAc,SACS;CAEvB,OAAO,MAAMD,uBADO,iDAAiD,UACzB,GAAG,UAAU,WAAW;AACtE;AAEA,MAAME,iCACJ,UACA,UAEC;CACC,cAAc,UAAa,KAAK,OAAO,UAAU,IAAI;CACrD,iBAAiB,UAAa,KAAK,OAAO,UAAU,KAAK;AAC3D;AAEF,MAAa,mBAAmB;CAC9B,SAAS;EACP,qBAAqBA,8BACnB,CAAC,MAAM,GACPD,qBACF;EACA,sBAAsBC,8BACpB,CAAC,MAAM,GACPF,sBACF;EACA,SAASE,8BAA4B,CAAC,MAAM,GAAGH,SAAO;CACxD;CACA,QAAQ;EACN,YAAYG,8BAA4B,CAAC,QAAQ,GAAGJ,YAAU;EAC9D,qBAAqBI,8BACnB,CAAC,QAAQ,GACTD,qBAGF;EACA,sBAAsBC,8BACpB,CAAC,QAAQ,GACTF,sBAIF;EACA,SAASE,8BAA4B,CAAC,QAAQ,GAAGH,SAAO;CAC1D;AACF;;;AChGA,MAAa,0BAA0B,OACrC,QAC4C;CAC5C,MAAM,SAAS,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAEvD,MAAM,WACJ,iBAAuD,KAAK,UAAU,MAAM;CAS9E,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACfA,MAAa,0BAA0B,OACrC,cAC4C;CAC5C,MAAM,kBAAkB,MAAM,OAAO,OAAO,UAAU,OAAO,SAAS;CACtE,MAAM,kBAAkB,OAAO,OAAO,IAAI,WAAW,eAAe,CAAC;CAErE,MAAM,WACJ,wBAA8D;CAShE,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACvBA,MAAa,uBAAuB,OAAO,EACzC,WACA,iBACA,gBAKsB;CACtB,MAAM,kBAAkB,WAAW,KAAK,OAAO,OAAO,eAAe,CAAC;CACtE,MAAM,kBAAkB,IAAI,YAAY,CAAC,CAAC,OAAO,SAAS;CAE1D,OAAO,MAAM,OAAO,OAAO,OACzB,EACE,MAAM,UACR,GACA,WACA,iBACA,eACF;AACF;;;ACtBA,MAAa,wBAAwB,YAAoC;CAMvE,OAAO,MALgB,OAAO,OAAO,YAAY,EAAE,MAAM,SAAS,GAAG,MAAM,CACzE,aACA,YACF,CAAC;AAGH;;;ACGA,MAAM,aAAa,OACjB,YACA,UACA,gBACuB;CACvB,MAAM,YAAY,WAAW,KAAK,OAAO,OAAO,UAAU,CAAC;CAE3D,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,WAAW,EAAE,MAAM,SAAS,GAAG,aAAa,QAAQ;AAClG;AAEA,MAAM,UAAU,OACd,KACA,UACA,cAAc,SACS;CACvB,OAAO,MAAM,OAAO,OAAO,UAAU,OAAO,KAAK,EAAE,MAAM,SAAS,GAAG,aAAa,QAAQ;AAC5F;AAEA,MAAM,uBAAuB,OAO3B,YACA,UACA,cAAc,SACS;CACvB,IAAI,WAAW,WAAA,OACb,OAAO,MAAM,QAAQ,WAAW,MAAM,UAAU,WAAW;CAG7D,OAAO,MAAM,WAAW,WAAW,MAAM,UAAU,WAAW;AAChE;AAEA,MAAM,sBAAsB,OAK1B,YACA,UACA,cAAc,SACS;CAEvB,OAAO,MAAM,qBADO,gDAAgD,UACxB,GAAG,UAAU,WAAW;AACtE;AAEA,MAAM,+BACJ,UACA,UAEC;CACC,cAAc,UAAa,KAAK,OAAO,UAAU,IAAI;CACrD,iBAAiB,UAAa,KAAK,OAAO,UAAU,KAAK;AAC3D;AAEF,MAAa,kBAAkB;CAC7B,SAAS;EACP,qBAAqB,4BACnB,CAAC,aAAa,YAAY,GAC1B,mBACF;EACA,sBAAsB,4BACpB,CAAC,aAAa,YAAY,GAC1B,oBACF;EACA,SAAS,4BAA4B,CAAC,aAAa,YAAY,GAAG,OAAO;CAC3E;CACA,QAAQ;EACN,YAAY,4BAA4B,CAAC,GAAG,UAAU;EACtD,qBAAqB,4BACnB,CAAC,GACD,mBAGF;EACA,sBAAsB,4BACpB,CAAC,GACD,oBAIF;EACA,SAAS,4BAA4B,CAAC,GAAG,OAAO;CAClD;AACF;;;AC1FA,MAAa,yBAAyB,OACpC,QAC2C;CAC3C,MAAM,eAAe,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAE7D,MAAM,WACJ,gBAAsD,KAAK,UAAU,YAAY;CASnF,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;ACfA,MAAa,yBAAyB,OACpC,QAC2C;CAC3C,MAAM,kBAAkB,MAAM,OAAO,OAAO,UAAU,OAAO,GAAG;CAChE,MAAM,kBAAkB,OAAO,OAAO,IAAI,WAAW,eAAe,CAAC;CAErE,MAAM,WACJ,uBAA6D;CAS/D,OAAO;EAAE,aAAA;GANP,iBAAiB;GACjB,MAAA;GACA,MAAM;GACN,QAAA;EAGiB;EAAG;CAAS;AACjC;;;;;;;;AC2BA,IAAa,8BAAb,cAAiD,MAAM;CACrD,YACE,UAAU,wIACV;EACA,MAAM,OAAO;EACb,KAAK,OAAO;CACd;AACF;AAyFA,IAAa,sBAAb,MAAiC;CAC/B;CACA;CACA,mCAA2B,IAAI,IAA2C;CAC1E;CACA;CACA,cAAsB;CACtB;CACA;CACA;CAEA,YAAY,EAAE,gBAAgB,iBAAmD,CAAC,GAAG;EACnF,IAAI,kBAAkB,MACpB,KAAK,UAAU,mBAAmB,EAAE,eAAe,CAAC;EAEtD,KAAK,eAAe,gBAAgB;CACtC;;;;;;;CAQA,MAAM,aAA4B;EAChC,IAAI,KAAK,aACP;EAKF,KAAK,sBAAsB,KAAK,cAAc;EAE9C,IAAI;GACF,MAAM,KAAK;EACb,UAAU;GACR,KAAK,oBAAoB,KAAA;EAC3B;CACF;CAEA,MAAc,gBAA+B;EAC3C,MAAM,KAAK,oBAAoB;EAC/B,MAAM,KAAK,kBAAkB;EAE7B,KAAK,cAAc;CACrB;;;;;;;;;;;;;;CAeA,MAAM,oBAAmC;EACvC,MAAM,KAAK,WAAW;EACtB,MAAM,KAAK,yBAAyB;EACpC,MAAM,KAAK,uBAAuB;CACpC;;;;;;;CAQA,MAAc,sBAAqC;EACjD,MAAM,iBAAiB,MAAM,KAAK,SAAS,QAAQ,sBAAsB;EACzE,IAAI,kBAAkB,MACpB,KAAK,uBAAuB;GAC1B,YAAY,MAAM,gBAAgB,QAAQ,oBAAoB,YAC5D,eAAe,UACjB;GACA,WAAW,MAAM,gBAAgB,OAAO,oBAAoB,YAC1D,eAAe,SACjB;EACF;EAGF,MAAM,eAAe,MAAM,KAAK,SAAS,QAAQ,oBAAoB;EACrE,IAAI,gBAAgB,MAClB,KAAK,qBAAqB;GACxB,YAAY,MAAM,iBAAiB,QAAQ,oBAAoB,YAC7D,aAAa,UACf;GACA,WAAW,MAAM,iBAAiB,OAAO,oBAAoB,YAC3D,aAAa,SACf;EACF;CAEJ;;;;;;CAOA,MAAc,6BAAqD;EACjE,IAAI,KAAK,wBAAwB,MAC/B,OAAO,KAAK;EAEd,IAAI,KAAK,iBAAiB,YACxB,MAAM,IAAI,4BAA4B;EAExC,OAAO,KAAK,yBAAyB;CACvC;;;;;;CAOA,MAAc,2BAAmD;EAC/D,IAAI,KAAK,wBAAwB,MAC/B,OAAO,KAAK;EAGd,KAAK,iCAAiC,YAAY;GAChD,MAAM,UAAU,MAAM,sBAAsB;GAC5C,KAAK,uBAAuB;GAC5B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QACjB,wBACA,MAAM,KAAK,yBAAyB,OAAO,CAC7C;GAEF,OAAO;EACT,EAAA,CAAG;EAEH,IAAI;GACF,OAAO,MAAM,KAAK;EACpB,UAAU;GACR,KAAK,8BAA8B,KAAA;EACrC;CACF;;;;;;CAOA,MAAc,2BAAmD;EAC/D,IAAI,KAAK,sBAAsB,MAC7B,OAAO,KAAK;EAEd,IAAI,KAAK,iBAAiB,YACxB,MAAM,IAAI,4BAA4B;EAExC,OAAO,KAAK,uBAAuB;CACrC;;;;;;CAOA,MAAc,yBAAiD;EAC7D,IAAI,KAAK,sBAAsB,MAC7B,OAAO,KAAK;EAGd,KAAK,+BAA+B,YAAY;GAC9C,MAAM,UAAU,MAAM,uBAAuB;GAC7C,KAAK,qBAAqB;GAC1B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QACjB,sBACA,MAAM,KAAK,uBAAuB,OAAO,CAC3C;GAEF,OAAO;EACT,EAAA,CAAG;EAEH,IAAI;GACF,OAAO,MAAM,KAAK;EACpB,UAAU;GACR,KAAK,4BAA4B,KAAA;EACnC;CACF;CAEA,MAAc,oBAAmC;EAC/C,MAAM,sBAAsB,MAAM,KAAK,SAAS,QAAQ,wBAAwB;EAEhF,IAAI,uBAAuB,MACzB;EAGF,KAAK,MAAM,CAAC,gBAAgB,eAAe,OAAO,QAAQ,mBAAmB,GAI3E,MAAM,KAAK,WAAW;GACpB;GACA,iBAAiB,WAAW;GAC5B,mBAAmB,WAAW;GAC9B,YAAY,WAAW;GACvB,YAAY,WAAW;GACvB,8BAA8B,WAAW;EAC3C,CAAC;CAEL;CAEA,MAAc,yBACZ,SAC6C;EAC7C,OAAO;GACL,YAAY,MAAM,uBAAuB,QAAQ,SAAS,EAAA,CAAG;GAC7D,aAAa,MAAM,uBAAuB,QAAQ,UAAU,EAAA,CAAG;EACjE;CACF;CAEA,MAAc,uBACZ,SAC8C;EAC9C,OAAO;GACL,YAAY,MAAM,wBAAwB,QAAQ,SAAS,EAAA,CAAG;GAC9D,aAAa,MAAM,wBAAwB,QAAQ,UAAU,EAAA,CAAG;EAClE;CACF;;;;;;CAOA,MAAM,qBAAgD;EACpD,OAAO;GACL,iBAAiB,MAAM,KAAK,wBAAwB;GACpD,mBAAmB,MAAM,KAAK,0BAA0B;EAC1D;CACF;;;;;;CAOA,MAAM,4BAA0E;EAE9E,QAAQ,MAAM,wBAAuB,MADP,KAAK,2BAA2B,EAAA,CACT,SAAS,EAAA,CAAG;CACnE;;;;;CAMA,MAAM,0BAAyE;EAE7E,QAAQ,MAAM,yBAAwB,MADV,KAAK,yBAAyB,EAAA,CACN,SAAS,EAAA,CAAG;CAClE;;;;;;;;;CAUA,MAAM,WAAW,EACf,gBACA,iBACA,mBACA,YACA,YACA,gCACiC;EACjC,MAAM,WAAW,KAAK,iBAAiB,IAAI,cAAc;EAEzD,MAAM,SACJ,mBAAmB,OACf;GACE,WACE,MAAM,iBAAiB,OAAO,oBAAoB,YAAY,eAAe;GAC/E,qBAAqB;EACvB,IACA,UAAU;EAEhB,MAAM,mBACJ,mBAAmB,QAAQ,oBAAoB,UAAU,QAAQ;EAEnE,IAAI,WAAW,UAAU;EASzB,IALE,qBAAqB,QACrB,eAAe,KAAA,KACf,eAAe,KAAA,KACf,iCAAiC,KAAA,GAEP;GAC1B,MAAM,0BAA0B,qBAAqB,UAAU,UAAU;GAEzE,IAAI,2BAA2B,MAC7B,MAAM,IAAI,MACR,iDAAiD,eAAe,gCAClE;GAGF,MAAM,WAAW,eAAe,KAAA,IAAY,aAAa,UAAU,UAAU;GAC7E,MAAM,WAAW,eAAe,KAAA,IAAY,aAAa,UAAU,UAAU;GAC7E,MAAM,WACJ,iCAAiC,KAAA,IAC7B,+BACA,UAAU,UAAU;GAgB1B,WAAW;IACT,WAdA,qBAAqB,OACjB,MAAM,gBAAgB,OAAO,oBAAoB,YAAY,iBAAiB,IAE9E,SAAU,SAAU;IAYxB,qBAAqB;IACrB,YAAY;IACZ,YAAY;IACZ,8BAA8B;IAE9B,kBAdA,4BAA4B,UAAU,UAAU,uBAChD,aAAa,UAAU,UAAU,cACjC,aAAa,UAAU,UAAU,cACjC,aAAa,UAAU,UAAU,gCAEjC,EAAE,aAAa,QAAQ,oBASO,UAAU,UAAU,mBAAmB,KAAA;GACvE;EACF,OAAO,IACL,UAAU,iCAAiC,QAC3C,oBACA,SAAS,oBAAoB,MAG7B,WAAW;GAAE,GAAG;GAAU,kBAAkB,KAAA;EAAU;EAGxD,KAAK,iBAAiB,IAAI,gBAAgB;GAAE;GAAQ;EAAS,CAAC;CAChE;;;;;;;;CASA,MAAM,mBAAmB,OAAuC;EAC9D,MAAM,KAAK,WAAW,KAAK;EAE3B,IAAI,KAAK,WAAW,MAClB;EAGF,MAAM,EACJ,gBACA,iBACA,mBACA,YACA,YACA,iCACE;EAEJ,MAAM,KAAK,QAAQ,kBAAkB,0BAA0B,CAAC,IAAI,aAAa;GAC/E,GAAG;IACF,iBAAiB;IAChB,GAAG,QAAQ;IACX,GAAI,mBAAmB,OAAO,EAAE,gBAAgB,IAAI,CAAC;IACrD,GAAI,qBAAqB,OAAO,EAAE,kBAAkB,IAAI,CAAC;IACzD,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;IACjD,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;IACjD,GAAI,iCAAiC,KAAA,IAAY,EAAE,6BAA6B,IAAI,CAAC;GACvF;EACF,EAAE;CACJ;;;;CAKA,gBAAgB,gBAAqC;EACnD,OAAO,KAAK,iBAAiB,IAAI,cAAc;CACjD;;;;;;CAOA,0BAA0B,gBAAiE;EACzF,MAAM,eAAe,KAAK,iBAAiB,IAAI,cAAc;EAE7D,IAAI,gBAAgB,MAClB;EAGF,OAAO;GACL,iBAAiB,aAAa,QAAQ;GACtC,mBAAmB,aAAa,UAAU;EAC5C;CACF;;;;;CAMA,MAAM,aAAa,gBAA2C;EAC5D,KAAK,iBAAiB,OAAO,cAAc;EAE3C,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,WAAW,2BAA2B,YAAY;GACnE,IAAI,WAAW,MACb,OAAO,CAAC;GAGV,MAAM,GAAG,iBAAiB,UAAU,GAAG,SAAS;GAChD,OAAO;EACT,CAAC;CAEL;;;;;CAMA,MAAM,mBAAkC;EACtC,KAAK,iBAAiB,MAAM;EAE5B,IAAI,KAAK,WAAW,MAClB,MAAM,KAAK,QAAQ,QAAQ,0BAA0B,CAAC,CAAC;CAE3D;;;;;;;;;CAUA,MAAM,QAAuB;EAC3B,KAAK,iBAAiB,MAAM;EAC5B,KAAK,uBAAuB,KAAA;EAC5B,KAAK,qBAAqB,KAAA;EAC1B,KAAK,cAAc;EAEnB,IAAI,KAAK,WAAW,MAAM;GACxB,MAAM,KAAK,QAAQ,WAAW,wBAAwB;GACtD,MAAM,KAAK,QAAQ,WAAW,sBAAsB;GACpD,MAAM,KAAK,QAAQ,WAAW,oBAAoB;EACpD;CACF;CAEA,gBAAwB,gBAAuD;EAC7E,MAAM,eAAe,KAAK,iBAAiB,IAAI,cAAc;EAE7D,IAAI,gBAAgB,MAClB,MAAM,IAAI,MAAM,6CAA6C,gBAAgB;EAG/E,OAAO;CACT;CAEA,MAAc,4BACZ,wBACoB;EACpB,MAAM,eAAe,KAAK,gBAAgB,sBAAsB;EAEhE,IAAI,aAAa,UAAU,oBAAoB,MAC7C,OAAO,aAAa,SAAS;EAG/B,IAAI,aAAa,UAAU,aAAa,MACtC,MAAM,IAAI,MACR,uDAAuD,wBACzD;EAGF,MAAM,uBAAuB,MAAM,KAAK,2BAA2B;EAEnE,IAAI,aAAa,aAAa,SAAS;EAEvC,IAAI,aAAa,SAAS,iCAAiC,MAAM;GAC/D,MAAM,wBAAwB,aAAa,QAAQ;GAEnD,IAAI,yBAAyB,MAC3B,MAAM,IAAI,MACR,iCAAiC,uBAAuB,wEAC1D;GAGF,aAAa,8BAA8B;IACzC,YAAY,aAAa,SAAS;IAClC,kBAAkB,CAAC,MAAM,KAAK,wBAAwB,GAAG,qBAAqB;GAChF,CAAC;EACH;EAEA,MAAM,mBAAmB,MAAM,8BAA8B;GAC3D,0BAA0B,qBAAqB;GAC/C,yBAAyB,aAAa,SAAS;GAC/C,YAAY,aAAa,SAAS;GAClC;EACF,CAAC;EAED,KAAK,iBAAiB,IAAI,wBAAwB;GAChD,GAAG;GACH,UAAU;IACR,GAAG,aAAa;IAChB;GACF;EACF,CAAC;EAED,OAAO;CACT;;;;;;;;;;;;;CAcA,MAAM,sBAAsB,EAC1B,mBACA,YACA,YACA,8BACA,mBAQqB;EACrB,MAAM,uBAAuB,MAAM,KAAK,2BAA2B;EACnE,MAAM,0BACJ,MAAM,gBAAgB,OAAO,oBAAoB,YAAY,iBAAiB;EAEhF,IAAI,oBAAoB;EACxB,IAAI,iCAAiC,MAAM;GACzC,IAAI,mBAAmB,MACrB,MAAM,IAAI,MACR,yHACF;GAEF,oBAAoB,8BAA8B;IAChD;IACA,kBAAkB,CAAC,MAAM,KAAK,wBAAwB,GAAG,eAAe;GAC1E,CAAC;EACH;EAEA,OAAO,MAAM,8BAA8B;GACzC,0BAA0B,qBAAqB;GAC/C;GACA;GACA,YAAY;EACd,CAAC;CACH;;;;;;;;;;;;;;;CAgBA,MAAM,mBAAmB,SAAoD;EAC3E,MAAM,uBAAuB,MAAM,KAAK,2BAA2B;EACnE,OAAO,MAAM,8BAA8B;GACzC,0BAA0B,qBAAqB;GAC/C,yBAAyB,qBAAqB;GAC9C,YAAY,wBAAwB,SAAS,WAAW;EAC1D,CAAC;CACH;CAEA,MAAM,2BAA2B,EAC/B,eACA,kBACgE;EAGhE,OAAO,MAAM,6BAA6B;GACxC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;CAEA,MAAM,4BAA4B,EAChC,eACA,kBACgD;EAGhD,OAAO,MAAM,6BAA6B;GACxC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;;;;;;CAOA,MAAM,4BAA4B,EAChC,eACA,kBAIiC;EAGjC,OAAO,MAAM,0BAA0B;GACrC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;;CAGA,MAAM,6BAA6B,EACjC,eACA,kBAIsB;EAGtB,OAAO,MAAM,0BAA0B;GACrC;GACA,WAAW,MAJK,KAAK,4BAA4B,cAAc;EAKjE,CAAC;CACH;CAEA,MAAM,kCAAkC,EACtC,eACA,kBAIC;EACD,MAAM,EAAE,oBAAoB,MAAM,KAAK,cAAc,CAAC,aAAa,CAAC;EAMpE,OAAO;GACL,eAAA,MAN0B,KAAK,2BAA2B;IAC1D;IACA;GACF,CAAC;GAIC;EACF;CACF;;;;;;;;CASA,MAAM,qCAAqC,EACzC,eACA,gBACA,mBACqF;EACrF,MAAM,OAAO,MAAM,KAAK,4BAA4B;GAClD;GACA;EACF,CAAC;EAQD,OAAO;GAAE;GAAM,SAAA,MANO,KAAK,gCAAgC;IACzD;IACA,WAAW;IACX;GACF,CAAC;EAEsB;CACzB;CAEA,MAAM,cAAc,WAEjB;EACD,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,qBAAqB,MAAM,KAAK,yBAAyB;EAE/D,MAAM,YACJ,UAAU,SAAS,IACf,MAAM,mCAAmC,WAAW,mBAAmB,UAAU,IACjF,MAAM,2BAA2B,UAAU,IAAI,mBAAmB,UAAU;EAElF,OAAO,EACL,iBAAiB,OAAO,OAAO,SAAS,EAC1C;CACF;;;;CAKA,MAAM,gCAAgC,EACpC,gBACA,WACA,mBACqD;EACrD,MAAM,eAAe,KAAK,gBAAgB,cAAc;EAExD,IAAI,aAAa,QAAQ,aAAa,MACpC,MAAM,IAAI,MAAM,qDAAqD,gBAAgB;EAGvF,OAAO,MAAM,qBAAqB;GAChC;GACA;GACA,WAAW,aAAa,OAAO;EACjC,CAAC;CACH;AACF;;;ACt3BA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,YAAA;CACA,oBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;;;ACYA,IAAa,iBAAb,MAAa,eAAe;CAC1B;CACA;CACA;CAEA,YAAY,EAAE,SAAS,WAAW,sBAAsB,aAAyC;EAC/F,KAAK,iBAAiB;EACtB,KAAK,YAAY,aAAa;EAC9B,MAAM,aAAa,aAAa;EAGhC,KAAK,iBAAiB,aAClB,mBAAmB,EACjB,gBAAgB,IAAI,eAAe;GAAE;GAAS;GAAW,sBAAsB;EAAM,CAAC,EACxF,CAAC,IACD,KAAA;CACN;CAEA,eAAuB,QAAwB;EAC7C,OAAO,GAAG,KAAK,YAAY;CAC7B;;;;;;CAOA,cAAc,aAAqC;EACjD,OAAO,IAAI,eAAe;GACxB,SAAS,KAAK;GACd,WAAW,GAAG,KAAK,YAAY;EACjC,CAAC;CACH;CAEA,MAAc,aAAa,QAA+B;EACxD,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,KAAK,eAAe,kBAAkB,gBAAgB,CAAC,IAAI,gBAAgB;GAC/E,IAAI,CAAC,YAAY,SAAS,MAAM,GAC9B,OAAO,CAAC,GAAG,aAAa,MAAM;GAEhC,OAAO;EACT,CAAC;CACH;CAEA,MAAc,eAAe,QAA+B;EAC1D,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,KAAK,eAAe,kBAAkB,gBAAgB,CAAC,IAAI,gBAAgB;GAC/E,OAAO,YAAY,QAAQ,MAAM,MAAM,MAAM;EAC/C,CAAC;CACH;CAEA,MAAM,WAA0B;EAC9B,IAAI,CAAC,KAAK,gBAAgB;EAC1B,MAAM,UAAW,MAAM,KAAK,eAAe,aAAa,gBAAgB,CAAC,CAAC,KAAM,CAAC;EAEjF,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,QAAQ;GACzB,MAAM,KAAK,WAAW,GAAG;EAC3B,CAAC,CACH;EAEA,MAAM,KAAK,eAAe,QAAQ,gBAAgB,CAAC,CAAC;CACtD;CAEA,MAAM,WAAW,QAA+B;EAC9C,MAAM,KAAK,eAAe,WAAW,KAAK,eAAe,MAAM,CAAC;EAChE,MAAM,KAAK,eAAe,MAAM;CAClC;CAEA,MAAM,QAAQ,QAAgB,OAAY;EACxC,MAAM,MAAM,KAAK,eAAe,MAAM;EAEtC,IAAI,KAAK,eAAe,SAAA,UACtB,MAAM,KAAK,eAAe,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;OAE5D,MAAM,KAAK,eAAe,QAAQ,KAAK,KAAK;EAG9C,MAAM,KAAK,aAAa,MAAM;CAChC;CAEA,MAAM,QAAW,QAAwC;EACvD,MAAM,MAAM,KAAK,eAAe,MAAM;EAEtC,IAAI,KAAK,eAAe,SAAA,UAAqC;GAC3D,MAAM,MAAM,MAAM,KAAK,eAAe,QAAQ,GAAG;GAEjD,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD;GAGF,OAAO,KAAK,MAAM,GAAG;EACvB,OAAO;GACL,MAAM,MAAM,MAAM,KAAK,eAAe,QAAW,GAAG;GAEpD,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD;GAGF,OAAO;EACT;CACF;CAEA,MAAM,aAAgB,QAAgB,QAAuB;EAC3D,IAAI,KAAK,eAAe,SAAA,UAAqC;GAC3D,MAAM,MAAM,MAAM,KAAK,eAAe,QAAQ,KAAK,eAAe,MAAM,CAAC;GAEzE,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD,OAAO;GAGT,OAAO,KAAK,MAAM,GAAG;EACvB;EAEA,MAAM,MAAM,MAAM,KAAK,eAAe,QAAW,KAAK,eAAe,MAAM,CAAC;EAE5E,IAAI,OAAO,QAAQ,QAAQ,eAAe,QAAQ,QAChD,OAAO;EAGT,OAAO;CACT;CAEA,MAAM,WAAc,QAAgB,SAAuD;EAEzF,MAAM,SAAS,QAAQ,MADE,KAAK,QAAW,MAAM,CACd;EACjC,MAAM,KAAK,QAAQ,QAAQ,MAAM;EACjC,OAAO;CACT;CAEA,MAAM,gBAAmB,QAAgB,QAAW,SAA2C;EAE7F,MAAM,SAAS,QAAQ,MADE,KAAK,aAAgB,QAAQ,MAAM,CAC3B;EACjC,MAAM,KAAK,QAAQ,QAAQ,MAAM;EACjC,OAAO;CACT;CAEA,uBAA0B,QAA+C;EACvE,OAAO;GACL,WAAW,KAAK,QAAQ,MAAM;GAC9B,MAAM,UAAa,KAAK,QAAQ,QAAQ,KAAK;EAC/C;CACF;AACF;;;AC/IA,SAAgB,6BACd,eAC+B;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,cAAc,QAAQ,GAAG;EACjD,SAAS,OAAO,KAAK,UAAU;GAC7B,cAAc,QAAQ,KAAK,KAAK;EAClC;EACA,YAAY,OAAO,QAAQ;GACzB,cAAc,WAAW,GAAG;EAC9B;CACF;AACF;AAEA,MAAa,gCAAgC,EAC3C,cAAc,eACd,GAAG,cACgD;CACnD,OAAO,IAAI,eAAe;EACxB,SAAS,6BAA6B,aAAa;EACnD,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,2BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,6BAA6B,OAAO,EACtD,CAAC;AACH;AAYA,SAAgB,+BACd,iBAC+B;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,gBAAgB,QAAQ,GAAG;EACnD,SAAS,OAAO,KAAK,UAAU;GAC7B,gBAAgB,QAAQ,KAAK,KAAK;EACpC;EACA,YAAY,OAAO,QAAQ;GACzB,gBAAgB,WAAW,GAAG;EAChC;CACF;AACF;AAEA,MAAa,kCAAkC,EAC7C,gBAAgB,iBAChB,GAAG,cACkD;CACrD,OAAO,IAAI,eAAe;EACxB,SAAS,+BAA+B,eAAe;EACvD,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,6BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,+BAA+B,OAAO,EACxD,CAAC;AACH;;;ACnFA,SAAgB,kCACd,sBAC6B;CAC7B,OAAO;EACL,MAAA;EACA,UAAU,QAAQ,qBAAqB,IAAI,GAAG;EAC9C,UAAU,KAAK,UAAU,qBAAqB,IAAI,KAAK,KAAK;EAC5D,YAAY,OAAO,QAAQ;GACzB,MAAM,qBAAqB,OAAO,GAAG;EACvC;CACF;AACF;;;;;AAUA,MAAa,qCAAqC,EAChD,sBACA,GAAG,cACqD;CACxD,OAAO,IAAI,eAAe;EACxB,SAAS,kCAAkC,oBAAoB;EAC/D,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,gCACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,kCAAkC,OAAO,EAC3D,CAAC;AACH;;;AC9BA,SAAgB,uBAAuB,EACrC,aACA,qBACgE;CAChE,OAAO;EACL,MAAA;EACA,UAAU,QAAQ,YAAY,IAAI,GAAG;EACrC,UAAU,KAAK,UAAU,YAAY,IAAI,KAAK,OAAO,iBAAiB;EACtE,aAAa,QAAQ,YAAY,OAAO,GAAG;CAC7C;AACF;;;;;AASA,MAAa,0BAA0B,EACrC,aACA,mBACA,GAAG,cAC0C;CAC7C,OAAO,IAAI,eAAe;EACxB,SAAS,uBAAuB;GAAE;GAAa;EAAkB,CAAC;EAClE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,qBACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,uBAAuB,OAAO,EAChD,CAAC;AACH;;;AC9BA,SAAgB,kCACd,mCAA0C,IAAI,IAAI,GACnB;CAC/B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,iBAAiB,IAAI,GAAG,KAAK;EACrD,SAAS,OAAO,KAAK,UAAU;GAC7B,iBAAiB,IAAI,KAAK,KAAK;EACjC;EACA,YAAY,OAAO,QAAQ;GACzB,iBAAiB,OAAO,GAAG;EAC7B;CACF;AACF;AAEA,MAAa,qCACX,YACmB;CACnB,OAAO,IAAI,eAAe;EACxB,SAAS,kCAAkC,SAAS,gBAAgB;EACpE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,gCACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,kCAAkC,OAAO,EAC3D,CAAC;AACH;AAYA,SAAgB,gCACd,mCAAwC,IAAI,IAAI,GACnB;CAC7B,OAAO;EACL,MAAA;EACA,SAAS,OAAO,QAAQ,iBAAiB,IAAI,GAAG;EAChD,SAAS,OAAO,KAAK,UAAU;GAC7B,iBAAiB,IAAI,KAAK,KAAK;EACjC;EACA,YAAY,OAAO,QAAQ;GACzB,iBAAiB,OAAO,GAAG;EAC7B;CACF;AACF;AAEA,MAAa,mCACX,YACmB;CACnB,OAAO,IAAI,eAAe;EACxB,SAAS,gCAAgC,SAAS,gBAAgB;EAClE,GAAG;CACL,CAAC;AACH;AAEA,SAAgB,8BACd,SACkB;CAClB,OAAO,mBAAsB,EAC3B,gBAAgB,gCAAgC,OAAO,EACzD,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice-code/util",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./build/index.cjs",