{"version":3,"file":"encrypt-storage-web-api.cjs","names":["#keys","#encAlgorithm","#stateManagementUse","#doNotEncryptValues","#doNotParseValues","#notifyHandler","#prefix","#allowNull","#allowUndefined","#storageType","InvalidSecretKeyError","AsyncEncryptCookie","#getKey","#notifier","IsNotBrowserEnvironmentError","#init","#encryptation","getAsyncEncryptation","#verifyEncryptation","nullValueErrorHandler","undefinedValueErrorHandler","#valueValidate","#multiple","hashAsyncSHA256","#getTTLRecord"],"sources":["../../src/classes/encrypt-storage-web-api.ts"],"sourcesContent":["import { InvalidSecretKeyError, IsNotBrowserEnvironmentError } from '@/errors';\nimport {\n  hashAsyncSHA256,\n  getAsyncEncryptation,\n  SECRET_KEY_MIN_LENGTH,\n  nullValueErrorHandler,\n  undefinedValueErrorHandler,\n} from '@/utils';\n\nimport { AsyncEncryptCookie } from './async-encrypt-cookie';\n\nimport type {\n  NotifyHandler,\n  CookieOptions,\n  AsyncEncryptation,\n  RemoveCookieOptions,\n  AsyncCookieInterface,\n  GetFromPatternOptions,\n  EncryptAlgorithms,\n  RemoveFromPatternOptions,\n  AsyncEncryptStorageOptions,\n  EncryptStorageCryptoWebApiInterface,\n  NotifyHandlerParams,\n  TTLStorageValue,\n  SetTTLItemParams,\n  AsyncEncryptStorageTTLInterface,\n  TTLMetadata,\n  RefreshTTLParams,\n  StorageType,\n  BaseEcnryptStorageOptions,\n} from '@/@types';\n\nconst secret = new globalThis.WeakMap();\n\nexport class EncryptStorageWebApi\n  implements\n    EncryptStorageCryptoWebApiInterface,\n    AsyncEncryptStorageTTLInterface\n{\n  readonly #keys: Set<string> = new Set();\n\n  // @ts-expect-error\n  #encryptation: AsyncEncryptation;\n\n  readonly #encAlgorithm: EncryptAlgorithms;\n\n  readonly #stateManagementUse: boolean;\n\n  readonly #doNotEncryptValues: boolean;\n\n  readonly #doNotParseValues: boolean;\n\n  readonly #notifyHandler: NotifyHandler | undefined;\n\n  readonly #prefix: string;\n\n  readonly #allowNull: boolean;\n\n  readonly #allowUndefined: boolean;\n\n  readonly #storageType: StorageType;\n\n  #multiple = false;\n\n  public readonly api = 'web-crypto' as const;\n\n  public cookie: AsyncCookieInterface;\n\n  /**\n   * EncryptStorage provides a wrapper implementation of `localStorage` and `sessionStorage` for a better security solution in browser data store\n   *\n   * @param {string} secretKey - A secret to encrypt data must be contain min of 10 characters\n   * @param {AsyncEncryptStorageOptions} [options] - Settings to set encryptData or select `sessionStorage` to browser storage\n   */\n  constructor(secretKey: string, options: BaseEcnryptStorageOptions = {}) {\n    if (secretKey.length < SECRET_KEY_MIN_LENGTH) {\n      throw new InvalidSecretKeyError();\n    }\n\n    const {\n      storageType = 'localStorage',\n      prefix = '',\n      stateManagementUse = false,\n      encAlgorithm = 'AES-GCM',\n      doNotEncryptValues = false,\n      notifyHandler,\n      doNotParseValues = false,\n      validation = {\n        strict: false,\n        allowNull: true,\n        allowUndefined: false,\n      },\n    } = options;\n\n    secret.set(this, secretKey);\n\n    this.#prefix = prefix;\n    this.#notifyHandler = notifyHandler;\n    this.#stateManagementUse = stateManagementUse;\n    this.#doNotEncryptValues = doNotEncryptValues;\n    this.#doNotParseValues = doNotParseValues;\n    this.#encAlgorithm = encAlgorithm;\n    this.#allowNull = validation?.strict\n      ? false\n      : (validation?.allowNull ?? true);\n    this.#allowUndefined = validation?.strict\n      ? false\n      : (validation?.allowUndefined ?? false);\n    this.#storageType = storageType;\n\n    this.cookie = new AsyncEncryptCookie({\n      decryptValue: (value) => this.decryptValue(value),\n      encryptValue: (value) => this.encryptValue(value),\n      getKey: (key) => this.#getKey(key),\n      notifier: (params) => this.#notifier(params),\n      doNotEncryptValues: this.#doNotEncryptValues,\n      doNotParseValues: this.#doNotParseValues,\n    });\n  }\n\n  get storage(): Storage {\n    if (typeof window === 'undefined') {\n      throw new IsNotBrowserEnvironmentError();\n    }\n\n    return window[this.#storageType];\n  }\n\n  async #init(encAlgorithm: EncryptAlgorithms) {\n    this.#encryptation = await getAsyncEncryptation(\n      encAlgorithm,\n      secret.get(this),\n    );\n  }\n\n  #getKey(key: string): string {\n    return this.#prefix ? `${this.#prefix}:${key}` : key;\n  }\n\n  #notifier(params: NotifyHandlerParams, callback?: VoidFunction) {\n    if (this.#notifyHandler) {\n      this.#notifyHandler(params);\n      callback?.();\n    }\n  }\n\n  async #verifyEncryptation() {\n    if (!this.#encryptation) {\n      await this.#init(this.#encAlgorithm);\n    }\n  }\n\n  #valueValidate<T = unknown>(value: T): T {\n    let validatedValue = value;\n\n    if (!this.#allowNull) {\n      validatedValue = nullValueErrorHandler<T>(value);\n    }\n\n    if (!this.#allowUndefined) {\n      validatedValue = undefinedValueErrorHandler<T>(value);\n    }\n\n    return validatedValue;\n  }\n\n  public get length() {\n    const value = this.storage.length || 0;\n\n    this.#notifier({\n      type: 'length',\n      value,\n    });\n\n    return value;\n  }\n\n  public async setItem(\n    key: string,\n    value: any,\n    doNotEncrypt = false,\n  ): Promise<void> {\n    const validatedValue = this.#valueValidate(value);\n    await this.#verifyEncryptation();\n    const encryptValues = this.#doNotEncryptValues || doNotEncrypt;\n    const storageKey = this.#getKey(key);\n    let valueToString =\n      typeof value === 'object'\n        ? JSON.stringify(validatedValue)\n        : String(validatedValue);\n\n    if (this.#doNotParseValues) {\n      valueToString = value;\n    }\n\n    const encryptedValue = encryptValues\n      ? valueToString\n      : await this.#encryptation.encrypt(valueToString);\n\n    this.storage.setItem(storageKey, encryptedValue);\n\n    if (!this.#multiple) {\n      this.#notifier({\n        type: 'set',\n        key,\n        value: valueToString,\n      });\n    }\n\n    this.#keys.add(key);\n  }\n\n  public async setMultipleItems(\n    param: [string, any][],\n    doNotEncrypt?: boolean,\n  ): Promise<void> {\n    await this.#verifyEncryptation();\n    this.#multiple = true;\n    await Promise.all(\n      param.map(([key, value]) => this.setItem(key, value, doNotEncrypt)),\n    );\n\n    const keys = param.map(([key]) => key);\n    const values = param.map(([_, value]) =>\n      typeof value === 'object' ? JSON.stringify(value) : String(value),\n    );\n    this.#notifier({\n      type: 'setMultiple',\n      key: keys,\n      value: values,\n    });\n\n    this.#multiple = false;\n  }\n\n  public async getItem<DataType = any>(\n    key: string,\n    doNotDecrypt = false,\n  ): Promise<DataType | undefined> {\n    await this.#verifyEncryptation();\n    const decryptValues = this.#doNotEncryptValues || doNotDecrypt;\n    const storageKey = this.#getKey(key);\n    const item = this.storage.getItem(storageKey);\n\n    if (item) {\n      const decryptedValue = decryptValues\n        ? item\n        : await this.#encryptation.decrypt(item);\n\n      if (this.#stateManagementUse && !this.#multiple) {\n        if (this.#notifyHandler) {\n          this.#notifyHandler({\n            type: 'get',\n            key,\n            value: decryptedValue,\n          });\n        }\n        return decryptedValue as unknown as DataType;\n      }\n\n      try {\n        const value = this.#doNotParseValues\n          ? decryptedValue\n          : JSON.parse(decryptedValue);\n\n        if (!this.#multiple) {\n          this.#notifier({\n            type: 'get',\n            key,\n            value,\n          });\n        }\n\n        return value as DataType;\n      } catch {\n        if (!this.#multiple) {\n          this.#notifier({\n            type: 'get',\n            key,\n            value: decryptedValue,\n          });\n        }\n        return decryptedValue as unknown as DataType;\n      }\n    }\n\n    if (!this.#multiple) {\n      this.#notifier({\n        type: 'get',\n        key,\n        value: undefined,\n      });\n    }\n\n    return undefined;\n  }\n\n  public async getMultipleItems(\n    keys: string[],\n    doNotDecrypt?: boolean,\n  ): Promise<Record<string, any>> {\n    await this.#verifyEncryptation();\n    this.#multiple = true;\n    const values = await Promise.all(\n      keys.map((key) => this.getItem(key, doNotDecrypt)),\n    );\n    const result = keys.reduce(\n      (accumulator: Record<string, any>, key, index) => {\n        accumulator[key] = values[index];\n\n        return accumulator;\n      },\n      {},\n    );\n\n    this.#notifier({\n      type: 'getMultiple',\n      key: keys,\n      value: result,\n    });\n\n    this.#multiple = false;\n\n    return result;\n  }\n\n  public removeItem(key: string): void {\n    const storageKey = this.#getKey(key);\n    this.storage.removeItem(storageKey);\n\n    if (!this.#multiple) {\n      this.#notifier({\n        type: 'remove',\n        key,\n      });\n    }\n\n    this.#keys.delete(key);\n  }\n\n  public removeMultipleItems(keys: string[]): void {\n    this.#multiple = true;\n\n    keys.forEach((key) => {\n      this.removeItem(key);\n    });\n\n    this.#notifier({\n      type: 'removeMultiple',\n      key: keys,\n    });\n\n    this.#multiple = false;\n  }\n\n  public removeItemFromPattern(\n    pattern: string,\n    options: RemoveFromPatternOptions = {} as RemoveFromPatternOptions,\n  ): void {\n    const { exact = false } = options;\n    const storageKeys = Object.keys(this.storage);\n    const filteredKeys = storageKeys.filter((key) => {\n      if (exact) {\n        return key === this.#getKey(pattern);\n      }\n\n      if (this.#prefix) {\n        return key.includes(pattern) && key.includes(this.#prefix);\n      }\n\n      return key.includes(pattern);\n    });\n\n    if (this.#notifyHandler) {\n      const keys = filteredKeys.map((key) =>\n        this.#prefix ? key.split(`${this.#prefix}:`)[1] : key,\n      );\n      this.#notifyHandler({\n        type: 'remove',\n        key: keys,\n      });\n    }\n\n    filteredKeys.forEach((key) => {\n      /* istanbul ignore next */\n      this.storage.removeItem(key);\n    });\n  }\n\n  public async getItemFromPattern(\n    pattern: string,\n    options: GetFromPatternOptions = {} as GetFromPatternOptions,\n  ): Promise<Record<string, any> | undefined> {\n    await this.#verifyEncryptation();\n    const { multiple = true, exact = false, doNotDecrypt = false } = options;\n    const decryptValues = this.#doNotEncryptValues || doNotDecrypt;\n    const keys = Object.keys(this.storage).filter((key) => {\n      if (exact) {\n        return key === this.#getKey(pattern);\n      }\n\n      if (this.#prefix) {\n        return key.includes(pattern) && key.includes(this.#prefix);\n      }\n\n      return key.includes(pattern);\n    });\n\n    if (!keys.length) {\n      return undefined;\n    }\n\n    if (!multiple) {\n      const [key] = keys;\n\n      const formattedKey = this.#prefix\n        ? key.replace(`${this.#prefix}:`, '')\n        : key;\n\n      if (this.#notifyHandler) {\n        this.#notifyHandler({\n          type: 'remove',\n          key: formattedKey,\n        });\n      }\n\n      return await this.getItem(formattedKey, decryptValues);\n    }\n\n    const parsedKeys = keys.map((key) => {\n      const formattedKey = this.#prefix\n        ? key.replace(`${this.#prefix}:`, '')\n        : key;\n\n      return formattedKey;\n    });\n\n    const values = await Promise.all(\n      parsedKeys.map((key) => this.getItem(key, decryptValues)),\n    );\n\n    const value = parsedKeys.reduce(\n      (accumulator: Record<string, any>, key, index) => {\n        accumulator[key] = values[index];\n\n        return accumulator;\n      },\n      {},\n    );\n\n    this.#notifier({\n      type: 'get',\n      key: keys,\n      value,\n    });\n\n    return value;\n  }\n\n  public clear(): void {\n    this.storage.clear();\n\n    this.#notifier({\n      type: 'clear',\n    });\n  }\n\n  public key(index: number): string | null {\n    const value = this.storage.key(index) || null;\n\n    this.#notifier({\n      type: 'key',\n      index,\n      value,\n    });\n\n    return value;\n  }\n\n  public async encryptValue(value: any): Promise<string> {\n    await this.#verifyEncryptation();\n    const parsedValue = this.#doNotParseValues ? value : JSON.stringify(value);\n    const encryptedValue = await this.#encryptation.encrypt(parsedValue);\n\n    return encryptedValue;\n  }\n\n  public async decryptValue<DataType = any>(\n    value: string,\n  ): Promise<DataType | null> {\n    await this.#verifyEncryptation();\n    const decryptedValue = await this.#encryptation.decrypt(value);\n\n    try {\n      return (\n        this.#doNotParseValues ? decryptedValue : JSON.parse(decryptedValue)\n      ) as DataType;\n    } catch {\n      /* istanbul ignore next */\n      return null;\n    }\n  }\n\n  public async hash(value: string): Promise<string> {\n    return hashAsyncSHA256(value);\n  }\n\n  /**\n   * TTL API\n   */\n\n  /**\n   * Returns a valid TTL record.\n   *\n   * If the key does not exist, is invalid or has expired,\n   * `Promise<null>` is returned.\n   *\n   * Expired items are automatically removed from storage.\n   *\n   * @template T\n   * @param {string} key Storage key.\n   *\n   * @returns {Promise<TTLStorageValue<T> | null>}\n   *\n   * @private\n   */\n  async #getTTLRecord<T = unknown>(\n    key: string,\n    doNotDecrypt = false,\n  ): Promise<TTLStorageValue<T> | null> {\n    const item = await this.getItem<TTLStorageValue<T>>(key, doNotDecrypt);\n\n    if (!item) {\n      return null;\n    }\n\n    if (\n      item == null ||\n      typeof item !== 'object' ||\n      typeof item.expiresAt !== 'number'\n    ) {\n      return null;\n    }\n\n    if (Date.now() >= item.expiresAt) {\n      this.removeItem(key);\n\n      return null;\n    }\n\n    return item;\n  }\n\n  public async setTTL<T>({\n    key,\n    value,\n    ttl,\n    doNotEncrypt = false,\n  }: SetTTLItemParams<T>): Promise<void> {\n    const expiresAt =\n      ttl instanceof Date ? ttl.getTime() : Date.now() + ttl * 1000;\n\n    const item: TTLStorageValue<T> = {\n      value,\n      expiresAt,\n    };\n\n    await this.setItem(key, item, doNotEncrypt);\n  }\n\n  public async getTTL<T = unknown>(\n    key: string,\n    doNotDecrypt = false,\n  ): Promise<T | null> {\n    const item = await this.#getTTLRecord<T>(key, doNotDecrypt);\n    return item?.value ?? null;\n  }\n\n  public async hasTTL(key: string): Promise<boolean> {\n    const item = await this.#getTTLRecord(key);\n    return item !== null;\n  }\n\n  public async getTTLMetadata(key: string): Promise<TTLMetadata | null> {\n    const item = await this.#getTTLRecord(key);\n\n    if (!item) {\n      return null;\n    }\n\n    return {\n      expiresAt: new Date(item.expiresAt),\n      remaining: (item.expiresAt - Date.now()) / 1000,\n      expired: Date.now() >= item.expiresAt,\n    };\n  }\n\n  public async getRemainingTTL(key: string): Promise<number | null> {\n    const item = await this.#getTTLRecord(key);\n\n    if (!item) {\n      return null;\n    }\n\n    const remaining = (item.expiresAt - Date.now()) / 1000;\n\n    return remaining > 0 ? remaining : 0;\n  }\n\n  public async refreshTTL({ key, ttl }: RefreshTTLParams): Promise<boolean> {\n    const item = await this.#getTTLRecord(key);\n\n    if (!item) {\n      return false;\n    }\n\n    const expiresAt =\n      ttl instanceof Date ? ttl.getTime() : Date.now() + ttl * 1000;\n\n    item.expiresAt = expiresAt;\n\n    await this.setItem(key, item);\n\n    return true;\n  }\n\n  public async removeTTL(key: string): Promise<boolean> {\n    const item = await this.#getTTLRecord(key);\n\n    if (!item) {\n      return false;\n    }\n\n    this.removeItem(key);\n    await this.setItem(key, item.value);\n\n    return true;\n  }\n\n  public async hasExpired(key: string): Promise<boolean> {\n    const item = await this.#getTTLRecord(key);\n\n    return item === null;\n  }\n}\n\n/* v8 ignore start -- @preserve */\nif (typeof window !== 'undefined') {\n  (window as any).EncryptStorageWebApi = EncryptStorageWebApi;\n}\n\nif (typeof window !== 'undefined' && window?.globalThis) {\n  // oxlint-disable-next-line no-unsafe-optional-chaining\n  (window?.globalThis as any).EncryptStorageWebApi = EncryptStorageWebApi;\n}\n/* v8 ignore end -- @preserve */\n"],"mappings":"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"}